Skip to content
Snippets Groups Projects
class-wp-revisions-control-bulk-actions.php 5.69 KiB
Newer Older
Erick Hitter's avatar
Erick Hitter committed
<?php
/**
 * Bulk actions.
 *
 * @package WP_Revisions_Control
 */

use WP_Revisions_Control\Singleton;

Erick Hitter's avatar
Erick Hitter committed
/**
 * Class WP_Revisions_Control_Bulk_Actions.
 */
class WP_Revisions_Control_Bulk_Actions {
Erick Hitter's avatar
Erick Hitter committed
	/**
	 * Supported post types.
	 *
	 * @var array
	 */
	/**
	 * Base for bulk action names.
	 *
	 * @var string
	 */
	protected $action_base = 'wp_rev_ctl_bulk_';

Erick Hitter's avatar
Erick Hitter committed
	/**
	 * Custom bulk actions.
	 *
	 * @var array
	 */
	protected $actions;

	/**
	 * One-time actions.
	public function setup() {
		$this->post_types = WP_Revisions_Control::get_instance()->get_post_types();

		if ( empty( $this->post_types ) || ! is_array( $this->post_types ) ) {
Erick Hitter's avatar
Erick Hitter committed
			return;
		}

		$this->register_actions();

		add_action( 'load-edit.php', array( $this, 'register_admin_hooks' ) );
		add_filter( 'removable_query_args', array( $this, 'remove_message_query_args' ) );
Erick Hitter's avatar
Erick Hitter committed
	}

	/**
	 * Register custom actions.
	 */
	protected function register_actions() {
		$actions = array();
		$actions[ $this->action_base . 'purge_excess' ] = __(
			'Purge excess revisions',
			'wp_revisions_control'
		);

		$actions[ $this->action_base . 'purge_all' ] = __(
			'Purge ALL revisions',
			'wp_revisions_control'
		);
Erick Hitter's avatar
Erick Hitter committed

		$this->actions = $actions;
	}

	/**
	 * Register various hooks.
	 */
	public function register_admin_hooks() {
Erick Hitter's avatar
Erick Hitter committed
		$screen = get_current_screen();

		if ( null === $screen ) {
			return;
		}

		if ( ! array_key_exists( $screen->post_type, $this->post_types ) ) {
		$post_type_caps = get_post_type_object( $screen->post_type )->cap;
		$user_can       = (
			current_user_can( $post_type_caps->edit_posts ) &&
			current_user_can( $post_type_caps->edit_published_posts ) &&
			current_user_can( $post_type_caps->edit_others_posts )
		);
		$user_can       = apply_filters(
			'wp_revisions_control_current_user_can_bulk_actions',
			$user_can,
			$screen->post_type
		);

		if ( ! $user_can ) {
			return;
		}

Erick Hitter's avatar
Erick Hitter committed
		if ( 'edit' !== $screen->base ) {
			return;
		}

		add_filter( 'bulk_actions-' . $screen->id, array( $this, 'add_actions' ) );
		add_filter( 'handle_bulk_actions-' . $screen->id, array( $this, 'handle_action' ), 10, 3 );
		add_action( 'admin_notices', array( $this, 'admin_notices' ) );
	}

	/**
	 * Remove message query arguments to prevent re-display.
	 *
	 * @param array $args Array of query variables to remove from URL.
	 * @return array
	 */
	public function remove_message_query_args( $args ) {
		return array_merge( $args, $this->get_message_query_args() );
	}

	/**
	 * Return array of supported query args that trigger admin notices.
	 *
	 * @return array
	 */
	protected function get_message_query_args() {
		$args   = array_keys( $this->actions );
		$args[] = $this->action_base . 'missing';
		$args[] = $this->action_base . 'nonce';

		return $args;
Erick Hitter's avatar
Erick Hitter committed
	}

	/**
	 * Add our actions.
	 *
	 * @param string[] $actions Array of available actions.
	 * @return array
	 */
	public function add_actions( $actions ) {
		return array_merge( $actions, $this->actions );
	}

	/**
	 * Handle our bulk actions.
	 *
	 * @param string $redirect_to Redirect URL.
	 * @param string $action      Bulk action being taken.
	 * @param array  $ids         Object IDs to manipulate.
	 * @return string
	 */
	public function handle_action( $redirect_to, $action, $ids ) {
		if ( ! array_key_exists( $action, $this->actions ) ) {
			return $redirect_to;
		}

		$response = array_fill_keys( $this->get_message_query_args(), 0 );
		switch ( str_replace( $this->action_base, '', $action ) ) {
			case 'purge_all':
				$this->purge_all( $ids );
				$response[ $action ] = 1;
				break;

			case 'purge_excess':
				$this->purge_excess( $ids );
				$response[ $action ] = 1;
				$response[ $this->action_base . 'missing' ] = 1;
		if ( is_array( $response ) ) {
			$response[ $this->action_base . 'nonce' ] = wp_create_nonce( $this->action_base );
			$redirect_to                              = add_query_arg( $response, $redirect_to );
Erick Hitter's avatar
Erick Hitter committed
		return $redirect_to;
	}

	/**
	 * Remove all revisions from the given IDs.
	 *
	 * @param array $ids Object IDs.
	 */
	protected function purge_all( $ids ) {
		$plugin = WP_Revisions_Control::get_instance();

		foreach ( $ids as $id ) {
			$plugin->do_purge_all( $id );
		}
	}

	/**
	 * Remove excess revisions from the given IDs.
	 *
	 * @param array $ids Object IDs.
	 */
	protected function purge_excess( $ids ) {
		$plugin = WP_Revisions_Control::get_instance();

		foreach ( $ids as $id ) {
			$plugin->do_purge_excess( $id );

	/**
	 * Render admin notices.
	 */
	public function admin_notices() {
		$message = null;

		$nonce_key = $this->action_base . 'nonce';

		if (
			! isset( $_GET[ $nonce_key ] ) ||
			! wp_verify_nonce( sanitize_text_field( $_GET[ $nonce_key ] ), $this->action_base )
		) {
			return;
		}

		foreach ( $this->get_message_query_args() as $arg ) {
			if ( isset( $_GET[ $arg ] ) && 1 === (int) $_GET[ $arg ] ) {
				$message = $arg;
				break;
			}
		}

		if ( null === $message ) {
			return;
		}

		$type = 'updated';

		switch ( str_replace( $this->action_base, '', $message ) ) {
			case 'purge_all':
				$message = __(
					'Purged all revisions.',
					'wp_revisions_control'
				);
				break;

			case 'purge_excess':
				$message = __(
					'Purged excess revisions.',
					'wp_revisions_control'
				);
				break;

			default:
			case 'missing':
				$message = __(
					'WP Revisions Control encountered an unspecified error.',
					'wp_revisions_control'
				);
				$type    = 'error';
				break;
		}

		if ( ! isset( $message, $type ) ) {
			return;
		}

		?>
		<div class="notice is-dismissible <?php echo esc_attr( $type ); ?>">
			<p><?php echo esc_html( $message ); ?></p>
		</div>
		<?php
	}