class-wp-revisions-control-bulk-actions.php 6.21 KB
Newer Older
Erick Hitter's avatar
Erick Hitter committed
1 2 3 4 5 6 7 8 9 10 11
<?php
/**
 * Bulk actions.
 *
 * @package WP_Revisions_Control
 */

/**
 * Class WP_Revisions_Control_Bulk_Actions.
 */
class WP_Revisions_Control_Bulk_Actions {
12 13 14 15 16 17 18
	/**
	 * Singleton.
	 *
	 * @var static
	 */
	private static $__instance;

Erick Hitter's avatar
Erick Hitter committed
19 20 21 22 23 24 25
	/**
	 * Supported post types.
	 *
	 * @var array
	 */
	protected $post_types;

26 27 28 29 30 31 32
	/**
	 * Base for bulk action names.
	 *
	 * @var string
	 */
	protected $action_base = 'wp_rev_ctl_bulk_';

Erick Hitter's avatar
Erick Hitter committed
33 34 35 36 37 38 39 40
	/**
	 * Custom bulk actions.
	 *
	 * @var array
	 */
	protected $actions;

	/**
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
	 * Silence is golden!
	 */
	private function __construct() {}

	/**
	 * Singleton implementation.
	 *
	 * @param array $post_types Supported post types, used only on instantiation.
	 * @return static
	 */
	public static function get_instance( $post_types = array() ) {
		if ( ! is_a( static::$__instance, __CLASS__ ) ) {
			static::$__instance = new self();

			static::$__instance->setup( $post_types );
		}

		return static::$__instance;
	}

	/**
	 * One-time actions.
Erick Hitter's avatar
Erick Hitter committed
63 64 65
	 *
	 * @param array $post_types Supported post types.
	 */
66
	public function setup( $post_types ) {
Erick Hitter's avatar
Erick Hitter committed
67 68 69 70 71 72 73
		if ( empty( $post_types ) || ! is_array( $post_types ) ) {
			return;
		}

		$this->post_types = $post_types;
		$this->register_actions();

74
		add_action( 'load-edit.php', array( $this, 'register_admin_hooks' ) );
Erick Hitter's avatar
Erick Hitter committed
75
		add_filter( 'removable_query_args', array( $this, 'remove_message_query_args' ) );
Erick Hitter's avatar
Erick Hitter committed
76 77 78 79 80 81
	}

	/**
	 * Register custom actions.
	 */
	protected function register_actions() {
82
		$actions = array();
Erick Hitter's avatar
Erick Hitter committed
83

84 85 86 87 88 89 90 91 92
		$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
93 94 95 96 97 98 99

		$this->actions = $actions;
	}

	/**
	 * Register various hooks.
	 */
100
	public function register_admin_hooks() {
Erick Hitter's avatar
Erick Hitter committed
101 102 103 104 105 106 107 108 109 110 111 112
		$screen = get_current_screen();

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

		$post_types = array_keys( $this->post_types );

		if ( ! in_array( $screen->post_type, $post_types, true ) ) {
			return;
		}

Erick Hitter's avatar
Erick Hitter committed
113
		$post_type_caps = get_post_type_object( $screen->post_type )->cap;
114 115 116 117 118
		$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 )
		);
Erick Hitter's avatar
Erick Hitter committed
119 120 121 122 123 124 125 126 127 128
		$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
129 130 131 132 133 134
		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 );
Erick Hitter's avatar
Erick Hitter committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
		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';
156
		$args[] = $this->action_base . 'nonce';
Erick Hitter's avatar
Erick Hitter committed
157 158

		return $args;
Erick Hitter's avatar
Erick Hitter committed
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	}

	/**
	 * 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;
		}

184
		$response = array_fill_keys( $this->get_message_query_args(), 0 );
185

Erick Hitter's avatar
Erick Hitter committed
186
		switch ( str_replace( $this->action_base, '', $action ) ) {
187 188
			case 'purge_all':
				$this->purge_all( $ids );
189
				$response[ $action ] = 1;
190 191 192 193
				break;

			case 'purge_excess':
				$this->purge_excess( $ids );
194
				$response[ $action ] = 1;
195 196
				break;

197 198 199
			case 'nonce':
				break;

200
			default:
201
				$response[ $this->action_base . 'missing' ] = 1;
202 203 204
				break;
		}

Erick Hitter's avatar
Erick Hitter committed
205
		if ( is_array( $response ) ) {
206 207
			$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
208 209
		}

Erick Hitter's avatar
Erick Hitter committed
210 211
		return $redirect_to;
	}
212 213 214 215 216 217 218

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

221
		foreach ( $ids as $id ) {
222
			$plugin->do_purge_all( $id );
223 224 225 226 227 228 229 230 231
		}
	}

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

234
		foreach ( $ids as $id ) {
235
			$plugin->do_purge_excess( $id );
236 237
		}
	}
Erick Hitter's avatar
Erick Hitter committed
238 239 240 241 242 243 244

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

245 246 247 248 249 250 251 252 253
		$nonce_key = $this->action_base . 'nonce';

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

Erick Hitter's avatar
Erick Hitter committed
254
		foreach ( $this->get_message_query_args() as $arg ) {
255
			if ( isset( $_GET[ $arg ] ) && 1 === (int) $_GET[ $arg ] ) {
Erick Hitter's avatar
Erick Hitter committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
				$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;

282 283 284
			case 'nonce':
				break;

Erick Hitter's avatar
Erick Hitter committed
285 286 287 288 289 290 291 292 293 294
			default:
			case 'missing':
				$message = __(
					'WP Revisions Control encountered an unspecified error.',
					'wp_revisions_control'
				);
				$type    = 'error';
				break;
		}

295 296 297 298
		if ( ! isset( $message, $type ) ) {
			return;
		}

Erick Hitter's avatar
Erick Hitter committed
299 300 301 302 303 304
		?>
		<div class="notice is-dismissible <?php echo esc_attr( $type ); ?>">
			<p><?php echo esc_html( $message ); ?></p>
		</div>
		<?php
	}
Erick Hitter's avatar
Erick Hitter committed
305
}