<?php /** * Offload "Edit" * * @package Bulk_Actions_Cron_Offload */ namespace Automattic\WP\Bulk_Actions_Cron_Offload; /** * Class Edit */ class Edit { /** * Class constants */ const ACTION = 'edit'; const ADMIN_NOTICE_KEY = 'bulk_actions_cron_offload_edit'; /** * Register this bulk process' hooks */ public static function register_hooks() { add_action( Main::build_hook( self::ACTION ), array( __CLASS__, 'process' ) ); add_action( Main::build_cron_hook( self::ACTION ), array( __CLASS__, 'process_via_cron' ) ); add_action( 'admin_notices', array( __CLASS__, 'admin_notices' ) ); add_filter( 'posts_where', array( __CLASS__, 'hide_posts_pending_move' ), 999, 2 ); } /** * Handle a request to edit some posts * * @param object $vars Bulk-request variables. */ public static function process( $vars ) { $action_scheduled = Main::next_scheduled( $vars ); if ( empty( $action_scheduled ) ) { Main::schedule_processing( $vars ); Main::do_admin_redirect( self::ADMIN_NOTICE_KEY, true ); } else { Main::do_admin_redirect( self::ADMIN_NOTICE_KEY, false ); } } /** * Cron callback to edit requested items * * @param object $vars Bulk-request variables. */ public static function process_via_cron( $vars ) { // Nothing to edit. if ( ! is_array( $vars->posts ) || empty( $vars->posts ) ) { do_action( 'bulk_actions_cron_offload_edit_request_no_posts', $vars->posts, $vars ); return; } // We want to use `bulk_edit_posts()`. require_once ABSPATH . '/wp-admin/includes/post.php'; // `bulk_edit_posts()` takes an array, normally `$_REQUEST`, so we convert back. $request_array = get_object_vars( $vars ); unset( $request_array['action'] ); unset( $request_array['user_id'] ); // Modify some keys to match `bulk_edit_post()`'s expectations. $request_array['post'] = $request_array['posts']; unset( $request_array['posts'] ); if ( ! is_null( $request_array['post_sticky'] ) ) { $request_array['sticky'] = $request_array['post_sticky']; } unset( $request_array['post_sticky'] ); if ( is_null( $request_array['post_status'] ) || 'all' === $request_array['post_status'] ) { $request_array['_status'] = -1; } else { $request_array['_status'] = $request_array['post_status']; } unset( $request_array['post_status'] ); // `bulk_edit_posts()` calls `current_user_can()`, so we make sure it can. wp_set_current_user( $vars->user_id ); // Perform bulk edit. $results = bulk_edit_posts( $request_array ); $edited = $results['updated']; $error = $results['skipped']; $locked = $results['locked']; // `bulk_edit_posts()` mixes these without indicating which it was. $auth_error = $error; $results = compact( 'edited', 'locked', 'auth_error', 'error' ); do_action( 'bulk_actions_cron_offload_edit_request_completed', $results, $vars ); } /** * Let the user know what's going on */ public static function admin_notices() { $screen = get_current_screen(); $type = ''; $message = ''; if ( isset( $_REQUEST[ self::ADMIN_NOTICE_KEY ] ) ) { if ( 1 === (int) $_REQUEST[ self::ADMIN_NOTICE_KEY ] ) { $type = 'success'; $message = __( 'Success! The selected posts will be edited shortly.', 'bulk-actions-cron-offload' ); } else { $type = 'error'; $message = __( 'The requested edits are already pending for the chosen posts.', 'bulk-actions-cron-offload' ); } } elseif ( 'edit' === $screen->base ) { if ( isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'] ) { return; } $status = isset( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all'; $pending = Main::get_post_ids_for_pending_events( self::ACTION, $screen->post_type, $status ); if ( ! empty( $pending ) ) { $type = 'warning'; $message = __( 'Some items that would normally be shown here are waiting to be edited. These items are hidden until they are processed.', 'bulk-actions-cron-offload' ); } } Main::render_admin_notice( $type, $message ); } /** * When an edit is pending for a given post type, hide those posts in the admin * * @param string $where Posts' WHERE clause. * @param object $q WP_Query object. * @return string */ public static function hide_posts_pending_move( $where, $q ) { if ( ! is_admin() || ! $q->is_main_query() ) { return $where; } if ( 'edit' !== get_current_screen()->base ) { return $where; } if ( 'trash' === $q->get( 'post_status' ) ) { return $where; } $post__not_in = Main::get_post_ids_for_pending_events( self::ACTION, $q->get( 'post_type' ), $q->get( 'post_status' ) ); if ( ! empty( $post__not_in ) ) { $post__not_in = implode( ',', $post__not_in ); $where .= ' AND ID NOT IN(' . $post__not_in . ')'; } return $where; } } Edit::register_hooks();