diff --git a/admin/PostEditSubmitMetabox.php b/admin/PostEditSubmitMetabox.php deleted file mode 100644 index f3908c92..00000000 --- a/admin/PostEditSubmitMetabox.php +++ /dev/null @@ -1,422 +0,0 @@ -post_type); - $post_status = $post->post_status; - - if ('auto-draft' == $post_status) - $post_status = 'draft'; - - if (!$post_status_obj = get_post_status_object($post_status)) { - $post_status_obj = get_post_status_object('draft'); - } - - // Don't exclude the current status, regardless of other arguments - $_args = ['include_status' => $post_status_obj->name]; - - $post_status_obj = get_post_status_object($post->post_status); - - $moderation_statuses = array($post->post_status => $post_status_obj); - - $can_publish = current_user_can($type_obj->cap->publish_posts); - - $_args = compact('type_obj', 'post_status_obj', 'can_publish', 'moderation_statuses'); - $_args = array_merge($args, $_args); // in case args passed into metabox are needed within static calls in the future - ?> -
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
- -
- - - - -
- post_status)) ? __('Revision Edits: %s', 'revisionary') : __('Revisions: %s'); - - if ($revisions_to_keep > 0 && $revisions_to_keep <= $args['args']['revisions_count']) { - echo ''; - printf($revisions_caption, '' . number_format_i18n($args['args']['revisions_count']) . '+'); - echo ''; - } else { - printf($revisions_caption, '' . number_format_i18n($args['args']['revisions_count']) . ''); - } - ?> - " target="_revision_diff"> -
- - - -
- -
- - - - - -
- -
-
- -
- - -
- ID)) { - if (!EMPTY_TRASH_DAYS) - $delete_text =__('Delete Permanently'); - else - $delete_text =__('Move to Trash'); - ?> - -
- -
- -
-
-
- -
- - - public && !$post_status_obj->private && empty($post_status_obj->moderation) && ('future' != $post_status_obj->name)) : - $draft_label = __('Update Revision', 'revisionary'); - ?> - - moderation) : - if (apply_filters('revisionary_display_save_as_button', true, $post, $args)): - $status_label = (!empty($post_status_obj->labels->save_as)) ? $post_status_obj->labels->save_as : sprintf(__('Save as %s'), $post_status_obj->label); - ?> - - - - - - - - - post_status)) { - $preview_link = rvy_preview_url($post); - - $type_obj = get_post_type_object($post->post_type); - - $can_publish = agp_user_can('edit_post', rvy_post_id($post->ID), '', ['skip_revision_allowance' => true]); - - if ($type_obj && empty($type_obj->public)) { - return; - } elseif ($can_publish) { - $preview_button = ('future-revision' == $post->post_status) ? __('View / Publish', 'revisionary') : __('View / Approve', 'revisionary'); - $preview_title = __('View / moderate saved revision', 'revisionary'); - } else { - $preview_button = __('View'); - $preview_title = __('View saved revision', 'revisionary'); - } - ?> - - - post_edit_ui, 'fltPreviewLink']); - $preview_link = add_query_arg('rvy', 1, esc_url( get_preview_post_link( $post ))); - $preview_button =__('Preview Changes'); - $style = ($is_revision) ? 'style="display:none;"' : ''; - - global $wp_version; - ?> - > - - post_edit_ui, 'fltPreviewLink']); - } - - /** - * Classic Editor Post Submit Metabox: Post Status Dropdown HTML - */ - public static function post_status_display($post, $args) - { - $defaults = ['post_status_obj' => false, 'can_publish' => false, 'moderation_statuses' => []]; - $args = array_merge($defaults, $args); - foreach (array_keys($defaults) as $var) { - $$var = $args[$var]; - } - - ?> - - name; - $status_label = (!empty($post_status_obj->labels->caption)) ? $post_status_obj->labels->caption : $post_status_obj->label; - ?> - - private) - echo(PWP::__wp('Privately Published')); - elseif ($post_status_obj->public) - echo(PWP::__wp('Published')); - elseif (!empty($post_status_obj->labels->caption)) - echo $post_status_obj->labels->caption; - else - echo $post_status_obj->label; - ?> -   - 1 || ($post_status != key($moderation_statuses))); - - if ($post_status_obj->public || $post_status_obj->private || $can_publish || $select_moderation) { ?> - private || ($post_status_obj->public && 'publish' != $post_status)) { ?>style="display:none;" - class="edit-post-status hide-if-no-js" tabindex='4'> - -
- - - - -
- - false, 'post_status_obj' => false, 'can_publish' => false]; - $args = array_merge($defaults, $args); - foreach (array_keys($defaults) as $var) { - $$var = $args[$var]; - } - - echo __('Visibility:', 'revisionary'); ?> - name) { // indicate eventual visibility of scheduled post - if (!$vis_status = get_post_meta($post->ID, '_scheduled_status', true)) - $vis_status = 'publish'; - - $vis_status_obj = get_post_status_object($vis_status); - } else { - $vis_status = $post_status_obj->name; - $vis_status_obj = $post_status_obj; - } - - if ('publish' == $vis_status) { - $post->post_password = ''; - $visibility = 'public'; - - if (('post' == $post->post_type || post_type_supports($post->post_type, 'sticky')) && is_sticky($post->ID)) { - $visibility_trans =__('Public, Sticky'); - } else { - $visibility_trans =__('Public'); - } - } elseif ($vis_status_obj->public) { - $post->post_password = ''; - $visibility = $vis_status; - - if (('post' == $post->post_type || post_type_supports($post->post_type, 'sticky')) && is_sticky($post->ID)) { - $visibility_trans = sprintf(__('%s, Sticky'), $vis_status_obj->label); - } else { - $visibility_trans = $vis_status_obj->labels->visibility; - } - } else { - $visibility = 'public'; - $visibility_trans =__('Public'); - } - - echo esc_html($visibility_trans); ?> - - - - - -
- - - /> -
- -

- - -

-
- - - ID) { - $published_stati = get_post_stati(['public' => true, 'private' => true], 'names', 'or'); - - if ('future' == $post_status_obj->name) { // scheduled for publishing at a future date - $stamp =__('Scheduled for: %s'); - } elseif (in_array($post_status_obj->name, $published_stati)) { // already published - $stamp =__('Published on: %s'); - } elseif ('0000-00-00 00:00:00' == $post->post_date_gmt) { // draft, 1 or more saves, no date specified - $stamp =__('Publish immediately'); - } elseif (time() < strtotime($post->post_date_gmt . ' +0000')) { // draft, 1 or more saves, future date specified - $stamp =__('Schedule for: %s'); - } else { // draft, 1 or more saves, date specified - $stamp =__('Publish on: %s'); - } - $date = '' . date_i18n($datef, strtotime($post->post_date)) . ''; - } else { // draft (no saves, and thus no date specified) - $stamp =__('Publish immediately'); - $date = date_i18n($datef, strtotime(current_time('mysql'))); - } - printf($stamp, $date); ?> - -
- false, 'can_publish' => false, 'moderation_statuses' => []]; - $args = array_merge($defaults, $args); - foreach (array_keys($defaults) as $var) { - $$var = $args[$var]; - } - ?> - - - public && !$post_status_obj->private && ('future' != $post_status_obj->name))) { - $status_obj = $post_status_obj; - - if (!empty($status_obj->public) || !empty($status_obj->private)) : - if (!empty($post->post_date_gmt) && time() < strtotime($post->post_date_gmt . ' +0000')) : - $future_status_obj = get_post_status_object('future'); - ?> - - - - - - name . '" />'; - ?> - - - - - - post_type); + $post_status = $post->post_mime_type; + + $post_status_obj = get_post_status_object($post_status); + + $can_publish = current_user_can($type_obj->cap->publish_posts); + + $_args = compact('type_obj', 'post_status_obj', 'can_publish'); + $_args = array_merge($args, $_args); // in case args passed into metabox are needed within static calls in the future + ?> +
+ +
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+ + +
+ +
+ + + + + +
+ +
+
+ +
+ + +
+ ID)) { + if (!EMPTY_TRASH_DAYS) + $delete_text =__('Delete Permanently'); + else + $delete_text =__('Move to Trash'); + ?> + +
+ +
+
+ +
+ + post_mime_type, 'update')) { + $draft_label = pp_revisions_label('update_revision'); + } + ?> + + + + + post_type); + + $can_publish = current_user_can('edit_post', rvy_post_id($post->ID)); + + if ($type_obj && empty($type_obj->public)) { + return; + } elseif ($can_publish) { + //$preview_button = ('future-revision' == $post->post_mime_type) ? __('View / Publish', 'revisionary') : __('Preview / Approve', 'revisionary'); + $preview_button = __('Preview', 'revisionary'); + $preview_title = __('View / moderate saved revision', 'revisionary'); + } else { + $preview_button = __('Preview', 'revisionary'); + $preview_title = __('View saved revision', 'revisionary'); + } + ?> + + + false]; + $args = array_merge($defaults, $args); + foreach (array_keys($defaults) as $var) { + $$var = $args[$var]; + } + + ?> + + labels->caption)) ? $post_status_obj->labels->caption : $post_status_obj->label; + ?> + + +   + + + + + + true, 'private' => true], 'names', 'or'); + + if ('future-revision' == $post_status_obj->name) { // scheduled for publishing at a future date + $stamp =__('Scheduled for: %s'); + + } elseif (strtotime($post->post_date_gmt) > agp_time_gmt()) { + $stamp =__('Publish on: %s'); + + } else { + $stamp = __('Publish on approval', 'revisionary'); + } + + $date = '' . date_i18n($datef, strtotime($post->post_date)) . ''; + + printf($stamp, $date); ?> + +
+ enabled_post_types); + $post_types_csv = implode( "','", $types ); + $clauses['where'] = str_replace( "$wpdb->posts.post_type = 'post'", "$wpdb->posts.post_type IN ('$post_types_csv')", $clauses['where'] ); + + remove_filter('posts_clauses_request', [&$this, 'fltDashboardQueryClauses']); + return $clauses; + } + + public static function glancePending() { return; - global $revisionary; + // @todo: modify this function for post_mime_type schema + + /* + if ( ( defined( 'SCOPER_VERSION' ) || defined( 'PP_VERSION' ) || defined( 'PPCE_VERSION' ) || defined( 'RVY_CONTENT_ROLES' ) ) && ! defined( 'USE_RVY_RIGHTNOW' ) ) + return; + + global $revisionary; - foreach (array_keys($revisionary->enabled_post_types) as $post_type) { - $cache_key = _count_posts_cache_key( $post_type ); - wp_cache_delete( $cache_key, 'counts' ); + foreach (array_keys($revisionary->enabled_post_types) as $post_type) { + $cache_key = _count_posts_cache_key( $post_type ); + wp_cache_delete( $cache_key, 'counts' ); - if ( $num_posts = wp_count_posts( $post_type ) ) { // @todo: PressPermit compat for count_posts filtering with revision statuses + if ( $num_posts = wp_count_posts( $post_type ) ) { // @todo: PressPermit compat for count_posts filtering with revision statuses - foreach( array( 'pending-revision', 'future-revision' ) as $status ) { - if ( ! empty($num_posts->$status) ) { - $post_type_obj = get_post_type_object($post_type); - $status_obj = get_post_status_object($status); + foreach( array( 'pending-revision', 'future-revision' ) as $status ) { + if ( ! empty($num_posts->$status) ) { + $post_type_obj = get_post_type_object($post_type); + $status_obj = get_post_status_object($status); - echo '
'; - - $num = number_format_i18n( $num_posts->$status ); + echo '
'; + + $num = number_format_i18n( $num_posts->$status ); - $status_label = str_replace('(%s)', '', reset($status_obj->label_count)); + $status_label = str_replace('(%s)', '', reset($status_obj->label_count)); - if ( intval($num_posts->$status) <= 1 ) - $text = sprintf( __('%1$s %2$s Revision', 'revisionary'), $status_label, $post_type_obj->labels->singular_name); - else - $text = sprintf( __('%1$s %2$s Revisions', 'revisionary'), $status_label, $post_type_obj->labels->singular_name); - - $url = "admin.php?page=revisionary-q&post_status=$status&post_type=$post_type"; + if ( intval($num_posts->$status) <= 1 ) + $text = sprintf( __('%1$s %2$s Revision', 'revisionary'), $status_label, $post_type_obj->labels->singular_name); + else + $text = sprintf( __('%1$s %2$s Revisions', 'revisionary'), $status_label, $post_type_obj->labels->singular_name); + + $url = "admin.php?page=revisionary-q&post_status=$status&post_type=$post_type"; - if (current_user_can('administrator') || (isset($post_type_obj->cap->edit_published_posts) && current_user_can($post_type_obj->cap->edit_published_posts) && current_user_can($post_type_obj->cap->edit_others_posts))) { // hide count from non-Admins until it is properly filtered - echo "$num $text"; - } else { - echo "" . sprintf( __("View %s", 'revisionary'), $text) . ""; + if (current_user_can('administrator') || (isset($post_type_obj->cap->edit_published_posts) && current_user_can($post_type_obj->cap->edit_published_posts) && current_user_can($post_type_obj->cap->edit_others_posts))) { // hide count from non-Admins until it is properly filtered + echo "$num $text"; + } else { + echo "" . sprintf( __("View %s", 'revisionary'), $text) . ""; + } + + echo "
"; } - - echo "
"; } } } + */ } } diff --git a/admin/admin-init_rvy.php b/admin/admin-init_rvy.php index 6303e5dd..5af15dad 100644 --- a/admin/admin-init_rvy.php +++ b/admin/admin-init_rvy.php @@ -3,13 +3,13 @@ add_action( 'init', '_rvy_post_edit_ui' ); -if (defined('REVISIONARY_PRO_VERSION')) { +if (defined('PUBLISHPRESS_REVISIONS_PRO_VERSION')) { require_once(RVY_ABSPATH . '/includes-pro/admin-load.php'); new RevisionaryProAdmin(); } if ( in_array( $pagenow, array( 'edit.php', 'post.php', 'post-new.php', 'plugins.php' ) ) ) { - add_action( 'all_admin_notices', '_rvy_intro_notice' ); + //add_action( 'all_admin_notices', '_rvy_intro_notice' ); // @todo: updated welcome message / screen if (get_site_transient('_revisionary_1x_migration')) { add_action( 'all_admin_notices', '_rvy_migration_notice' ); @@ -19,15 +19,20 @@ function _rvy_post_edit_ui() { global $pagenow, $revisionary; - if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) ) { - if ( $pagenow == 'post.php' ) { - require_once( dirname(__FILE__).'/post-edit_rvy.php' ); - $revisionary->post_edit_ui = new RvyPostEdit(); - } + if (in_array($pagenow, ['post.php', 'post-new.php'])) { + if ($pagenow == 'post.php') { + require_once( dirname(__FILE__).'/post-editor-workflow-ui_rvy.php' ); - if ($revisionary->isBlockEditorActive()) { - require_once( dirname(__FILE__).'/post-edit-block-ui_rvy.php' ); + if (\PublishPress\Revisions\Utils::isBlockEditorActive()) { + require_once( dirname(__FILE__).'/post-edit-block-ui_rvy.php' ); + } else { + require_once( dirname(__FILE__).'/post-edit_rvy.php' ); + $revisionary->post_edit_ui = new RvyPostEdit(); + } } + } elseif ('edit.php' == $pagenow) { + require_once( dirname(__FILE__).'/admin-posts_rvy.php' ); + new RevisionaryAdminPosts(); } } @@ -41,6 +46,8 @@ function rvy_load_textdomain() { } function rvy_admin_init() { + rvy_load_textdomain(); + // @todo: clean up "Restore Revision" URL on Diff screen if (!empty($_GET['amp;revision']) && !empty($_GET['amp;action']) && !empty($_GET['amp;_wpnonce'])) { $_GET['revision'] = $_GET['amp;revision']; @@ -71,14 +78,18 @@ function rvy_admin_init() { check_admin_referer('bulk-revision-queue'); - $sendback = remove_query_arg( array('trashed', 'untrashed', 'approved_count', 'published_count', 'deleted', 'locked', 'ids', 'posts', '_wp_nonce', '_wp_http_referer'), wp_get_referer() ); + if (!$url = str_replace('#038;', '&', wp_get_referer())) { + $url = admin_url("admin.php?page=revisionary-q"); + } + + $sendback = remove_query_arg( array('trashed', 'untrashed', 'submitted_count', 'approved_count', 'published_count', 'deleted', 'locked', 'ids', 'posts', '_wp_nonce', '_wp_http_referer'), $url); if ( 'delete_all' == $doaction ) { // Prepare for deletion of all posts with a specified post status (i.e. Empty trash). $post_status = preg_replace('/[^a-z0-9_-]+/i', '', sanitize_key($_REQUEST['post_status'])); // Verify the post status exists. if ( get_post_status_object( $post_status ) ) { - $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type=%s AND post_status = %s", $post_type, $post_status ) ); + $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type=%s AND post_mime_type = %s", $post_type, $post_status ) ); } $doaction = 'delete'; } elseif ( isset( $_REQUEST['media'] ) ) { @@ -106,13 +117,11 @@ function rvy_admin_init() { continue; } - if (!rvy_is_revision_status($revision->post_status)) { + if (!rvy_in_revision_workflow($revision)) { continue; } - if ( !$is_administrator - && !agp_user_can('edit_post', rvy_post_id($revision->ID), '', ['skip_revision_allowance' => true]) - ) { + if (!$is_administrator && !current_user_can('edit_post', rvy_post_id($revision->ID))) { if (count($post_ids) == 1) { wp_die( __('Sorry, you are not allowed to approve this revision.', 'revisionary') ); } else { @@ -120,7 +129,7 @@ function rvy_admin_init() { } } - if (('future-revision' == $revision->post_status) && ('publish_revision' == $doaction)) { + if (('future-revision' == $revision->post_mime_type) && ('publish_revision' == $doaction)) { if (rvy_revision_publish($revision->ID)) { $approved++; } @@ -138,6 +147,41 @@ function rvy_admin_init() { break; + case 'submit_revision' : + $submitted = 0; + $is_administrator = current_user_can('administrator'); + + require_once( dirname(__FILE__).'/revision-action_rvy.php'); + + foreach ((array) $post_ids as $post_id) { + if (!$revision = get_post($post_id)) { + continue; + } + + if ('draft' != $revision->post_status) { + continue; + } + + if (!$is_administrator && !current_user_can('set_revision_pending-revision', $revision->ID)) { + if (count($post_ids) == 1) { + wp_die( __('Sorry, you are not allowed to submit this revision.', 'revisionary') ); + } else { + continue; + } + } + + if (rvy_revision_submit($revision->ID)) { + $submitted++; + } + } + + if ($submitted) { + $arg = 'submitted_count'; + $sendback = add_query_arg($arg, $submitted, $sendback); + } + + break; + case 'unschedule_revision' : $unscheduled = 0; $is_administrator = current_user_can('administrator'); @@ -149,13 +193,11 @@ function rvy_admin_init() { continue; } - if ('future-revision' != $revision->post_status) { + if ('future-revision' != $revision->post_mime_type) { continue; } - if ( !$is_administrator - && !agp_user_can('edit_post', rvy_post_id($revision->ID), '', ['skip_revision_allowance' => true]) - ) { + if (!$is_administrator && !current_user_can('edit_post', rvy_post_id($revision->ID))) { if (count($post_ids) == 1) { wp_die( __('Sorry, you are not allowed to approve this revision.', 'revisionary') ); } else { @@ -181,11 +223,11 @@ function rvy_admin_init() { if ( ! $revision = get_post($post_id) ) continue; - if ( ! rvy_is_revision_status($revision->post_status) ) + if ( ! rvy_in_revision_workflow($revision) ) continue; if ( ! current_user_can('administrator') && ! current_user_can( 'delete_post', rvy_post_id($revision->ID) ) ) { // @todo: review Administrator cap check - if (('pending-revision' != $revision->post_status) || !rvy_is_post_author($revision)) { // allow submitters to delete their own still-pending revisions + if (!in_array($revision->post_mime_type, ['draft-revision', 'pending-revision']) || !rvy_is_post_author($revision)) { // allow submitters to delete their own still-pending revisions wp_die( __('Sorry, you are not allowed to delete this revision.', 'revisionary') ); } } @@ -204,7 +246,7 @@ function rvy_admin_init() { } if ($sendback) { - $sendback = remove_query_arg( array('action', 'action2', '_wp_http_referer', '_wpnonce', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view'), $sendback ); + $sendback = remove_query_arg( array('action', 'action2', '_wp_http_referer', '_wpnonce', 'deleted', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view'), $sendback ); $sendback = str_replace('#038;', '&', $sendback); // @todo Proper decode wp_redirect($sendback); } @@ -220,6 +262,14 @@ function rvy_admin_init() { require_once( dirname(__FILE__).'/revision-action_rvy.php'); add_action( 'wp_loaded', 'rvy_revision_delete' ); + } elseif ( ! empty($_GET['action']) && ('revise' == $_GET['action']) ) { + require_once( dirname(__FILE__).'/revision-action_rvy.php'); + add_action( 'wp_loaded', 'rvy_revision_create' ); + + } elseif ( ! empty($_GET['action']) && ('submit' == $_GET['action']) ) { + require_once( dirname(__FILE__).'/revision-action_rvy.php'); + add_action( 'wp_loaded', 'rvy_revision_submit' ); + } elseif ( ! empty($_GET['action']) && ('approve' == $_GET['action']) ) { require_once( dirname(__FILE__).'/revision-action_rvy.php'); add_action( 'wp_loaded', 'rvy_revision_approve' ); @@ -238,17 +288,17 @@ function rvy_admin_init() { $revision_id = (!empty($_REQUEST['revision'])) ? (int) $_REQUEST['revision'] : $_REQUEST['to']; - if (('modified' == rvy_get_option('past_revisions_order_by')) && !rvy_is_revision_status(get_post_field('post_status', $revision_id))) { + if (('modified' == rvy_get_option('past_revisions_order_by')) && !rvy_in_revision_workflow($revision_id)) { require_once(dirname(__FILE__).'/history_rvy.php'); add_filter('query', ['RevisionaryHistory', 'fltOrderRevisionsByModified']); } } - if (defined('REVISIONARY_PRO_VERSION') && !empty($_REQUEST['rvy_ajax_settings'])) { + if (defined('PUBLISHPRESS_REVISIONS_PRO_VERSION') && !empty($_REQUEST['rvy_ajax_settings'])) { include_once(RVY_ABSPATH . '/includes-pro/pro-activation-ajax.php'); } - if (defined('REVISIONARY_PRO_VERSION') && !empty($_REQUEST['rvy_refresh_updates'])) { + if (defined('PUBLISHPRESS_REVISIONS_PRO_VERSION') && !empty($_REQUEST['rvy_refresh_updates'])) { do_action('revisionary_refresh_updates'); } @@ -261,7 +311,7 @@ function rvy_admin_init() { } function rvy_intro_message($abbreviated = false) { - + /* $guide_link = sprintf( __('For more details on setting up PublishPress Revisions, %sread this guide%s.', 'revisionary'), '', @@ -275,11 +325,12 @@ function rvy_intro_message($abbreviated = false) { $guide_link, '

' ); + */ } function rvy_migration_message() { return sprintf( - __('Revisionary is now PublishPress Revisions! Note the new Revisions menu and %sRevision Queue%s screen, where Pending and Scheduled Revisions are listed. %s', 'revisionary'), + __('Revisionary is now PublishPress Revisions! Note the new Revisions menu and %sRevision Queue%s screen, where Revisions are listed. %s', 'revisionary'), '
', '', '
' . rvy_intro_message(true) . '
' @@ -287,9 +338,11 @@ function rvy_migration_message() { } function _rvy_intro_notice() { + /* if ( current_user_can( 'edit_users') ) { rvy_dismissable_notice( 'intro_revisor_role', rvy_intro_message()); } + */ } function _rvy_migration_notice() { @@ -317,7 +370,7 @@ function RvyDismissNotice(){ endif; } -function rvy_get_post_revisions($post_id, $status = 'inherit', $args = '' ) { +function rvy_get_post_revisions($post_id, $status = '', $args = '' ) { global $wpdb; $defaults = array( 'order' => 'DESC', 'orderby' => 'post_modified_gmt', 'use_memcache' => true, 'fields' => COLS_ALL_RVY, 'return_flipped' => false ); @@ -327,11 +380,15 @@ function rvy_get_post_revisions($post_id, $status = 'inherit', $args = '' ) { $$var = ( isset( $args[$var] ) ) ? $args[$var] : $defaults[$var]; } - if (!in_array( - $status, - array_merge(rvy_revision_statuses(), array('inherit')) - ) ) { - return []; + if (!$status) { + $all_rev_statuses_clause = " AND (post_mime_type = 'draft-revision' OR post_mime_type = 'pending-revision' OR post_mime_type = 'future-revision')"; + } else { + if (!in_array( + $status, + array_merge(rvy_revision_statuses(), array('inherit')) + ) ) { + return []; + } } if ( COL_ID_RVY == $fields ) { @@ -355,15 +412,26 @@ function rvy_get_post_revisions($post_id, $status = 'inherit', $args = '' ) { ) ); } else { - $revisions = $wpdb->get_col( - $wpdb->prepare( - "SELECT ID FROM $wpdb->posts " - . " INNER JOIN $wpdb->postmeta pm_published ON $wpdb->posts.ID = pm_published.post_id AND pm_published.meta_key = '_rvy_base_post_id'" - . " WHERE pm_published.meta_value = %s AND post_status = %s", - $post_id, - $status - ) - ); + if (!empty($all_rev_statuses_clause)) { + $revisions = $wpdb->get_col( + $wpdb->prepare( + "SELECT ID FROM $wpdb->posts " + . " INNER JOIN $wpdb->postmeta pm_published ON $wpdb->posts.ID = pm_published.post_id AND pm_published.meta_key = '_rvy_base_post_id'" + . " WHERE pm_published.meta_value = %s $all_rev_statuses_clause", + $post_id + ) + ); + } else { + $revisions = $wpdb->get_col( + $wpdb->prepare( + "SELECT ID FROM $wpdb->posts " + . " INNER JOIN $wpdb->postmeta pm_published ON $wpdb->posts.ID = pm_published.post_id AND pm_published.meta_key = '_rvy_base_post_id'" + . " WHERE pm_published.meta_value = %s AND post_mime_type = %s", + $post_id, + $status + ) + ); + } } if ( $return_flipped ) @@ -388,15 +456,34 @@ function rvy_get_post_revisions($post_id, $status = 'inherit', $args = '' ) { ) ); } else { - $revisions = $wpdb->get_results( - $wpdb->prepare( - "SELECT * FROM $wpdb->posts " - . " INNER JOIN $wpdb->postmeta pm_published ON $wpdb->posts.ID = pm_published.post_id AND pm_published.meta_key = '_rvy_base_post_id'" - . " WHERE pm_published.meta_value = %d AND post_status = %s $order_clause", - $post_id, - $status - ) - ); + if (!empty($all_rev_statuses_clause)) { + + $test = $wpdb->prepare( + "SELECT * FROM $wpdb->posts " + . " INNER JOIN $wpdb->postmeta pm_published ON $wpdb->posts.ID = pm_published.post_id AND pm_published.meta_key = '_rvy_base_post_id'" + . " WHERE pm_published.meta_value = %d $all_rev_statuses_clause $order_clause", + $post_id + ); + + $revisions = $wpdb->get_results( + $wpdb->prepare( + "SELECT * FROM $wpdb->posts " + . " INNER JOIN $wpdb->postmeta pm_published ON $wpdb->posts.ID = pm_published.post_id AND pm_published.meta_key = '_rvy_base_post_id'" + . " WHERE pm_published.meta_value = %d $all_rev_statuses_clause $order_clause", + $post_id + ) + ); + } else { + $revisions = $wpdb->get_results( + $wpdb->prepare( + "SELECT * FROM $wpdb->posts " + . " INNER JOIN $wpdb->postmeta pm_published ON $wpdb->posts.ID = pm_published.post_id AND pm_published.meta_key = '_rvy_base_post_id'" + . " WHERE pm_published.meta_value = %d AND post_mime_type = %s $order_clause", + $post_id, + $status + ) + ); + } } } diff --git a/admin/admin-plugins_rvy.php b/admin/admin-plugins_rvy.php deleted file mode 100644 index 3daf486a..00000000 --- a/admin/admin-plugins_rvy.php +++ /dev/null @@ -1,15 +0,0 @@ -" . _pp_('Settings') . ""; - } - - return $links; - } -} // end class diff --git a/admin/admin-posts_rvy.php b/admin/admin-posts_rvy.php new file mode 100644 index 00000000..98148f51 --- /dev/null +++ b/admin/admin-posts_rvy.php @@ -0,0 +1,224 @@ + +
+
+ posts ) ) { + foreach ($wp_query->posts as $row) { + $listed_ids[] = $row->ID; + } + } + + if ($listed_ids) { + $id_csv = "'" . implode("','", array_map('intval', $listed_ids)) . "'"; + $revision_base_status_csv = rvy_revision_base_statuses(['return' => 'csv']); + $revision_status_csv = rvy_revision_statuses(['return' => 'csv']); + + $results = $wpdb->get_results( + "SELECT comment_count AS published_post, COUNT(comment_count) AS num_revisions FROM $wpdb->posts WHERE comment_count IN ($id_csv) AND post_status IN ($revision_base_status_csv) AND post_mime_type IN ($revision_status_csv) GROUP BY comment_count" + ); + + foreach($results as $row) { + $this->post_revision_count[$row->published_post] = $row->num_revisions; + } + } + } + + private function logTrashedRevisions() { + global $wpdb, $wp_query; + + if (!empty($wp_query) && !empty($wp_query->posts)) { + $listed_ids = []; + + foreach($wp_query->posts AS $row) { + $listed_ids []= $row->ID; + } + + $listed_post_csv = implode("','", array_map('intval', $listed_ids)); + $this->trashed_revisions = $wpdb->get_col("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_rvy_base_post_id' AND post_id IN ('$listed_post_csv')"); + } else { + $this->trashed_revisions = []; + } + } + + /** + * Adds "Pending Revision" or "Scheduled Revision" to the list of display states for trashed revisions in the Posts list table. + * + * @param array $post_states An array of post display states. + * @param WP_Post $post The current post object. + * @return array Filtered array of post display states. + */ + public function fltTrashedPostState($post_states, $post) { + if (!$post->comment_count) { // revisions buffer base post id to comment_count column for perf + return $post_states; + } + + if (!isset($this->trashed_revisions)) { + $this->logTrashedRevisions(); + } + + if (in_array($post->ID, $this->trashed_revisions)) { + if ($status_obj = get_post_status_object($post->post_mime_type)) { + $post_states['rvy_revision'] = $status_obj->label; + } + + if (!isset($post_states['rvy_revision'])) { + $post_states['rvy_revision'] = __('Revision', 'revisionary'); + } + } + + return $post_states; + } + + function fltCommentsNumber($comment_count, $post_id) { + if (isset($this->trashed_revisions) && in_array($post_id, $this->trashed_revisions)) { + $comment_count = 0; + } + + return $comment_count; + } + + function flt_display_post_states($post_states, $post) { + if (!empty($this->post_revision_count[$post->ID]) && !defined('REVISIONARY_SUPPRESS_POST_STATE_DISPLAY')) { + $post_states []= __('Has Revision', 'revisionary'); + } + + return $post_states; + } + + function revisions_row_action_link($actions = array()) { + global $post; + + if (!empty($post) && !rvy_is_supported_post_type($post->post_type)) { + return $actions; + } + + if (!empty($this->post_revision_count[$post->ID])) { + if ( 'trash' != $post->post_status && wp_check_post_lock( $post->ID ) === false ) { + $actions['revision_queue'] = "" . __('Revision Queue', 'revisionary') . ''; + } + } + + $status_obj = get_post_status_object($post->post_status); + + if (empty($actions['view'])) { + + } + + if (!empty($status_obj->public) || !empty($status_obj->private) || rvy_get_option('pending_revision_unpublished')) { + if (current_user_can('copy_post', $post->ID)) { + $redirect_arg = ( ! empty($_REQUEST['rvy_redirect']) ) ? "&rvy_redirect=" . esc_url($_REQUEST['rvy_redirect']) : ''; + //$url = wp_nonce_url(rvy_admin_url("admin.php?page=rvy-revisions&post={$post->ID}&action=revise$redirect_arg"), "submit-post_{$post->ID}" ); + $url = rvy_admin_url("admin.php?page=rvy-revisions&post={$post->ID}&action=revise$redirect_arg"); + + $caption = (isset($actions['edit']) || !rvy_get_option('caption_copy_as_edit')) ? pp_revisions_status_label('draft-revision', 'submit') : __('Edit'); + + $caption = str_replace(' ', ' ', $caption); + + $actions['create_revision'] = "" . $caption . ''; + } + } + + return $actions; + } + + public function fltPostCountQuery($query) + { + global $wpdb; + + $posts = $wpdb->posts; + + $matches = []; + + // wp_count_posts() : + // SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s + + /* + SELECT COUNT( 1 ) + FROM $wpdb->posts + WHERE post_type = %s + AND post_status NOT IN ( '" . implode( "','", $exclude_states ) . "' ) + AND post_author = %d + */ + + $pos_from = strpos($query, "FROM $posts"); + $pos_where = strpos($query, "WHERE "); + + // @todo: use 'wp_count_posts' filter instead? + + if ((strpos($query, "ELECT post_status, COUNT( * ) AS num_posts ") || (strpos($query, "ELECT COUNT( 1 )") && $pos_from && (!$pos_where || ($pos_from < $pos_where)))) + && preg_match("/FROM\s*{$posts}\s*WHERE post_type\s*=\s*'([^ ]+)'/", $query, $matches) + ) { + $_post_type = (!empty($matches[1])) ? $matches[1] : PWP::findPostType(); + + if ($_post_type) { + $revision_status_csv = rvy_revision_statuses(['return' => 'csv']); + + if (!function_exists('presspermit')) { + // avoid counting posts stored with a status that's no longer registered + $statuses = get_post_stati(); + $statuses_clause = " AND post_status IN ('" . implode("','", $statuses) . "')"; + } else { + $statuses_clause = ''; + } + + if (!strpos($query, "AND post_mime_type NOT IN ($revision_status_csv)")) { + $query = str_replace( + " post_type = '{$matches[1]}'", + "( post_type = '{$matches[1]}' AND post_mime_type NOT IN ($revision_status_csv){$statuses_clause} )", + $query + ); + } + } + } + + return $query; + } +} diff --git a/admin/admin_lib-mu_rvy.php b/admin/admin_lib-mu_rvy.php index 200c496d..cc906080 100644 --- a/admin/admin_lib-mu_rvy.php +++ b/admin/admin_lib-mu_rvy.php @@ -4,8 +4,6 @@ function rvy_mu_site_menu() { if ( ! current_user_can( 'manage_options' ) ) return; - $path = RVY_ABSPATH; - // WP MU site options if ( awp_is_mu() ) { // Network-Wide Settings diff --git a/admin/admin_rvy.php b/admin/admin_rvy.php index 75720f31..a01a10f4 100644 --- a/admin/admin_rvy.php +++ b/admin/admin_rvy.php @@ -2,13 +2,15 @@ /** * @package PublishPress\Revisions\RevisionaryAdmin * @author PublishPress - * @copyright Copyright (c) 2019 PublishPress. All rights reserved. + * @copyright Copyright (c) 2021 PublishPress. All rights reserved. * @license GPLv2 or later * @since 1.0.0 + * + * Scripts and filter / action handlers applicable for all wp-admin URLs + * + * Selectively load other classes based on URL */ -// @todo: separate out functions specific to Classic Editor - if( basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']) ) die(); @@ -16,78 +18,28 @@ class RevisionaryAdmin { - var $revision_save_in_progress; - private $post_revision_count = array(); - private $hide_quickedit = array(); - private $trashed_revisions; - function __construct() { global $pagenow, $post; $script_name = $_SERVER['SCRIPT_NAME']; - $request_uri = esc_url($_SERVER['REQUEST_URI']); - - add_action('admin_head', array(&$this, 'admin_head')); - add_action('admin_enqueue_scripts', array(&$this, 'admin_scripts')); - add_action('admin_print_scripts', [$this, 'admin_print_scripts'], 99); + + add_action('admin_head', [$this, 'admin_head']); + add_action('admin_enqueue_scripts', [$this, 'admin_scripts']); + add_action('revisionary_admin_footer', [$this, 'publishpressFooter']); if ( ! defined('XMLRPC_REQUEST') && ! strpos($script_name, 'p-admin/async-upload.php' ) ) { - global $blog_id; - if ( RVY_NETWORK && ( is_main_site($blog_id) ) ) { + if ( RVY_NETWORK && ( is_main_site() ) ) { require_once( dirname(__FILE__).'/admin_lib-mu_rvy.php' ); add_action('admin_menu', 'rvy_mu_site_menu', 15 ); } - - add_action('admin_menu', array(&$this,'build_menu')); - - if ( strpos($script_name, 'p-admin/plugins.php') ) { - add_filter( 'plugin_row_meta', array(&$this, 'flt_plugin_action_links'), 10, 2 ); - } - } - - add_action('admin_footer-edit.php', array(&$this, 'act_hide_quickedit') ); - add_action('admin_footer-edit-pages.php', array(&$this, 'act_hide_quickedit') ); - - add_action('admin_head', array(&$this, 'add_editor_ui') ); - add_action('admin_head', array(&$this, 'act_hide_admin_divs') ); - - if ( ! ( defined( 'SCOPER_VERSION' ) || defined( 'PP_VERSION' ) || defined( 'PPCE_VERSION' ) ) || defined( 'USE_RVY_RIGHTNOW' ) ) { - require_once( 'admin-dashboard_rvy.php' ); - } - - // log this action so we know when to ignore the save_post action - add_action('inherit_revision', array(&$this, 'act_log_revision_save') ); - - add_filter('pre_post_status', array(&$this, 'flt_detect_revision_save'), 50 ); - - if ( rvy_get_option( 'pending_revisions' ) ) { - if ( strpos( $script_name, 'p-admin/edit.php') - || strpos( $script_name, 'p-admin/edit-pages.php') - || ( strpos( $script_name, 'p-admin/post.php') ) - || ( strpos( $script_name, 'p-admin/page.php') ) - || false !== strpos( urldecode($request_uri), 'admin.php?page=rvy-revisions') - || false !== strpos( urldecode($_SERVER['REQUEST_URI']), 'admin.php?page=revisionary-q') - ) { - - if ( false === strpos( urldecode($_SERVER['REQUEST_URI']), 'admin.php?page=revisionary-q') ) { - add_filter( 'the_title', array(&$this, 'flt_post_title'), 10, 2 ); - } - add_filter( 'get_delete_post_link', array(&$this, 'flt_delete_post_link'), 10, 2 ); - } - } + add_action('admin_menu', [$this, 'build_menu']); - if ( rvy_get_option( 'pending_revisions' ) || rvy_get_option( 'scheduled_revisions' ) ) { - if ('revision.php' == $pagenow) { - require_once( dirname(__FILE__).'/history_rvy.php' ); - new RevisionaryHistory(); + if ( strpos($script_name, 'p-admin/plugins.php') ) { + add_filter( 'plugin_row_meta', [$this, 'flt_plugin_action_links'], 10, 2 ); } } - if ( rvy_get_option( 'scheduled_revisions' ) ) { - add_filter( 'dashboard_recent_posts_query_args', array(&$this, 'flt_dashboard_recent_posts_query_args' ) ); - } - // ===== Special early exit if this is a plugin install script if ( strpos($script_name, 'p-admin/plugins.php') || strpos($script_name, 'p-admin/plugin-install.php') || strpos($script_name, 'p-admin/plugin-editor.php') ) { if (strpos($script_name, 'p-admin/plugin-install.php') && !empty($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], '=rvy')) { @@ -95,595 +47,97 @@ function __construct() { echo ''; }); } - - return; // no further filtering on WP plugin maintenance scripts - } - - // low-level filtering for miscellaneous admin operations which are not well supported by the WP API - $hardway_uris = array( - 'p-admin/index.php', 'p-admin/revision.php', 'admin.php?page=rvy-revisions', 'admin.php?page=revisionary-q', - 'p-admin/post.php', 'p-admin/post-new.php', 'p-admin/page.php', 'p-admin/page-new.php', - 'p-admin/link-manager.php', 'p-admin/edit.php', 'p-admin/edit-pages.php', 'p-admin/edit-comments.php', - 'p-admin/categories.php', 'p-admin/link-category.php', 'p-admin/edit-link-categories.php', 'p-admin/upload.php', - 'p-admin/edit-tags.php', 'p-admin/profile.php', 'p-admin/link-add.php', 'p-admin/admin-ajax.php' ); - - $hardway_uris = apply_filters('rvy_admin_hardway_uris', $hardway_uris); - - $uri = urldecode($request_uri); - foreach ( $hardway_uris as $uri_sub ) { // index.php can only be detected by index.php, but 3rd party-defined hooks may include arguments only present in REQUEST_URI - if ( defined('XMLRPC_REQUEST') || strpos($script_name, $uri_sub) || strpos($uri, $uri_sub) ) { - require_once(RVY_ABSPATH . '/hardway/hardway-admin_rvy.php'); - break; - } - } - - if (!empty($_REQUEST['page']) && ('revisionary-q' == $_REQUEST['page'])) { - if ( (!empty($_REQUEST['revision_updated'])) && ! empty($_REQUEST['post_id']) ) { - add_action( 'admin_menu', array( &$this, 'handle_update_redirect' ) ); - } - } - - if (strpos($request_uri, 'edit.php')) { - if ((!empty($_REQUEST['revision_submitted'])) && !empty($_REQUEST['post_id'])) { - add_action( 'admin_menu', array( &$this, 'handle_submission_redirect' ) ); - } - - add_filter( 'get_post_time', array(&$this, 'flt_get_post_time'), 10, 3 ); - - if ( ! empty( $_REQUEST['revision_action'] ) ) { - add_action( 'all_admin_notices', array( &$this, 'revision_action_notice' ) ); - } - } - - add_action( 'post_submitbox_start', array( &$this, 'pending_rev_checkbox' ) ); - add_action( 'post_submitbox_misc_actions', array( &$this, 'publish_metabox_time_display' ) ); - - add_action('admin_enqueue_scripts', [$this, 'fltAdminPostsListing'], 50); // 'the_posts' filter is not applied on edit.php for hierarchical types - - add_filter('display_post_states', [$this, 'flt_display_post_states'], 50, 2); - add_filter( 'page_row_actions', array($this, 'revisions_row_action_link' ) ); - add_filter( 'post_row_actions', array($this, 'revisions_row_action_link' ) ); - - if (!empty($_REQUEST['post_status']) && ('trash' == $_REQUEST['post_status'])) { - add_filter('display_post_states', [$this, 'fltTrashedPostState'], 20, 2 ); - add_filter('get_comments_number', [$this, 'fltCommentsNumber'], 20, 2); - } - - if ( in_array( $pagenow, array( 'plugins.php', 'plugin-install.php' ) ) ) { - require_once( dirname(__FILE__).'/admin-plugins_rvy.php' ); - $rvy_plugin_admin = new Rvy_Plugin_Admin(); - } - - if (!empty($_REQUEST['page']) && ('cms-tpv-page-page' == $_REQUEST['page'])) { - add_action('pre_get_posts', [$this, 'pre_get_posts']); - } - - add_filter('presspermit_disable_exception_ui', [$this, 'fltDisableExceptionUI'], 10, 4); - - add_filter('presspermit_status_control_scripts', [$this, 'fltDisableStatusControlScripts']); - - add_filter('cme_plugin_capabilities', [$this, 'fltPublishPressCapsSection']); - - add_action('admin_menu', [$this, 'actSettingsPageMaybeRedirect'], 999); - } - - public function fltPublishPressCapsSection($section_caps) { - $section_caps['PublishPress Revisions'] = ['edit_others_drafts', 'edit_others_revisions', 'list_others_revisions']; - return $section_caps; - } - - public function fltDisableStatusControlScripts($enable_scripts) { - if ($post_id = rvy_detect_post_id()) { - if ($post = get_post($post_id)) { - if (!empty($post) && rvy_is_revision_status($post->post_status)) { - $enable_scripts = false; - } - } - } - - return $enable_scripts; - } - - public function fltDisableExceptionUI($disable, $src_name, $post_id, $post_type = '') { - global $pagenow; - - if (!empty($pagenow) && ('term.php' == $pagenow)) { - return $disable; - } - - if (!$post_id) { - // Permissions version < 3.1.4 always passes zero value $post_id - $post_id = rvy_detect_post_id(); - } - - if ($post_id) { - $post_status = get_post_field('post_status', $post_id); - - if (in_array($post_status, ['pending-revision', 'future-revision'])) { - return true; - } - - if (!agp_user_can('edit_post', $post_id, '', ['skip_revision_allowance' => true])) { - return true; - } - } - - return $disable; - } - - // Prevent PublishPress Revisions statuses from confusing the page listing - public function pre_get_posts($wp_query) { - $stati = array_diff(get_post_stati(), apply_filters('revisionary_cmstpv_omit_statuses', ['pending-revision', 'future-revision'], rvy_detect_post_type())); - $wp_query->query['post_status'] = $stati; - $wp_query->query_vars['post_status'] = $stati; - } - public function fltAdminPostsListing() { - global $wpdb, $wp_query, $typenow; - - $listed_ids = array(); - - if ( ! empty( $wp_query->posts ) ) { - foreach ($wp_query->posts as $row) { - $listed_ids[] = $row->ID; - } + return; // no further filtering on WP plugin maintenance scripts } - if ($listed_ids) { - $id_csv = implode("','", array_map('intval', $listed_ids)); - $results = $wpdb->get_results( - "SELECT comment_count AS published_post, COUNT(comment_count) AS num_revisions FROM $wpdb->posts WHERE comment_count IN('$id_csv') AND post_status IN ('pending-revision', 'future-revision') GROUP BY comment_count" - ); - - foreach($results as $row) { - $this->post_revision_count[$row->published_post] = $row->num_revisions; + if (in_array($pagenow, array('post.php', 'post-new.php'))) { + if (empty($post)) { + $post = get_post(rvy_detect_post_id()); } - } - static $can_edit_published; - static $can_edit_others; - static $listed_post_statuses; + if ($post && rvy_is_supported_post_type($post->post_type)) { + // only apply revisionary UI for currently published or scheduled posts + if (!rvy_in_revision_workflow($post) && (in_array($post->post_status, rvy_filtered_statuses()) || ('future' == $post->post_status))) { + require_once( dirname(__FILE__).'/filters-admin-ui-item_rvy.php' ); + new RevisionaryPostEditorMetaboxes(); - if (is_null($can_edit_others) && ! empty( $wp_query->posts ) ) { - if (!$type_obj = get_post_type_object($typenow)) { - $limit_quickedit = false; - return; - } - - $can_edit_others = agp_user_can($type_obj->cap->edit_others_posts, 0, '', ['skip_revision_allowance' => true]); - - $can_edit_published = isset($type_obj->cap->edit_published_posts) && agp_user_can($type_obj->cap->edit_published_posts, 0, '', ['skip_revision_allowance' => true]); - - if (!$can_edit_others || !$can_edit_published) { - $listed_post_statuses = array(); - $ids = array(); - foreach ($wp_query->posts as $row) { - $ids []= $row->ID; - } + } elseif (rvy_in_revision_workflow($post)) { + add_action('the_post', array($this, 'limitRevisionEditorUI')); - $id_csv = implode("','", array_map('intval', $ids)); - $results = $wpdb->get_results("SELECT ID, post_status FROM $wpdb->posts WHERE ID IN ('$id_csv')"); - foreach($results as $row ) { - $listed_post_statuses[$row->ID] = $row->post_status; - } - } - } - - if ($can_edit_others && $can_edit_published) { - return; - } + require_once( dirname(__FILE__).'/edit-revision-ui_rvy.php' ); + new RevisionaryEditRevisionUI(); - if (!empty($wp_query->posts)) { - foreach ($wp_query->posts as $row) { - if (in_array($listed_post_statuses[$row->ID], rvy_filtered_statuses())) { - // @todo: better cap check precision for filter-applied statuses - if (!$can_edit_published || (!$can_edit_others && !rvy_is_post_author($row))) { - $this->hide_quickedit []= $row->ID; + if (\PublishPress\Revisions\Utils::isBlockEditorActive()) { + require_once( dirname(__FILE__).'/edit-revision-block-ui_rvy.php' ); + new RevisionaryEditRevisionBlockUI(); + } else { + require_once( dirname(__FILE__).'/edit-revision-classic-ui_rvy.php' ); + new RevisionaryEditRevisionClassicUI(); } } } } - } - - private function logTrashedRevisions() { - global $wpdb, $wp_query; - - if (!empty($wp_query) && !empty($wp_query->posts)) { - $listed_ids = []; - - foreach($wp_query->posts AS $row) { - $listed_ids []= $row->ID; - } - - $listed_post_csv = implode("','", array_map('intval', $listed_ids)); - $this->trashed_revisions = $wpdb->get_col("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_rvy_base_post_id' AND post_id IN ('$listed_post_csv')"); - } else { - $this->trashed_revisions = []; - } - } - - /** - * Adds "Pending Revision" or "Scheduled Revision" to the list of display states for trashed revisions in the Posts list table. - * - * @param array $post_states An array of post display states. - * @param WP_Post $post The current post object. - * @return array Filtered array of post display states. - */ - public function fltTrashedPostState($post_states, $post) { - if (!$post->comment_count) { // revisions buffer base post id to comment_count column for perf - return $post_states; - } - - if (!isset($this->trashed_revisions)) { - $this->logTrashedRevisions(); - } - - if (in_array($post->ID, $this->trashed_revisions)) { - if ($orig_revision_status = get_post_meta($post->ID, '_wp_trash_meta_status', true)) { - if ($status_obj = get_post_status_object($orig_revision_status)) { - $post_states['rvy_revision'] = $status_obj->label; - } - } - - if (!isset($post_states['rvy_revision'])) { - $post_states['rvy_revision'] = __('Pending Revision', 'revisionary'); - } - } - - return $post_states; - } - function fltCommentsNumber($comment_count, $post_id) { - if (isset($this->trashed_revisions) && in_array($post_id, $this->trashed_revisions)) { - $comment_count = 0; - } - - return $comment_count; - } - - function flt_display_post_states($post_states, $post) { - if (!empty($this->post_revision_count[$post->ID]) && !defined('REVISIONARY_SUPPRESS_POST_STATE_DISPLAY')) { - $post_states []= __('Has Revision', 'revisionary'); - } - - return $post_states; - } - - function revisions_row_action_link($actions = array()) { - global $post; - - if (empty($this->post_revision_count[$post->ID])) { - return $actions; - } - - if ( 'trash' != $post->post_status && current_user_can( 'edit_post', $post->ID ) && wp_check_post_lock( $post->ID ) === false ) { - $actions['revision_queue'] = "" . __('Revision Queue', 'revisionary') . ''; + if ( ! ( defined( 'SCOPER_VERSION' ) || defined( 'PP_VERSION' ) || defined( 'PPCE_VERSION' ) ) || defined( 'USE_RVY_RIGHTNOW' ) ) { + add_action('dashboard_glance_items', [$this, 'actDashboardGlanceItems']); } - return $actions; - } - - function revision_action_notice() { - if ( ! empty($_GET['restored_post'] ) ) { - $msg = __('The revision was restored.', 'revisionary'); - - } elseif ( ! empty($_GET['scheduled'] ) ) { - $msg = __('The revision was scheduled for publication.', 'revisionary'); - - } elseif ( ! empty($_GET['published_post'] ) ) { - $msg = __('The revision was published.', 'revisionary'); - } else { - return; + if ( rvy_get_option( 'pending_revisions' ) || rvy_get_option( 'scheduled_revisions' ) ) { + if ('revision.php' == $pagenow) { + require_once( dirname(__FILE__).'/history_rvy.php' ); + new RevisionaryHistory(); } - - ?> -
-
- enabled_post_types); - $post_types_csv = implode( "','", $types ); - $clauses['where'] = str_replace( "$wpdb->posts.post_type = 'post'", "$wpdb->posts.post_type IN ('$post_types_csv')", $clauses['where'] ); - - remove_filter( 'posts_clauses_request', array( &$this, 'flt_dashboard_query_clauses' ) ); - return $clauses; - } - - function handle_submission_redirect() { - global $revisionary; - - if ( $revised_post = get_post( (int) $_REQUEST['post_id'] ) ) { - $status = sanitize_key( $_REQUEST['revision_submitted'] ); - - // Workaround for Gutenberg stripping published thumbnail, page template on revision creation - foreach(['_thumbnail_id', '_wp_page_template'] as $meta_key) { - if ($archived_val = rvy_get_transient("_archive_{$meta_key}_{$revised_post->ID}")) { - rvy_update_post_meta($revised_post->ID, $meta_key, $archived_val); - rvy_delete_transient("_archive_{$meta_key}_{$revised_post->ID}"); - } - } - - if ( $revisions = rvy_get_post_revisions( $revised_post->ID, $status, array( 'order' => 'DESC', 'orderby' => 'ID' ) ) ) { // @todo: retrieve revision_id in block editor js, pass as redirect arg - foreach( $revisions as $revision ) { - if (rvy_is_post_author($revision)) { - // @todo: move to a 'save_post' action handler - if ( time() - strtotime( $revision->post_modified_gmt ) < 90 ) { // sanity check in finding the revision that was just submitted - $args = array( 'revision_id' => $revision->ID, 'published_post' => $revised_post, 'object_type' => $revised_post->post_type ); - if ( ! empty( $_REQUEST['cc'] ) ) { - $args['selected_recipients'] = array_map('intval', explode( ',', $_REQUEST['cc'] )); - } - - $revisionary->do_notifications( $status, $status, (array) $revised_post, $args ); - } - - if (apply_filters('revisionary_do_submission_redirect', true)) { - rvy_halt( $revisionary->get_revision_msg( $revision, array( 'post_arr' => (array) $revision, 'post_id' => $revised_post->ID ) ) ); - } - } - } - } + if ( rvy_get_option( 'scheduled_revisions' ) ) { + add_filter('dashboard_recent_posts_query_args', [$this, 'flt_dashboard_recent_posts_query_args']); } - } - function handle_update_redirect() { - global $revisionary; - - if (!rvy_get_option('revision_update_redirect')) { - return; + if (!empty($_REQUEST['page']) && ('cms-tpv-page-page' == $_REQUEST['page'])) { + add_action('pre_get_posts', [$this, 'cmstpv_compat_get_posts']); } - if ( $revision = get_post( (int) $_REQUEST['post_id'] ) ) { - if (rvy_is_post_author($revision)) { - // Note: Revision Update notification is triggered by 'post_updated' action. + add_filter('presspermit_status_control_scripts', [$this, 'fltDisableStatusControlScripts']); - if (apply_filters('revisionary_do_update_redirect', true, $revision)) { - rvy_halt( $revisionary->get_revision_msg( - $revision, - ['post_arr' => (array) $revision, 'post_id' => rvy_post_id($revision->ID)] - )); - } - } - } + add_filter('cme_plugin_capabilities', [$this, 'fltPublishPressCapsSection']); } - - function add_editor_ui() { - global $revisionary, $pagenow; - - if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) ) { - global $post; - - if ( $post && rvy_is_supported_post_type($post->post_type)) { - if ( $revisionary->isBlockEditorActive() ) { - if ( ! $post->ID && ! is_content_administrator_rvy() ) { - if (!agp_user_can('edit_post', $post->ID, '', ['skip_revision_allowance' => true])) { - wp_deregister_script( 'autosave' ); - wp_dequeue_script( 'autosave' ); - } - } - } - if ( $status_obj = get_post_status_object( $post->post_status ) ) { - // only apply revisionary UI for currently published or scheduled posts - if (in_array($post->post_status, rvy_filtered_statuses()) || ('future' == $post->post_status)) { - require_once( dirname(__FILE__).'/filters-admin-ui-item_rvy.php' ); - $revisionary->filters_admin_item_ui = new RevisionaryAdminFiltersItemUI(); - } elseif (rvy_is_revision_status($post->post_status) && !$revisionary->isBlockEditorActive()) { - require_once( dirname(__FILE__).'/edit-revision-ui_rvy.php' ); - $revisionary->filters_admin_item_ui = new RevisionaryEditRevisionUI(); - } - } - } - } - } - - function publish_metabox_time_display() { - global $post, $action; - - if ( ! rvy_get_option( 'scheduled_revisions' ) ) { - return; - } - - $stati = get_post_stati( array( 'public' => true, 'private' => true ), 'names', 'or' ); - - if ( empty($post) || ! $type_obj = get_post_type_object($post->post_type) ) { - return; - } - - if ( ! empty($post) && in_array( $post->post_status, $stati ) && ! current_user_can( $type_obj->cap->publish_posts ) && rvy_is_supported_post_type($post->post_type) ) : - $datef = __( 'M j, Y @ g:i a', 'revisionary' ); - if ( 0 != $post->ID ) { - if ( 'future' == $post->post_status ) { // scheduled for publishing at a future date - $stamp = __('Scheduled for: %s'); - } else if ( 'publish' == $post->post_status || 'private' == $post->post_status ) { // already published - $stamp = __('Published on: %s'); - } else if ( '0000-00-00 00:00:00' == $post->post_date_gmt ) { // draft, 1 or more saves, no date specified - $stamp = __('Publish immediately'); - } else if ( time() < strtotime( $post->post_date_gmt . ' +0000' ) ) { // draft, 1 or more saves, future date specified - $stamp = __('Schedule for: %s'); - } else { // draft, 1 or more saves, date specified - $stamp = __('Publish on: %s'); - } - $date = '' . date_i18n( $datef, strtotime( $post->post_date ) ) . ''; - } else { // draft (no saves, and thus no date specified) - $stamp = __('Publish immediately'); - $date = date_i18n( $datef, strtotime( current_time('mysql') ) ); - } - ?> -
- - - -
-
- post_status, rvy_filtered_statuses()) && ('future' != $post->post_status)) || !rvy_is_supported_post_type($post->post_type)) { - return; + if (in_array($pagenow, ['post.php', 'post-new.php']) || (!empty($_REQUEST['page']) && in_array($_REQUEST['page'], ['revisionary-settings', 'rvy-net_options', 'revisionary-q']))) { + wp_enqueue_style('revisionary-admin-common', RVY_URLPATH . '/common/css/pressshack-admin.css', [], PUBLISHPRESS_REVISIONS_VERSION); } - if (!agp_user_can('edit_post', $post->ID, '', ['skip_revision_allowance' => true])) { - return; + if ((!empty($_REQUEST['page']) && in_array($_REQUEST['page'], ['revisionary-settings']))) { + wp_enqueue_script('revisionary-settings', RVY_URLPATH . '/admin/settings.js', [], PUBLISHPRESS_REVISIONS_VERSION); } - $caption = apply_filters('revisionary_pending_checkbox_caption_classic', __( 'Save as Pending Revision', 'revisionary' ), $post); - $checked = (apply_filters('revisionary_default_pending_revision', false, $post )) ? "checked='checked'" : ''; - - $title = esc_attr(__('Do not publish current changes yet, but save to Revision Queue', 'revisionary')); - echo "
"; - } - - function act_log_revision_save() { - $this->revision_save_in_progress = true; - } - - function flt_detect_revision_save( $post_status ) { - if (rvy_is_revision_status($post_status)) { - $this->revision_save_in_progress = true; - } - - return $post_status; - } - - // adds an Options link next to Deactivate, Edit in Plugins listing - function flt_plugin_action_links($links, $file) { - if ($file == plugin_basename(REVISIONARY_FILE)) { - $page = ( RVY_NETWORK ) ? 'rvy-net_options' : 'revisionary-settings'; - $links[] = "" . __awp('Settings') . ""; - } - - return $links; - } - - function admin_scripts() { - wp_enqueue_style('revisionary', RVY_URLPATH . '/admin/revisionary.css', [], REVISIONARY_VERSION); - - global $pagenow, $post, $revisionary; - if ( ('post.php' == $pagenow) && (('revision' == $post->post_type) || rvy_is_revision_status($post->post_status)) ) { - wp_enqueue_style('rvy-revision-edit', RVY_URLPATH . '/admin/rvy-revision-edit.css', [], REVISIONARY_VERSION); - - if (!rvy_get_option('scheduled_revisions') && !$revisionary->isBlockEditorActive()) { - ?> - - - - - - - - '."\n"; - - global $pagenow, $revisionary; - - if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) && ! defined('RVY_PREVENT_PUBHIST_CAPTION') && ! $revisionary->isBlockEditorActive() ) { - wp_enqueue_script( 'rvy_post', RVY_URLPATH . "/admin/post-edit.js", array('jquery'), RVY_VERSION, true ); - - $args = array( - 'nowCaption' => __( 'Current Time', 'revisionary' ), - /*'pubHistoryCaption' => __( 'Publication History:', 'revisionary' ) */ - ); - wp_localize_script( 'rvy_post', 'rvyPostEdit', $args ); - } - if( false !== strpos( urldecode($_SERVER['REQUEST_URI']), 'admin.php?page=rvy-revisions' ) ) { - - // add Ajax goodies we need for fancy publish date editing in Revisions Manager and role duration/content date limit editing Bulk Role Admin - ?> - - ID); - - if ( !rvy_is_revision_status($revision->post_status) || $post = get_post($published_id) ) { - require_once( dirname(__FILE__).'/revision-ui_rvy.php' ); - } - } - } - + // legacy revision management UI for past revisions require_once( dirname(__FILE__).'/revision-ui_rvy.php' ); } - - // all required JS functions are present in Role Scoper JS; TODO: review this for future version changes as necessary - // TODO: replace some of this JS with equivalent JQuery - if ( ! defined('SCOPER_VERSION') ) - wp_enqueue_script( 'rvy', RVY_URLPATH . "/admin/revisionary.js", array('jquery'), RVY_VERSION, true ); + + if ( ! defined('SCOPER_VERSION') ) { + // old js for notification recipient selection UI + wp_enqueue_script( 'rvy', RVY_URLPATH . "/admin/revisionary.js", array('jquery'), PUBLISHPRESS_REVISIONS_VERSION, true ); + } + } + + function actDashboardGlanceItems($items) { + require_once(dirname(__FILE__).'/admin-dashboard_rvy.php'); + RevisionaryDashboard::glancePending(); } function moderation_queue() { @@ -695,7 +149,7 @@ function build_menu() { if ( strpos( $_SERVER['REQUEST_URI'], 'wp-admin/network/' ) ) return; - + $path = RVY_ABSPATH; // For Revisions Manager access, satisfy WordPress' demand that all admin links be properly defined in menu @@ -727,143 +181,79 @@ function build_menu() { return; global $rvy_default_options, $rvy_options_sitewide; - + if ( empty($rvy_default_options) ) rvy_refresh_default_options(); - global $blog_id; if ( ! RVY_NETWORK || ( count($rvy_options_sitewide) != count($rvy_default_options) ) ) { add_submenu_page( 'revisionary-q', __('PublishPress Revisions Settings', 'revisionary'), __('Settings', 'revisionary'), 'read', 'revisionary-settings', 'rvy_omit_site_options'); - add_action('revisionary_page_revisionary-settings', 'rvy_omit_site_options' ); + add_action('revisionary_page_revisionary-settings', 'rvy_omit_site_options' ); } - if (!defined('REVISIONARY_PRO_VERSION')) { + if (!defined('PUBLISHPRESS_REVISIONS_PRO_VERSION')) { add_submenu_page( - 'revisionary-q', - __('Upgrade to Pro', 'revisionary'), - __('Upgrade to Pro', 'revisionary'), - 'read', - 'revisionary-pro', + 'revisionary-q', + __('Upgrade to Pro', 'revisionary'), + __('Upgrade to Pro', 'revisionary'), + 'read', + 'revisionary-pro', 'rvy_omit_site_options' ); } } - function act_hide_quickedit() { - if ( empty( $this->hide_quickedit ) ) - return; + function limitRevisionEditorUI() { + global $post; - $post_type = awp_post_type_from_uri(); - $type_obj = get_post_type_object($post_type); - ?> - - post_type, 'author'); + remove_post_type_support($post->post_type, 'custom-fields'); // todo: filter post_id in query } - function act_hide_admin_divs() { - - // Hide unrevisionable elements if editing for revisions, regardless of Limited Editing Element settings - // - // TODO: allow revisioning of slug, menu order, comment status, ping status ? - // TODO: leave Revisions metabox for links to user's own pending revisions - if ( rvy_get_option( 'pending_revisions' ) ) { - global $post; - if ( ! empty($post->post_type) ) - $object_type = $post->post_type; - else - $object_type = awp_post_type_from_uri(); - - $object_id = rvy_detect_post_id(); - - if ( $object_id ) { - if (!empty($post) && (rvy_is_revision_status($post->post_status) || !agp_user_can('edit_post', $object_id, '', ['skip_revision_allowance' => true]))) { - //if ( 'page' == $object_type ) - //$unrevisable_css_ids = array( 'pageauthordiv', 'pagecustomdiv', 'pageslugdiv', 'pagecommentstatusdiv' ); - //else - //$unrevisable_css_ids = array_merge( $unrevisable_css_ids, array( 'categorydiv', 'authordiv', 'postcustom', 'customdiv', 'slugdiv', 'commentstatusdiv', 'password-span', 'trackbacksdiv', 'tagsdiv-post_tag', 'visibility', 'edit-slug-box', 'postimagediv', 'ef_editorial_meta' ) ); - - $unrevisable_css_ids = array( 'authordiv', 'visibility', 'postcustom', 'pagecustom' ); // todo: filter custom fields queries for revision_id - - //foreach( get_taxonomies( array(), 'object' ) as $taxonomy => $tx_obj ) - // $unrevisable_css_ids []= ( $tx_obj->hierarchical ) ? "{$taxonomy}div" : "tagsdiv-$taxonomy"; - - $unrevisable_css_ids = apply_filters( 'rvy_hidden_meta_boxes', $unrevisable_css_ids ); - - if (rvy_is_revision_status($post->post_status)) { - $unrevisable_css_ids = array_merge($unrevisable_css_ids, ['publish', 'slugdiv', 'edit-slug-box']); - } + function flt_dashboard_recent_posts_query_args($query_args) { + if ('future' == $query_args['post_status']) { + require_once(dirname(__FILE__).'/admin-dashboard_rvy.php'); + $rvy_dash = new RevisionaryDashboard(); + $query_args = $rvy_dash->recentPostsQueryArgs($query_args); + } - echo( "\n\n"; - - // display the current status, but hide edit link - echo "\n\n"; // this line adapted from Clutter Free plugin by Mark Jaquith - } - } - } + return $query_args; } - function flt_delete_post_link( $link, $post_id ) { - if ( strpos( $link, 'revision.php' ) ) { - if ( $post_id ) { - $link = "admin.php?page=rvy-revisions&action=delete&&return=1&revision=". $post_id; + // adds a Settings link next to Deactivate, Edit in Plugins listing + function flt_plugin_action_links($links, $file) { + if ($file == plugin_basename(REVISIONARY_FILE)) { + $page = ( defined('RVY_NETWORK') && RVY_NETWORK ) ? 'rvy-net_options' : 'revisionary-settings'; + $links[] = "" . __awp('Settings') . ""; + } - $link = "javascript:if(confirm('". __('Delete'). "?')) window.location='". wp_nonce_url( $link, 'delete-revision_' . $post_id ). "'"; - } - } + return $links; + } - return $link; - } + public function fltPublishPressCapsSection($section_caps) { + $section_caps['PublishPress Revisions'] = ['edit_others_drafts', 'edit_others_revisions', 'list_others_revisions', 'manage_unsubmitted_revisions']; + return $section_caps; + } - function flt_post_title ( $title, $id = '' ) { - if ( $id ) - if ( $post = get_post( $id ) ) { - if (rvy_is_revision_status($post->post_status)) { - $title = sprintf( __( '%s (revision)', 'revisionary' ), $title ); + public function fltDisableStatusControlScripts($enable_scripts) { + if ($post_id = rvy_detect_post_id()) { + if ($post = get_post($post_id)) { + if (!empty($post) && rvy_in_revision_workflow($post)) { + $enable_scripts = false; } } + } - return $title; + return $enable_scripts; } - - // only added for edit.php and edit-pages.php - function flt_get_post_time( $time, $format, $gmt ) { - if ( function_exists('get_the_ID') && $post_id = get_the_ID() ) { - if ( $post = get_post( $post_id ) ) { - if ( 'pending-revision' == $post->post_status ) { - if ( $gmt ) - $time = mysql2date($format, $post->post_modified_gmt, $gmt); - else - $time = mysql2date($format, $post->post_modified, $gmt); - } - } - } - - return $time; + + // Prevent PublishPress Revisions statuses from confusing the CMS Tree Page View plugin page listing + public function cmstpv_compat_get_posts($wp_query) { + $wp_query->query['post_mime_type'] = ''; + $wp_query->query_vars['post_mime_type'] = ''; } - function publishpressFooter() { - if (defined('REVISIONARY_PRO_VERSION') && !rvy_get_option('display_pp_branding')) { + public function publishpressFooter() { + if (defined('PUBLISHPRESS_REVISIONS_PRO_VERSION') && !rvy_get_option('display_pp_branding')) { return; } @@ -872,7 +262,7 @@ function publishpressFooter() {
- PublishPress Revisions', '' @@ -907,31 +297,4 @@ function publishpressFooter() { 'revisionary-settings', - ] as $old_slug => $new_slug) { - if ( - strpos($_SERVER['REQUEST_URI'], "page=$old_slug") - && (false !== strpos($_SERVER['REQUEST_URI'], 'admin.php')) - ) { - global $submenu; - - // Don't redirect if pp-settings is registered by another plugin or theme - foreach (array_keys($submenu) as $i) { - foreach (array_keys($submenu[$i]) as $j) { - if (isset($submenu[$i][$j][2]) && ($old_slug == $submenu[$i][$j][2])) { - return; - } - } - } - - $arr_url = parse_url($_SERVER['REQUEST_URI']); - wp_redirect(admin_url('admin.php?' . str_replace("page=$old_slug", "page=$new_slug", $arr_url['query']))); - exit; - } - } - } } // end class RevisionaryAdmin diff --git a/admin/agents_checklist_rvy.php b/admin/agents_checklist_rvy.php index 59b0ea0d..20bc2c7e 100644 --- a/admin/agents_checklist_rvy.php +++ b/admin/agents_checklist_rvy.php @@ -7,17 +7,6 @@ // TODO: scale this down more, as it's overkill for Revisionary's usage class RevisionaryAgentsChecklist { - public static function all_agents_checklist( $role_bases, $agents, $args, $class = 'rs-agents' ) { - $div_style = "class='$class rvy-agents-checklist'"; - - foreach ( $role_bases as $role_basis ) { - echo "
"; - self::agents_checklist($role_basis, $agents[$role_basis], $role_basis, array(), $args); - - echo "
"; - } - } - public static function agents_checklist( $role_basis, $all_agents, $id_prefix = '', $stored_assignments = '', $args = '') { if ( empty($all_agents) ) return; @@ -38,22 +27,11 @@ public static function agents_checklist( $role_basis, $all_agents, $id_prefix = } } - public static function eligible_agents_input_box( $role_basis, $id_prefix, $propagation ) { - $id = "{$id_prefix}_csv"; - $msg = __( "Enter additional User Names or IDs (comma-separate)", 'revisionary'); - echo '
' . $msg . ':
'; - echo ""; - } - // stored_assignments[agent_id][inherited_from] = progenitor_assignment_id (note: this function treats progenitor_assignment_id as a boolean) static function _agents_checklist_display( $agents_subset, $role_basis, $all_agents, $id_prefix, $stored_assignments, $args, &$key) { $defaults = array( - 'eligible_ids' => '', 'locked_ids' => '', - 'suppress_extra_prefix' => false, 'check_for_incomplete_submission' => false, - 'checkall_threshold' => 6, 'filter_threshold' => 10, 'default_hide_threshold' => 20, - 'caption_length_limit' => 20, 'emsize_threshold' => 4, - 'objtype_display_name' => '', 'objtype_display_name_plural' => '', - 'for_entity_ids' => ''); + 'filter_threshold' => 10, 'default_hide_threshold' => 20, 'caption_length_limit' => 20, 'emsize_threshold' => 4 + ); $args = (array) $args; foreach( array_keys( $defaults ) as $var ) { @@ -63,28 +41,15 @@ static function _agents_checklist_display( $agents_subset, $role_basis, $all_age global $is_IE; $ie_checkbox_style = ( $is_IE ) ? "style='height:1em'" : ''; - if ( is_array($eligible_ids) && empty($eligible_ids) ) - $eligible_ids = array(-1); - else - if ( ! is_array($eligible_ids) ) $eligible_ids = array(); else $eligible_ids = array_flip($eligible_ids); - if ( ! is_array($stored_assignments) ) $stored_assignments = array(); - if ( ! is_array($locked_ids) ) $locked_ids = array(); else $locked_ids = array_flip($locked_ids); - if ( is_array($for_entity_ids) && ! empty($for_entity_ids) ) $for_entity_ids = array_flip($for_entity_ids); - - if ( ! $suppress_extra_prefix ) - $id_prefix .= "_{$role_basis}"; + + $id_prefix .= "_{$role_basis}"; $agent_count = array(); $agent_count[CURRENT_ITEMS_RVY] = count($stored_assignments); - if ( empty($eligible_ids) ) - $agent_count[ELIGIBLE_ITEMS_RVY] = count($all_agents) - count( $stored_assignments ); - elseif ( $eligible_ids != array(-1) ) - $agent_count[ELIGIBLE_ITEMS_RVY] = count( array_diff_key($eligible_ids, $stored_assignments) ); - else - $agent_count[ELIGIBLE_ITEMS_RVY] = 0; + $agent_count[ELIGIBLE_ITEMS_RVY] = count($all_agents) - count( $stored_assignments ); $default_hide_filtered_list = ( $default_hide_threshold && ( $agent_count[$agents_subset] > $default_hide_threshold ) ); @@ -151,10 +116,7 @@ static function _agents_checklist_display( $agents_subset, $role_basis, $all_age foreach( $all_agents as $agent ) { $id = $agent->ID; - if ( is_array($for_entity_ids) ) - $role_assigned = isset($for_entity_ids[$id]) || isset($for_children_ids[$id]) ; - else - $role_assigned = isset($stored_assignments[$id]); + $role_assigned = isset($stored_assignments[$id]); switch ( $agents_subset ) { case CURRENT_ITEMS_RVY: @@ -162,7 +124,6 @@ static function _agents_checklist_display( $agents_subset, $role_basis, $all_age break; default: //ELIGIBLE_ITEMS_RVY if ( $role_assigned ) continue 2; - if ( $eligible_ids && ! isset($eligible_ids[$id] ) ) continue 2; } $caption = $agent->display_name; @@ -208,10 +169,7 @@ static function _agents_checklist_display( $agents_subset, $role_basis, $all_age $id = $agent->ID; $agent_display_name = $agent->display_name; - if ( is_array($for_entity_ids) ) - $role_assigned = isset($for_entity_ids[$id]) || isset($for_children_ids[$id]) ; - else - $role_assigned = isset($stored_assignments[$id]); + $role_assigned = isset($stored_assignments[$id]); switch ( $agents_subset ) { case CURRENT_ITEMS_RVY: @@ -219,7 +177,6 @@ static function _agents_checklist_display( $agents_subset, $role_basis, $all_age break; default: //ELIGIBLE_ITEMS_RVY if ( $role_assigned ) continue 2; - if ( $eligible_ids && ! isset($eligible_ids[$id] ) ) continue 2; } // markup for role duration / content date limits @@ -228,14 +185,9 @@ static function _agents_checklist_display( $agents_subset, $role_basis, $all_age $link_class = ''; $limit_style = ''; - $disabled = ( $locked_ids && isset($locked_ids[$id]) ) ? " disabled='disabled'" : ''; - $li_title = "title=' " . strtolower($agent_display_name) . " '"; - if ( $role_assigned && ( ! is_array($for_entity_ids) || isset($for_entity_ids[$id]) ) ) - $this_checked = ' checked="checked"'; - else - $this_checked = ''; + $this_checked = ( $role_assigned ) ? ' checked="checked"' : ''; if ( $this_checked ) $last_agents[] = $id; @@ -243,7 +195,7 @@ static function _agents_checklist_display( $agents_subset, $role_basis, $all_age $label_class = ''; echo "\r\n
  • " - . ""; + . ""; echo "$label"; break; case 'date_sched' : - if ( ('future-revision' === $post->post_status ) || ( strtotime($post->post_date_gmt) > agp_time_gmt() ) ) { + if ( ('future-revision' === $post->post_mime_type ) || ( strtotime($post->post_date_gmt) > agp_time_gmt() ) ) { $t_time = get_the_time( __( 'Y/m/d g:i:s a', 'revisionary' ) ); $m_time = $post->post_date; @@ -422,7 +474,7 @@ function rvy_pending_custom_col( $column_name, $post_id ) { $h_time = str_replace( ' ', '
    ', $h_time ); } - if ('future-revision' == $post->post_status) { + if ('future-revision' == $post->post_mime_type) { $t_time = sprintf(__('Scheduled publication: %s', 'revisionary'), $t_time); } else { $h_time = "[$h_time]"; @@ -506,7 +558,7 @@ protected function handle_published_row_actions( $post, $column_name ) { ); } - $request_url = add_query_arg($_REQUEST, admin_url('admin.php?page=revisionary-q')); + $request_url = add_query_arg($_REQUEST, rvy_admin_url('admin.php?page=revisionary-q')); $actions['list_filter'] = sprintf( '%3$s', @@ -591,10 +643,28 @@ public function prepare_items() { $total_items = $wp_query->found_posts; + // auto-flush revision flags + /* + if (!$total_items && !rvy_get_option('queue_query_all_posts') && !get_transient('revisionary_flushed_has_revision_flag')) { + revisionary_refresh_revision_flags(); + set_transient('revisionary_flushed_has_revision_flag', true, 60); + } + */ + $this->set_pagination_args( [ 'total_items' => $total_items, 'per_page' => $per_page ]); + + if (empty($_REQUEST['all']) && empty($_REQUEST['author']) && empty($_REQUEST['post_author']) && empty($_REQUEST['post_status'])) :?> + + revisions_where_filter("post_status IN ('$status_csv') $type_clause", ['status_count' => true]); + $where = $this->revisions_where_filter("post_mime_type IN ('$status_csv') $type_clause", ['status_count' => true]); - $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE $where"; - $query .= ' GROUP BY post_status'; + $query = "SELECT post_mime_type, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE $where"; + $query .= ' GROUP BY post_mime_type'; - $query = apply_filters('presspermit_posts_request', $query, ['has_cap_check' => true]); // has_cap_check argument triggers inclusion of revision statuses + // @todo: review Permissions integration for revision count filtering + //$query = apply_filters('presspermit_posts_request', $query, ['has_cap_check' => true]); // has_cap_check argument triggers inclusion of revision statuses $results = (array) $wpdb->get_results( $query, ARRAY_A ); $counts = []; foreach ( $results as $row ) { - $counts[ $row['post_status'] ] = $row['num_posts']; + $counts[ $row['post_mime_type'] ] = $row['num_posts']; } if (!rvy_get_option('pending_revisions')) { + unset($counts['draft-revision']); unset($counts['pending-revision']); } @@ -665,14 +737,13 @@ private function count_revisions($post_type = '', $statuses = '' ) { /** * - * @global array $locked_post_status This seems to be deprecated. * @return array */ protected function get_views() { global $wp_query, $wpdb, $current_user; $post_types = rvy_get_manageable_types(); - $statuses = ['pending-revision', 'future-revision']; + $revision_statuses = rvy_revision_statuses(); $q = ['post_type' => $post_types, 'fields' => 'ids', 'post_parent' => $this->published_post_ids]; @@ -684,14 +755,18 @@ protected function get_views() { $q['m'] = (int) $_REQUEST['m']; } - $num_posts = $this->count_revisions($post_types, $statuses); + $num_posts = $this->count_revisions($post_types, $revision_statuses); $links = []; + + $links[''] = ''; $links['all'] = ''; + $revision_status_csv = rvy_revision_statuses(['return' => 'csv']); + $where = $this->revisions_where_filter( $wpdb->prepare( - "$wpdb->posts.post_status IN ('pending-revision', 'future-revision') AND $wpdb->posts.post_author = '%d'", + "$wpdb->posts.post_mime_type IN ($revision_status_csv) AND $wpdb->posts.post_author = '%d'", $current_user->ID ), ['status_count' => true] @@ -710,23 +785,26 @@ protected function get_views() { $link_class = ''; } - $links['mine'] = sprintf(__('%sMy Revisions%s(%s)', 'revisionary'), "", '', "$my_count"); + $links['mine'] = sprintf( + translate_nooped_plural(pp_revisions_label('my_revisions'), $my_count), + "", '', "$my_count" + ) .' '; } $where = $this->revisions_where_filter( $wpdb->prepare( - "r.post_status IN ('pending-revision', 'future-revision') AND p.post_author = '%d'", + "r.post_mime_type IN ($revision_status_csv) AND p.post_author = '%d'", $current_user->ID ), - ['alias' => 'r', 'status_count' => true] + ['alias' => 'r', 'status_count' => true, 'my_published_count' => true] ); $count_query = apply_filters('presspermit_posts_request', - "SELECT COUNT(DISTINCT p.ID) FROM $wpdb->posts AS p INNER JOIN $wpdb->posts AS r ON r.comment_count = p.ID WHERE $where", + "SELECT COUNT(r.ID) FROM $wpdb->posts AS p INNER JOIN $wpdb->posts AS r ON r.comment_count = p.ID WHERE $where", ['has_cap_check' => true, 'source_alias' => 'p'] ); - $status_csv = "'" . implode("','", rvy_filtered_statuses()) . "'"; + $status_csv = rvy_filtered_statuses(['return' => 'csv']); $count_query .= " AND p.post_status IN ($status_csv)"; // work around some versions of PressPermit inserting non-aliased post_type reference into where clause under some configurations @@ -742,18 +820,21 @@ protected function get_views() { $link_class = ''; } - $links['my_posts'] = sprintf(__('%sMy Published Posts%s(%s)', 'revisionary'), "", '', "$my_post_count"); + $links['my_posts'] = sprintf( + translate_nooped_plural(pp_revisions_label('my_published_posts'), $my_post_count), + "", '', "$my_post_count" + ) . ' '; } $all_count = 0; - foreach($statuses as $status) { + foreach($revision_statuses as $status) { if (!isset($num_posts->$status)) { $num_posts->$status = 0; } if (!empty($num_posts->$status)) { $status_obj = get_post_status_object($status); - + $status_label = $status_obj ? sprintf( translate_nooped_plural( $status_obj->label_count, $num_posts->$status ), number_format_i18n( $num_posts->$status ) @@ -771,13 +852,21 @@ protected function get_views() { } } - if (empty($current_link_class) && empty($_REQUEST['post_type']) && empty($_REQUEST['author']) && empty($_REQUEST['post_author']) && empty($_REQUEST['published_post']) && empty($_REQUEST['post_status'])) { + if (empty($current_link_class) && empty($_REQUEST['post_type']) && empty($_REQUEST['author']) && empty($_REQUEST['post_author']) && empty($_REQUEST['published_post']) && empty($_REQUEST['post_status']) && empty($_REQUEST['all'])) { $link_class = " class='current'"; } else { $link_class = ''; } - $links['all'] = "" . sprintf( __('All %s', 'revisionary'), "($all_count)" ) . ''; + $links[''] = "" . sprintf( __('My Activity', 'revisionary'), "($all_count)" ) . ''; + + if (empty($current_link_class) && empty($_REQUEST['post_type']) && empty($_REQUEST['author']) && empty($_REQUEST['post_author']) && empty($_REQUEST['published_post']) && empty($_REQUEST['post_status']) && !empty($_REQUEST['all'])) { + $link_class = " class='current'"; + } else { + $link_class = ''; + } + + $links['all'] = "" . sprintf( __('All %s', 'revisionary'), "($all_count)" ) . ''; return $links; } @@ -801,6 +890,8 @@ protected function get_bulk_actions() { } } + $actions['submit_revision'] = __('Submit'); + if ($approval_potential = apply_filters('revisionary_bulk_action_approval', $approval_potential)) { $actions['approve_revision'] = __('Approve'); $actions['publish_revision'] = __('Publish'); @@ -841,6 +932,7 @@ protected function extra_tablenav( $which ) { ?>
    'post-query-submit' ) ); } } + */ ?>
    'csv']); + $extra_checks = "AND post_status != 'auto-draft'"; if (isset($_GET['post_status']) && ('all' != $_GET['post_status'])) { $extra_checks = $wpdb->prepare( ' AND post_status = %s', sanitize_key($_GET['post_status']) ); } else { - $extra_checks = " AND post_status IN ('pending-revision', 'future-revision')"; + $extra_checks = " AND post_mime_type IN ($revision_status_csv)"; } $date_col = ( ! empty($_REQUEST['post_status']) && 'future-revision' == $_REQUEST['post_status'] ) ? 'post_date' : 'post_modified'; @@ -997,16 +1092,6 @@ public function print_column_headers( $with_id = true ) { // use post status and post type column headers to reset filter, but not for sorting $_url = remove_query_arg($orderby, $current_url); - /* - if (!empty($_REQUEST['post_status']) && ('future-revision' == $_REQUEST['post_status'])) { - $order = 'ASC'; - $orderby = (isset($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], array('post_type', 'post_status'))) ? : 'date_sched'; - } else { - $order = 'DESC'; - $orderby = 'date'; - } - */ - $column_display_name = '' . $column_display_name . ''; } else { $column_display_name = '' . $column_display_name . ''; @@ -1080,7 +1165,7 @@ public function column_author( $post ) { //if (defined('PUBLISHPRESS_MULTIPLE_AUTHORS_VERSION')) { // do_action("manage_{$post->post_type}_posts_custom_column", 'authors', $post->ID); //} else { - $request_url = add_query_arg($_REQUEST, admin_url('admin.php?page=revisionary-q')); + $request_url = add_query_arg($_REQUEST, rvy_admin_url('admin.php?page=revisionary-q')); $args = ['author' => get_the_author_meta( 'ID' )]; echo $this->apply_edit_link( add_query_arg('author', $args['author'], $request_url), get_the_author() ); @@ -1151,19 +1236,22 @@ protected function handle_row_actions( $post, $column_name, $primary ) { ); } } + } - //if ( current_user_can( 'read_post', $post->ID ) ) { // @todo make this work for Author with Revision exceptions - if ( $can_read_post || $can_edit_post ) { - $actions['diff'] = sprintf( - '%3$s', - admin_url("revision.php?revision=$post->ID"), - /* translators: %s: post title */ - esc_attr( sprintf( __('Compare Changes', 'revisionary'), $title ) ), - _x('Compare', 'revisions', 'revisionary') - ); - } + //if ( current_user_can( 'read_post', $post->ID ) ) { // @todo make this work for Author with Revision exceptions + if ( $can_read_post || $can_edit_post ) { + $actions['diff'] = sprintf( + '%3$s', + admin_url("revision.php?revision=$post->ID"), + /* translators: %s: post title */ + esc_attr( sprintf( __('Compare Changes', 'revisionary'), $title ) ), + _x('Compare', 'revisions', 'revisionary') + ); } + $actions = apply_filters('revisionary_queue_row_actions', $actions, $post); + + return $this->row_actions( $actions ); } diff --git a/admin/edit-revision-block-ui_rvy.php b/admin/edit-revision-block-ui_rvy.php new file mode 100644 index 00000000..ff1b1b5b --- /dev/null +++ b/admin/edit-revision-block-ui_rvy.php @@ -0,0 +1,28 @@ + + + post_type)) ? $post->post_type : awp_post_type_from_uri(); + + $unrevisable_css_ids = apply_filters('rvy_hidden_meta_boxes', ['authordiv', 'visibility', 'postcustom', 'pagecustom']); + + if (rvy_in_revision_workflow($post)) { + $unrevisable_css_ids = array_merge($unrevisable_css_ids, ['publish', 'slugdiv', 'edit-slug-box']); + } + + echo( "\n\n"; + + // display the current status, but hide edit link + echo "\n\n"; // this line adapted from Clutter Free plugin by Mark Jaquith + } + } + + public function fltEditorUIstatus($status, $post, $args) { + if (rvy_in_revision_workflow($post)) { + $status = $post->post_mime_type; + } + + return $status; + } + + public function fltImmediateCaption($caption, $post) { + if (rvy_in_revision_workflow($post)) { + $caption = __('Publish on approval', 'revisionary'); + } + + return $caption; + } + + public function post_submit_meta_box($post, $args = []) + { + if (rvy_is_revision_status($post->post_mime_type)) { + require_once(dirname(__FILE__) . '/RevisionEditSubmitMetabox.php'); + RvyRevisionEditSubmitMetabox::post_submit_meta_box($post, $args); + } + } + + public function act_replace_publish_metabox($post_type, $post) + { + global $wp_meta_boxes; + + if ('attachment' != $post_type) { + if (!empty($wp_meta_boxes[$post_type]['side']['core']['submitdiv'])) { + $wp_meta_boxes[$post_type]['side']['core']['submitdiv']['callback'] = [$this, 'post_submit_meta_box']; + } + } + } + + public function actSubmitMetaboxActions() { + global $post; + + $compare_link = rvy_admin_url("revision.php?revision=$post->ID"); + $compare_button = _x('Compare', 'revisions', 'revisionary'); + $compare_title = __('Compare this revision to published copy, or to other revisions', 'revisionary'); + ?> + + + ", ''); + } else { + $preview_msg = __('Revision updated.', 'revisionary'); + } + + $messages['post'][1] = $preview_msg; + $messages['page'][1] = $preview_msg; + $messages[$post->post_type][1] = $preview_msg; + + return $messages; + } +} diff --git a/admin/edit-revision-ui_rvy.php b/admin/edit-revision-ui_rvy.php index 19b1bc68..b70050ac 100644 --- a/admin/edit-revision-ui_rvy.php +++ b/admin/edit-revision-ui_rvy.php @@ -2,32 +2,113 @@ if( basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']) ) die(); +/* + * Revision Edit: UI modifications for Classic Editor + */ class RevisionaryEditRevisionUI { function __construct () { - $this->add_js(); + add_action('admin_head', [$this, 'add_js']); + //add_action('admin_head', [$this, 'add_meta_boxes']); + //add_action('admin_head', [$this, 'act_tweak_metaboxes'], 11); } - + function add_js() { + wp_enqueue_style('rvy-revision-edit', RVY_URLPATH . '/admin/rvy-revision-edit.css', [], PUBLISHPRESS_REVISIONS_VERSION); + + if (!rvy_get_option('scheduled_revisions')) { + ?> + + + + - - $priorities ) { + foreach ( $priorities as $priority => $boxes ) { + foreach ( array_keys($boxes) as $box_id ) { + // Remove Revision Notification List metabox if this user is NOT submitting a pending revision + if ( 'pending_revision_notify' == $box_id ) { + if (!$object_id || !rvy_get_option('pending_rev_notify_admin') || current_user_can('edit_post', $object_id)) { + unset( $wp_meta_boxes[$object_type][$context][$priority][$box_id] ); + } + } + } + } + } } + */ } diff --git a/admin/filters-admin-ui-item_rvy.php b/admin/filters-admin-ui-item_rvy.php index 7705dc34..81b75a90 100644 --- a/admin/filters-admin-ui-item_rvy.php +++ b/admin/filters-admin-ui-item_rvy.php @@ -2,159 +2,19 @@ if( basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']) ) die(); -class RevisionaryAdminFiltersItemUI { +/* + * Post Edit UI: main post (not revision) editor filters which apply for both Gutenberg and Classic Editor + */ +class RevisionaryPostEditorMetaboxes { private $pending_revisions = array(); private $future_revisions = array(); - // note: in current implementations, this must be instatiated on admin_head action function __construct () { - $this->add_js(); - $this->add_meta_boxes(); - $this->act_tweak_metaboxes(); - } - - function add_js() { - global $post, $revisionary; - - if ( ! $revisionary->isBlockEditorActive() ) { - if ( ! empty($post->post_type) ) - $object_type = $post->post_type; - else - $object_type = awp_post_type_from_uri(); - - $object_id = rvy_detect_post_id(); - - if (!$object_id || agp_user_can('edit_post', $object_id, '', ['skip_revision_allowance' => true])) { - // for logged user who can fully edit a published post, clarify the meaning of setting future publish date - - // @todo: pass post id value, admin URL into JS to support ajax call - ?> - - - -isBlockEditorActive() ) :?> - - + add_action('admin_head', [$this, 'actAdminBarPreventPostClobber'], 5); + add_action('admin_head', [$this, 'add_meta_boxes']); + add_action('admin_head', [$this, 'act_tweak_metaboxes'], 11); - - - post_type); - - // Use simpler criteria due to early execution of revisions.php access check in revisionary_main.php - $can_publish = $type_obj && ( - isset($type_obj->cap->edit_published_posts) - && !empty($current_user->allcaps[$type_obj->cap->edit_published_posts]) - && (($current_user->ID == $parent_post->ID) || !empty($current_user->allcaps[$type_obj->cap->edit_published_posts])) - ); - */ - - if (!$revisionary->canEditPost($post, ['simple_cap_check' => true]) && defined('RVY_REVISOR_SUPPRESS_REVISIONS_LINK')):?> - - -$property_name ) ) { + echo $this->$property_name; + + } elseif ( ! empty( $_GET['post'] ) ) { + $args = array( 'format' => 'list', 'parent' => false ); + rvy_list_post_revisions( (int) $_GET['post'], $status, $args ); + } + } + + function rvy_metabox_revisions_pending() { + self::rvy_metabox_revisions( 'pending-revision' ); + } + + function rvy_metabox_revisions_future() { + self::rvy_metabox_revisions( 'future-revision' ); + } function act_tweak_metaboxes() { static $been_here; @@ -193,8 +65,6 @@ function act_tweak_metaboxes() { if ( empty($wp_meta_boxes) ) return; - $src_name = 'post'; - $object_type = awp_post_type_from_uri(); if ( empty($wp_meta_boxes[$object_type]) ) @@ -215,16 +85,34 @@ function act_tweak_metaboxes() { } elseif ( 'future_revisions' == $box_id ) { if ( ! $object_id || ! $this->future_revisions = rvy_list_post_revisions( $object_id, 'future-revision', array( 'format' => 'list', 'parent' => false, 'echo' => false ) ) ) unset( $wp_meta_boxes[$object_type][$context][$priority][$box_id] ); - - // Remove Revision Notification List metabox if this user is NOT submitting a pending revision - } elseif ( 'pending_revision_notify' == $box_id ) { - if (!$object_id || !rvy_get_option('pending_rev_notify_admin') || agp_user_can('edit_post', $object_id, '', ['skip_revision_allowance' => true])) { - unset( $wp_meta_boxes[$object_type][$context][$priority][$box_id] ); - } } } } } } + public function fltDisableExceptionUI($disable, $src_name, $post_id, $post_type = '') { + if (!$post_id) { + // Permissions version < 3.1.4 always passes zero value $post_id + $post_id = rvy_detect_post_id(); + } + + if ($post_id && rvy_in_revision_workflow($post_id)) { + return true; + } + + return $disable; + } + + function actAdminBarPreventPostClobber() { + global $post; + + // prevent PHP Notice from Multiple Authors code: + // Notice: Trying to get property of non-object in F:\www\wp50\wp-content\plugins\publishpress-multiple-authors\core\Classes\Utils.php on line 309 + // @todo: address within MA + if (defined('PUBLISHPRESS_MULTIPLE_AUTHORS_VERSION') && !empty($_REQUEST['post'])) { + $post = get_post((int) $_REQUEST['post']); + } + } + } // end class diff --git a/admin/history_rvy.php b/admin/history_rvy.php index 7c7ed5fc..6a852b5a 100644 --- a/admin/history_rvy.php +++ b/admin/history_rvy.php @@ -1,12 +1,14 @@ revision_status = ['draft-revision', 'pending-revision']; + add_action('load-revision.php', [$this, 'actLoadRevision']); add_action('admin_enqueue_scripts', [$this, 'actEnqueueScripts'], 10, 1); @@ -40,9 +42,9 @@ function actCompareRevisionsTweakUI() { // Hide Restore button if user does not have permission if ($_post = get_post($revision_id)) { - if (!rvy_is_revision_status($_post->post_status)) { + if (!rvy_in_revision_workflow($_post)) { if ($parent_post = get_post($_post->post_parent)) { - if (!$revisionary->canEditPost($parent_post, ['skip_revision_allowance' => true])) : + if (!$revisionary->canEditPost($parent_post)) : ?>