Passed
Push — 178-feature/delete-terms--by-p... ( a57d30...18363f )
by Rajan
12:03
created

TermsModule   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 363
Duplicated Lines 0 %

Test Coverage

Coverage 88.89%

Importance

Changes 0
Metric Value
eloc 115
dl 0
loc 363
ccs 104
cts 117
cp 0.8889
rs 9.6
c 0
b 0
f 0
wmc 35

13 Methods

Rating   Name   Duplication   Size   Complexity  
A delete_terms_by_id() 0 19 5
A filter_js_array() 0 2 1
A delete_terms_from_query() 0 4 1
A parse_common_filters() 0 11 1
A do_delete() 0 9 2
A bd_ends_with() 0 7 2
A term_contains() 0 21 3
B get_term_id_by_name() 0 25 9
A bd_starts_with() 0 4 1
A term_starts() 0 21 3
A term_count_query() 0 32 3
A term_ends() 0 21 3
A term_query() 0 34 1
1
<?php
2
namespace BulkWP\BulkDelete\Core\Terms;
3
4
use BulkWP\BulkDelete\Core\Base\BaseModule;
5
6 1
defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
7
8
/**
9
 * Module for deleting terms.
10
 *
11
 * @since 6.0.0
12
 */
13
abstract class TermsModule extends BaseModule {
14
	/**
15
	 * Build query params for WP_Query by using delete options.
16
	 *
17
	 * Return an empty query array to short-circuit deletion.
18
	 *
19
	 * @param array $options Delete options.
20
	 *
21
	 * @return array Query.
22
	 */
23
	abstract protected function build_query( $options );
24
25
	/**
26
	 * Item type.
27
	 *
28
	 * @var string Item Type. Possible values 'posts', 'pages', 'users', 'terms' etc.
29
	 */
30
	protected $item_type = 'terms';
31
32
	/**
33
	 * Handle common filters.
34
	 *
35
	 * @param array $request Request array.
36
	 *
37
	 * @return array User options.
38
	 */
39
	protected function parse_common_filters( $request ) {
40
		$options = array();
41
42
		$options['restrict']     = bd_array_get_bool( $request, 'smbd_' . $this->field_slug . '_restrict', false );
43
		$options['limit_to']     = absint( bd_array_get( $request, 'smbd_' . $this->field_slug . '_limit_to', 0 ) );
44
		$options['force_delete'] = bd_array_get_bool( $request, 'smbd_' . $this->field_slug . '_force_delete', false );
45
46
		$options['date_op'] = bd_array_get( $request, 'smbd_' . $this->field_slug . '_op' );
47
		$options['days']    = absint( bd_array_get( $request, 'smbd_' . $this->field_slug . '_days' ) );
48
49
		return $options;
50
	}
51
52
	/**
53
	 * Filter the js array.
54
	 * This function will be overridden by the child classes.
55
	 *
56
	 * @since 5.5
57
	 *
58
	 * @param array $js_array JavaScript Array.
59
	 *
60
	 * @return array Modified JavaScript Array.
61
	 */
62
	public function filter_js_array( $js_array ) {
63
		return $js_array;
64
	}
65
66
	/**
67
	 * Perform the deletion.
68
	 *
69
	 * @param array $options Array of Delete options.
70
	 *
71
	 * @return int Number of items that were deleted.
72
	 */
73 25
	protected function do_delete( $options ) {
74 25
		$query = $this->build_query( $options );
75
76 25
		if ( empty( $query ) ) {
77
			// Short circuit deletion, if nothing needs to be deleted.
78
			return 0;
79
		}
80
81 25
		return $this->delete_terms_from_query( $query, $options );
82
	}
83
84
	/**
85
	 * Build the query using query params and then Delete posts.
86
	 *
87
	 * @param array $query   Params for WP Query.
88
	 * @param array $options Delete Options.
89
	 *
90
	 * @return int Number of posts deleted.
91
	 */
92 25
	protected function delete_terms_from_query( $query, $options ) {
93 25
		$term_ids = $this->term_query( $query, $options['taxonomy'] );
94
95 25
		return $this->delete_terms_by_id( $term_ids, $options );
96
	}
97
98
	/**
99
	 * Delete terms by ids.
100
	 *
101
	 * @param int[] $term_ids List of term ids to delete.
102
	 * @param mixed $options  user options.
103
	 *
104
	 * @return int Number of posts deleted.
105
	 */
106 25
	protected function delete_terms_by_id( $term_ids, $options ) {
107 25
		$count = 0;
108
109 25
		foreach ( $term_ids as $term_id ) {
110 18
			$term = get_term( $term_id, $options['taxonomy'] );
111
112 18
			if ( ! $term instanceof \WP_Term ) {
113
				continue;
114
			}
115
116 18
			if ( isset( $options['no_posts'] ) && $term->count > 0 ) {
117
				continue;
118
			}
119
120 18
			wp_delete_term( $term_id, $options['taxonomy'] );
121 18
			$count ++;
122
		}
123
124 25
		return $count;
125
	}
126
127
	/**
128
	 * Custom string function use to get is string start with specified string.
129
	 *
130
	 * @param string $haystack search string.
131
	 * @param string $needle   find string.
132
	 *
133
	 * @return boolean.
0 ignored issues
show
Documentation Bug introduced by
The doc comment boolean. at position 0 could not be parsed: Unknown type name 'boolean.' at position 0 in boolean..
Loading history...
134
	 */
135 2
	protected function bd_starts_with( $haystack, $needle ) {
136 2
		$length = strlen( $needle );
137
138 2
		return ( substr( $haystack, 0, $length ) === $needle );
139
	}
140
141
	/**
142
	 * Custom string function use to get is string ends with specified string.
143
	 *
144
	 * @param string $haystack search string.
145
	 * @param string $needle   find string.
146
	 *
147
	 * @return boolean.
0 ignored issues
show
Documentation Bug introduced by
The doc comment boolean. at position 0 could not be parsed: Unknown type name 'boolean.' at position 0 in boolean..
Loading history...
148
	 */
149 2
	protected function bd_ends_with( $haystack, $needle ) {
150 2
		$length = strlen( $needle );
151 2
		$substr = substr( $haystack, -$length );
152 2
		$zero   = 0;
153
154 2
		return $length === $zero ||
155 2
		( $substr === $needle );
156
	}
157
158
	/**
159
	 * Get terms which is start with specified string.
160
	 *
161
	 * @param string $term_text user input text.
162
	 * @param array  $options   user options.
163
	 *
164
	 * @return array term ids.
165
	 */
166 2
	protected function term_starts( $term_text, $options ) {
167
		$term_ids = array(
168 2
			'include' => array(),
169
			'exclude' => array(),
170
		);
171 2
		$terms    = get_terms(
172 2
			$options['taxonomy'], array(
173 2
				'hide_empty' => false,
174
			)
175
		);
176
177 2
		foreach ( $terms as $term ) {
178 2
			if ( $this->bd_starts_with( $term->name, $term_text ) ) {
179 1
				$term_ids['include'][] = $term->term_id;
180
181 1
				continue;
182
			}
183 2
			$term_ids['exclude'][] = $term->term_id;
184
		}
185
186 2
		return $term_ids;
187
	}
188
189
	/**
190
	 * Get terms which is ends with specified string.
191
	 *
192
	 * @param string $term_text user input text.
193
	 * @param array  $options   user options.
194
	 *
195
	 * @return array term ids.
196
	 */
197 2
	protected function term_ends( $term_text, $options ) {
198
		$term_ids = array(
199 2
			'include' => array(),
200
			'exclude' => array(),
201
		);
202 2
		$terms    = get_terms(
203 2
			$options['taxonomy'], array(
204 2
				'hide_empty' => false,
205
			)
206
		);
207
208 2
		foreach ( $terms as $term ) {
209 2
			if ( $this->bd_ends_with( $term->name, $term_text ) ) {
210 1
				$term_ids['include'][] = $term->term_id;
211
212 1
				continue;
213
			}
214 2
			$term_ids['exclude'][] = $term->term_id;
215
		}
216
217 2
		return $term_ids;
218
	}
219
220
	/**
221
	 * Get terms which is contain specified string.
222
	 *
223
	 * @param string $term_text user input text.
224
	 * @param array  $options   user options.
225
	 *
226
	 * @return array term ids.
227
	 */
228 5
	protected function term_contains( $term_text, $options ) {
229
		$term_ids = array(
230 5
			'include' => array(),
231
			'exclude' => array(),
232
		);
233 5
		$terms    = get_terms(
234 5
			$options['taxonomy'], array(
235 5
				'hide_empty' => false,
236
			)
237
		);
238
239 5
		foreach ( $terms as $term ) {
240 5
			if ( strpos( $term->name, $term_text ) !== false ) {
241 3
				$term_ids['include'][] = $term->term_id;
242
243 3
				continue;
244
			}
245 5
			$term_ids['exclude'][] = $term->term_id;
246
		}
247
248 5
		return $term_ids;
249
	}
250
251
	/**
252
	 * Get term ids which is have the sepcified post count .
253
	 *
254
	 * @param array $options user options.
255
	 *
256
	 * @return array term ids.
257
	 */
258 14
	protected function term_count_query( $options ) {
259 14
		$term_ids = array();
260 14
		$terms    = get_terms(
261 14
			$options['taxonomy'], array(
262 14
				'hide_empty' => false,
263
			)
264
		);
265 14
		foreach ( $terms as $term ) {
266
			$args = array(
267 14
				'post_type' => $options['post_type'],
268
				'tax_query' => array(
269
					array(
270 14
						'taxonomy' => $options['taxonomy'],
271 14
						'field'    => 'slug',
272 14
						'terms'    => $term->slug,
273
					),
274
				),
275
			);
276
277 14
			$posts = get_posts( $args );
278
279 14
			$term_id = $this->get_term_id_by_name( $options['term_text'], $options['term_opt'], $term->term_id, count( $posts ) );
280 14
			if ( ! empty( $term_id ) ) {
281 10
				$term_ids['include'][] = $term->term_id;
282
283 10
				continue;
284
			}
285
286 12
			$term_ids['exclude'][] = $term->term_id;
287
		}
288
289 14
		return $term_ids;
290
	}
291
292
	/**
293
	 * Get term id by name.
294
	 *
295
	 * @param string $term_text  user text input.
296
	 * @param array  $term_opt   user options.
297
	 * @param int    $term_id    term id.
298
	 * @param int    $post_count post count.
299
	 *
300
	 * @return int term id.
301
	 */
302 14
	protected function get_term_id_by_name( $term_text, $term_opt, $term_id, $post_count ) {
303 14
		switch ( $term_opt ) {
304 14
			case 'equal_to':
305 4
				if ( $post_count == $term_text ) {
306 3
					return $term_id;
307
				}
308 4
				break;
309
310 10
			case 'not_equal_to':
311 4
				if ( $post_count != $term_text ) {
312 3
					return $term_id;
313
				}
314 3
				break;
315
316 6
			case 'less_than':
317 3
				if ( $post_count < $term_text ) {
318 2
					return $term_id;
319
				}
320 2
				break;
321
322 3
			case 'greater_than':
323 3
				if ( $post_count > $term_text ) {
324 2
					return $term_id;
325
				}
326 3
				break;
327
		}
328 12
	}
329
330
	/**
331
	 * Wrapper for WP_Term.
332
	 *
333
	 * Adds some performance enhancing defaults.
334
	 *
335
	 * @since  6.0
336
	 *
337
	 * @param array $options  List of options.
338
	 * @param mixed $taxonomy List of Taxonomies.
339
	 *
340
	 * @return array Result array
341
	 */
342 25
	public function term_query( $options, $taxonomy ) {
343
		$defaults = array(
344 25
			'fields'     => 'ids', // retrieve only ids.
345 25
			'taxonomy'   => $taxonomy,
346 25
			'hide_empty' => 0,
347
			'count'      => true,
348
		);
349 25
		$options  = wp_parse_args( $options, $defaults );
350
351 25
		$term_query = new \WP_Term_Query();
352
353
		/**
354
		 * This action runs before the query happens.
355
		 *
356
		 * @since 5.5
357
		 * @since 5.6 added $term_query param.
358
		 *
359
		 * @param \WP_Query $term_query Query object.
360
		 */
361 25
		do_action( 'bd_before_term_query', $term_query );
362
363 25
		$terms = $term_query->query( $options );
364
365
		/**
366
		 * This action runs after the query happens.
367
		 *
368
		 * @since 5.5
369
		 * @since 5.6 added $term_query param.
370
		 *
371
		 * @param \WP_Query $term_query Query object.
372
		 */
373 25
		do_action( 'bd_after_term_query', $term_query );
374
375 25
		return $terms;
376
	}
377
}
378