Passed
Push — master ( e95607...5b55be )
by Sudar
15:04
created

BaseModule   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 423
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 99
dl 0
loc 423
rs 9.92
c 0
b 0
f 0
wmc 31

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
A get_name() 0 2 1
A get_hidden_box_user_meta_field() 0 5 2
A get_field_slug() 0 2 1
A delete() 0 12 1
A get_success_message() 0 8 3
A append_to_js_array() 0 2 1
A process() 0 28 2
A parse_cron_filters() 0 16 2
A register() 0 10 2
A get_cron_hook() 0 2 1
A get_action() 0 2 1
A is_scheduled() 0 2 1
A render_box() 0 12 2
A schedule_deletion() 0 10 2
A setup_metabox() 0 7 1
A is_hidden() 0 6 2
A filter_js_array() 0 18 3
A get_cron_label() 0 2 1
A get_task_list_link() 0 5 1
1
<?php
2
3
namespace BulkWP\BulkDelete\Core\Base;
4
5
use BulkWP\BulkDelete\Core\Base\Mixin\Renderer;
6
7
defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
8
9
/**
10
 * Encapsulates the Bulk Delete Meta box Module Logic.
11
 *
12
 * All Bulk Delete Meta box Modules should extend this class.
13
 * This class extends Renderer Mixin class since Bulk Delete still supports PHP 5.3.
14
 * Once PHP 5.3 support is dropped, Renderer will be implemented as a Trait and this class will `use` it.
15
 *
16
 * @since 6.0.0
17
 */
18
abstract class BaseModule extends Renderer {
19
	/**
20
	 * Item Type. Possible values 'posts', 'pages', 'users' etc.
21
	 *
22
	 * @var string
23
	 */
24
	protected $item_type;
25
26
	/**
27
	 * The hook suffix of the screen where this meta box would be shown.
28
	 *
29
	 * @var string
30
	 */
31
	protected $page_hook_suffix;
32
33
	/**
34
	 * Slug of the page where this module will be shown.
35
	 *
36
	 * @var string
37
	 */
38
	protected $page_slug;
39
40
	/**
41
	 * Slug of the meta box.
42
	 *
43
	 * @var string
44
	 */
45
	protected $meta_box_slug;
46
47
	/**
48
	 * Action in which the delete operation should be performed.
49
	 *
50
	 * @var string
51
	 */
52
	protected $action = '';
53
54
	/**
55
	 * Hook for scheduler.
56
	 *
57
	 * @var string
58
	 */
59
	protected $cron_hook;
60
61
	/**
62
	 * Url of the scheduler addon.
63
	 *
64
	 * @var string
65
	 */
66
	protected $scheduler_url;
67
68
	/**
69
	 * Messages shown to the user.
70
	 *
71
	 * @var array
72
	 */
73
	protected $messages = array(
74
		'box_label'         => '',
75
		'cron_label'        => '',
76
		'validation_error'  => '',
77
		'confirm_deletion'  => '',
78
		'scheduled'         => '',
79
		'nothing_to_delete' => '',
80
		'deleted_one'       => '',
81
		'deleted_multiple'  => '',
82
	);
83
84
	/**
85
	 * Initialize and setup variables.
86
	 *
87
	 * @return void
88
	 */
89
	abstract protected function initialize();
90
91
	/**
92
	 * Render the Modules.
93
	 *
94
	 * @return void
95
	 */
96
	abstract public function render();
97
98
	/**
99
	 * Process common filters.
100
	 *
101
	 * @param array $request Request array.
102
	 *
103
	 * @return array User options.
104
	 */
105
	abstract protected function parse_common_filters( $request );
106
107
	/**
108
	 * Process user input and create metabox options.
109
	 *
110
	 * @param array $request Request array.
111
	 * @param array $options User options.
112
	 *
113
	 * @return array User options.
114
	 */
115
	abstract protected function convert_user_input_to_options( $request, $options );
116
117
	/**
118
	 * Perform the deletion.
119
	 *
120
	 * @param array $options Array of Delete options.
121
	 *
122
	 * @return int Number of items that were deleted.
123
	 */
124
	abstract protected function do_delete( $options );
125
126
	/**
127
	 * Create new instances of Modules.
128
	 */
129
	public function __construct() {
130
		$this->initialize();
131
	}
132
133
	/**
134
	 * Register.
135
	 *
136
	 * @param string $hook_suffix Page Hook Suffix.
137
	 * @param string $page_slug   Page slug.
138
	 */
139
	public function register( $hook_suffix, $page_slug ) {
140
		$this->page_hook_suffix = $hook_suffix;
141
		$this->page_slug        = $page_slug;
142
143
		add_action( "add_meta_boxes_{$this->page_hook_suffix}", array( $this, 'setup_metabox' ) );
144
145
		add_filter( 'bd_javascript_array', array( $this, 'filter_js_array' ) );
146
147
		if ( ! empty( $this->action ) ) {
148
			add_action( 'bd_' . $this->action, array( $this, 'process' ) );
149
		}
150
	}
151
152
	/**
153
	 * Setup the meta box.
154
	 */
155
	public function setup_metabox() {
156
		add_meta_box(
157
			$this->meta_box_slug,
158
			$this->messages['box_label'],
159
			array( $this, 'render_box' ),
160
			$this->page_hook_suffix,
161
			'advanced'
162
		);
163
	}
164
165
	/**
166
	 * Render the meta box.
167
	 */
168
	public function render_box() {
169
		if ( $this->is_hidden() ) {
170
			printf(
171
				/* translators: 1 Module url */
172
				__( 'This section just got enabled. Kindly <a href = "%1$s">refresh</a> the page to fully enable it.', 'bulk-delete' ),
173
				'admin.php?page=' . esc_attr( $this->page_slug )
174
			);
175
176
			return;
177
		}
178
179
		$this->render();
180
	}
181
182
	/**
183
	 * Is the current meta box hidden by user.
184
	 *
185
	 * @return bool True, if hidden. False, otherwise.
186
	 */
187
	protected function is_hidden() {
188
		$current_user    = wp_get_current_user();
189
		$user_meta_field = $this->get_hidden_box_user_meta_field();
190
		$hidden_boxes    = get_user_meta( $current_user->ID, $user_meta_field, true );
191
192
		return is_array( $hidden_boxes ) && in_array( $this->meta_box_slug, $hidden_boxes, true );
193
	}
194
195
	/**
196
	 * Get the user meta field that stores the status of the hidden meta boxes.
197
	 *
198
	 * @return string Name of the User Meta field.
199
	 */
200
	protected function get_hidden_box_user_meta_field() {
201
		if ( 'posts' === $this->item_type ) {
202
			return 'metaboxhidden_toplevel_page_bulk-delete-posts';
203
		} else {
204
			return 'metaboxhidden_bulk-wp_page_' . $this->page_slug;
205
		}
206
	}
207
208
	/**
209
	 * Filter the js array.
210
	 *
211
	 * Use `append_to_js_array` function to append any module specific js options.
212
	 *
213
	 * @see $this->append_to_js_array
214
	 *
215
	 * @param array $js_array JavaScript Array.
216
	 *
217
	 * @return array Modified JavaScript Array
218
	 */
219
	public function filter_js_array( $js_array ) {
220
		$js_array['dt_iterators'][] = '_' . $this->field_slug;
221
222
		$js_array['pre_action_msg'][ $this->action ] = $this->action . '_confirm';
223
		$js_array['error_msg'][ $this->action ]      = $this->action . '_error';
224
225
		$js_array['msg'][ $this->action . '_confirm' ] = __( 'Are you sure you want to delete all the posts based on the selected option?', 'bulk-delete' );
226
		$js_array['msg'][ $this->action . '_error' ]   = __( 'Please select posts from at least one option', 'bulk-delete' );
227
228
		if ( ! empty( $this->messages['confirm_deletion'] ) ) {
229
			$js_array['msg'][ $this->action . '_confirm' ] = $this->messages['confirm_deletion'];
230
		}
231
232
		if ( ! empty( $this->messages['validation_error'] ) ) {
233
			$js_array['msg'][ $this->action . '_error' ] = $this->messages['validation_error'];
234
		}
235
236
		return $this->append_to_js_array( $js_array );
237
	}
238
239
	/**
240
	 * Append any module specific options to JS array.
241
	 *
242
	 * This function will be overridden by the child classes.
243
	 *
244
	 * @param array $js_array JavaScript Array.
245
	 *
246
	 * @return array Modified JavaScript Array
247
	 */
248
	protected function append_to_js_array( $js_array ) {
249
		return $js_array;
250
	}
251
252
	/**
253
	 * Helper function for processing deletion.
254
	 * Setups up cron and invokes the actual delete method.
255
	 *
256
	 * @param array $request Request array.
257
	 */
258
	public function process( $request ) {
259
		$options      = $this->parse_common_filters( $request );
260
		$options      = $this->convert_user_input_to_options( $request, $options );
261
		$cron_options = $this->parse_cron_filters( $request );
262
263
		/**
264
		 * Filter the processed delete options.
265
		 *
266
		 * @since 6.0.0
267
		 *
268
		 * @param array $options Processed options.
269
		 * @param array $request Request array.
270
		 * @param \BulkWP\BulkDelete\Core\Base\BaseModule The delete module.
271
		 */
272
		$options = apply_filters( 'bd_processed_delete_options', $options, $request, $this );
273
274
		if ( $this->is_scheduled( $cron_options ) ) {
275
			$msg = $this->schedule_deletion( $cron_options, $options );
276
		} else {
277
			$items_deleted = $this->delete( $options );
278
			$msg           = sprintf( $this->get_success_message( $items_deleted ), $items_deleted );
279
		}
280
281
		add_settings_error(
282
			$this->page_slug,
283
			$this->action,
284
			$msg,
285
			'updated'
286
		);
287
	}
288
289
	/**
290
	 * Delete items based on delete options.
291
	 *
292
	 * @param array $options Delete Options.
293
	 *
294
	 * @return int Number of items deleted.
295
	 */
296
	public function delete( $options ) {
297
		/**
298
		 * Filter delete options before deleting items.
299
		 *
300
		 * @since 6.0.0 Added `Modules` parameter.
301
		 *
302
		 * @param array $options Delete options.
303
		 * @param \BulkWP\BulkDelete\Core\Base\BaseModule Modules that is triggering deletion.
304
		 */
305
		$options = apply_filters( 'bd_delete_options', $options, $this );
306
307
		return $this->do_delete( $options );
308
	}
309
310
	/**
311
	 * Get Success Message.
312
	 *
313
	 * @param int $items_deleted Number of items that were deleted.
314
	 *
315
	 * @return string Success message.
316
	 */
317
	protected function get_success_message( $items_deleted ) {
318
		if ( 0 === $items_deleted ) {
319
			if ( ! empty( $this->messages['nothing_to_delete'] ) ) {
320
				return $this->messages['nothing_to_delete'];
321
			}
322
		}
323
324
		return _n( $this->messages['deleted_one'], $this->messages['deleted_multiple'], $items_deleted, 'bulk-delete' ); // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralSingle, WordPress.WP.I18n.NonSingularStringLiteralPlural
325
	}
326
327
	/**
328
	 * Getter for cron_hook.
329
	 *
330
	 * @return string Cron Hook name.
331
	 */
332
	public function get_cron_hook() {
333
		return $this->cron_hook;
334
	}
335
336
	/**
337
	 * Getter for field slug.
338
	 *
339
	 * @return string Field Slug.
340
	 */
341
	public function get_field_slug() {
342
		return $this->field_slug;
343
	}
344
345
	/**
346
	 * Getter for action.
347
	 *
348
	 * @return string Modules action.
349
	 */
350
	public function get_action() {
351
		return $this->action;
352
	}
353
354
	/**
355
	 * Is the current deletion request a scheduled request?
356
	 *
357
	 * @param array $cron_options Request object.
358
	 *
359
	 * @return bool True if it is a scheduled request, False otherwise.
360
	 */
361
	protected function is_scheduled( $cron_options ) {
362
		return $cron_options['is_scheduled'];
363
	}
364
365
	/**
366
	 * Schedule Deletion of items.
367
	 *
368
	 * @param array $cron_options Cron options.
369
	 * @param array $options      Deletion option.
370
	 *
371
	 * @return string Message.
372
	 */
373
	protected function schedule_deletion( $cron_options, $options ) {
374
		$options['cron_label'] = $cron_options['cron_label'];
375
376
		if ( '-1' === $cron_options['frequency'] ) {
377
			wp_schedule_single_event( $cron_options['start_time'], $this->cron_hook, array( $options ) );
378
		} else {
379
			wp_schedule_event( $cron_options['start_time'], $cron_options['frequency'], $this->cron_hook, array( $options ) );
380
		}
381
382
		return $this->messages['scheduled'] . ' ' . $this->get_task_list_link();
383
	}
384
385
	/**
386
	 * Get the link to the page that lists all the scheduled tasks.
387
	 *
388
	 * @return string Link to scheduled tasks page.
389
	 */
390
	protected function get_task_list_link() {
391
		return sprintf(
392
			/* translators: 1 Cron page url */
393
			__( 'See the full list of <a href = "%s">scheduled tasks</a>', 'bulk-delete' ),
394
			get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=' . \Bulk_Delete::CRON_PAGE_SLUG
395
		);
396
	}
397
398
	/**
399
	 * Parse request and create cron options.
400
	 *
401
	 * @param array $request Request array.
402
	 *
403
	 * @return array Parsed cron option.
404
	 */
405
	protected function parse_cron_filters( $request ) {
406
		$cron_options = array(
407
			'is_scheduled' => false,
408
		);
409
410
		$scheduled = bd_array_get_bool( $request, 'smbd_' . $this->field_slug . '_cron', false );
411
412
		if ( $scheduled ) {
413
			$cron_options['is_scheduled'] = true;
414
			$cron_options['frequency']    = sanitize_text_field( $request[ 'smbd_' . $this->field_slug . '_cron_freq' ] );
415
			$cron_options['start_time']   = bd_get_gmt_offseted_time( sanitize_text_field( $request[ 'smbd_' . $this->field_slug . '_cron_start' ] ) );
416
417
			$cron_options['cron_label'] = $this->get_cron_label();
418
		}
419
420
		return $cron_options;
421
	}
422
423
	/**
424
	 * Get the human readable label for the Schedule job.
425
	 *
426
	 * @return string Human readable label for schedule job.
427
	 */
428
	public function get_cron_label() {
429
		return $this->messages['cron_label'];
430
	}
431
432
	/**
433
	 * Get the name of the module.
434
	 *
435
	 * This is used as the key to identify the module from page.
436
	 *
437
	 * @return string Module name.
438
	 */
439
	public function get_name() {
440
		return bd_get_short_class_name( $this );
441
	}
442
}
443