PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.2-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.2-a.1
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-sync / src / modules / class-terms.php
jetpack / jetpack_vendor / automattic / jetpack-sync / src / modules Last commit date
class-attachments.php 8 months ago class-callables.php 1 month ago class-comments.php 2 months ago class-constants.php 8 months ago class-full-sync-immediately.php 3 months ago class-full-sync.php 2 months ago class-import.php 8 months ago class-menus.php 2 months ago class-meta.php 2 months ago class-module.php 5 months ago class-network-options.php 8 months ago class-options.php 2 months ago class-plugins.php 2 months ago class-posts.php 2 months ago class-protect.php 8 months ago class-search.php 2 months ago class-stats.php 6 months ago class-term-relationships.php 8 months ago class-terms.php 2 months ago class-themes.php 2 months ago class-updates.php 8 months ago class-users.php 1 month ago class-woocommerce-hpos-orders.php 1 month ago class-woocommerce-products.php 8 months ago class-woocommerce.php 1 month ago class-wp-super-cache.php 8 months ago
class-terms.php
492 lines
1 <?php
2 /**
3 * Terms sync module.
4 *
5 * @package automattic/jetpack-sync
6 */
7
8 namespace Automattic\Jetpack\Sync\Modules;
9
10 use Automattic\Jetpack\Sync\Settings;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit( 0 );
14 }
15
16 /**
17 * Class to handle sync for terms.
18 */
19 class Terms extends Module {
20
21 /**
22 * Sync module name.
23 *
24 * @access public
25 *
26 * @return string
27 */
28 public function name() {
29 return 'terms';
30 }
31
32 /**
33 * The id field in the database.
34 *
35 * @access public
36 *
37 * @return string
38 */
39 public function id_field() {
40 return 'term_taxonomy_id';
41 }
42
43 /**
44 * The table name.
45 *
46 * @access public
47 *
48 * @return string
49 * @deprecated since 3.11.0 Use table() instead.
50 */
51 public function table_name() {
52 _deprecated_function( __METHOD__, '3.11.0', 'Automattic\\Jetpack\\Sync\\Terms->table' );
53 return 'term_taxonomy';
54 }
55
56 /**
57 * The table in the database with the prefix.
58 *
59 * @access public
60 *
61 * @return string|bool
62 */
63 public function table() {
64 global $wpdb;
65 return $wpdb->term_taxonomy;
66 }
67
68 /**
69 * Allows WordPress.com servers to retrieve term-related objects via the sync API.
70 *
71 * @param string $object_type The type of object. Accepts: 'term', 'term_taxonomy', 'term_relationships'.
72 * @param int $id The id of the object.
73 *
74 * @return false|object A term or term_taxonomy object, depending on object type.
75 */
76 public function get_object_by_id( $object_type, $id ) {
77 $id = (int) $id;
78
79 if ( empty( $id ) ) {
80 return false;
81 }
82
83 $objects = $this->get_objects_by_id( $object_type, array( $id ) );
84
85 return $objects[ $id ] ?? false;
86 }
87
88 /**
89 * Retrieve a set of objects by their IDs.
90 *
91 * @access public
92 *
93 * @param string $object_type Object type. Accepts: 'term', 'term_taxonomy', 'term_relationships'.
94 * @param array $ids Object IDs.
95 *
96 * @return array Array of objects.
97 */
98 public function get_objects_by_id( $object_type, $ids ) {
99 global $wpdb;
100
101 $objects = array();
102
103 if ( ! is_array( $ids ) || empty( $ids ) || empty( $object_type ) ) {
104 return $objects;
105 }
106
107 // Sanitize.
108 $ids = array_map( 'intval', $ids );
109 $ids_str = implode( ',', $ids );
110
111 $where_sql = Settings::get_whitelisted_taxonomies_sql();
112
113 switch ( $object_type ) {
114 case 'term':
115 $query = "SELECT * FROM $wpdb->terms t INNER JOIN $wpdb->term_taxonomy tt ON t.term_id=tt.term_id WHERE t.term_id IN ( $ids_str ) AND ";
116 $callback = 'expand_raw_terms';
117 break;
118 case 'term_taxonomy':
119 $query = "SELECT * FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ( $ids_str ) AND ";
120 $callback = 'expand_raw_term_taxonomies';
121 break;
122 case 'term_relationships':
123 $query = "SELECT * FROM $wpdb->term_relationships tr INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id=tt.term_taxonomy_id WHERE object_id IN ( $ids_str ) AND ";
124 $callback = 'expand_raw_term_relationships';
125 break;
126 default:
127 return array();
128 }
129
130 $query .= $where_sql;
131
132 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Already sanitized above.
133 $results = $wpdb->get_results( $query );
134
135 if ( ! is_array( $results ) ) {
136 return array();
137 }
138
139 $objects = $this->$callback( $results );
140
141 return $objects ?? array();
142 }
143
144 /**
145 * Initialize terms action listeners.
146 *
147 * @access public
148 *
149 * @param callable $callable Action handler callable.
150 */
151 public function init_listeners( $callable ) {
152 add_action( 'created_term', array( $this, 'save_term_handler' ), 10, 3 );
153 add_action( 'edited_term', array( $this, 'save_term_handler' ), 10, 3 );
154 add_action( 'jetpack_sync_save_term', $callable );
155 add_action( 'jetpack_sync_add_term', $callable );
156 add_action( 'delete_term', $callable, 10, 4 );
157 add_action( 'set_object_terms', $callable, 10, 6 );
158 add_action( 'deleted_term_relationships', $callable, 10, 2 );
159 add_filter( 'jetpack_sync_before_enqueue_set_object_terms', array( $this, 'filter_set_object_terms_no_update' ) );
160 add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_save_term', array( $this, 'filter_blacklisted_taxonomies' ) );
161 add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_add_term', array( $this, 'filter_blacklisted_taxonomies' ) );
162 }
163
164 /**
165 * Initialize terms action listeners for full sync.
166 *
167 * @access public
168 *
169 * @param callable $callable Action handler callable.
170 */
171 public function init_full_sync_listeners( $callable ) {
172 add_action( 'jetpack_full_sync_terms', $callable, 10, 2 );
173 }
174
175 /**
176 * Initialize the module in the sender.
177 *
178 * @access public
179 */
180 public function init_before_send() {
181 // Full sync.
182 add_filter( 'jetpack_sync_before_send_jetpack_full_sync_terms', array( $this, 'expand_term_taxonomy_id' ) );
183 }
184
185 /**
186 * Enqueue the terms actions for full sync.
187 *
188 * @access public
189 *
190 * @param array $config Full sync configuration for this sync module.
191 * @param int $max_items_to_enqueue Maximum number of items to enqueue.
192 * @param boolean $state True if full sync has finished enqueueing this module, false otherwise.
193 * @return array Number of actions enqueued, and next module state.
194 */
195 public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) {
196 global $wpdb;
197 return $this->enqueue_all_ids_as_action( 'jetpack_full_sync_terms', $wpdb->term_taxonomy, 'term_taxonomy_id', $this->get_where_sql( $config ), $max_items_to_enqueue, $state );
198 }
199
200 /**
201 * Retrieve the WHERE SQL clause based on the module config.
202 *
203 * @access public
204 *
205 * @param array $config Full sync configuration for this sync module.
206 * @return string WHERE SQL clause, or `null` if no comments are specified in the module config.
207 */
208 public function get_where_sql( $config ) {
209 $where_sql = Settings::get_blacklisted_taxonomies_sql();
210
211 if ( is_array( $config ) && ! empty( $config ) ) {
212 $where_sql .= ' AND term_taxonomy_id IN (' . implode( ',', array_map( 'intval', $config ) ) . ')';
213 }
214
215 return $where_sql;
216 }
217
218 /**
219 * Retrieve an estimated number of actions that will be enqueued.
220 *
221 * @access public
222 *
223 * @param array $config Full sync configuration for this sync module.
224 * @return int Number of items yet to be enqueued.
225 */
226 public function estimate_full_sync_actions( $config ) {
227 global $wpdb;
228
229 $query = "SELECT count(*) FROM $wpdb->term_taxonomy";
230
231 $where_sql = $this->get_where_sql( $config );
232 if ( $where_sql ) {
233 $query .= ' WHERE ' . $where_sql;
234 }
235
236 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
237 $count = (int) $wpdb->get_var( $query );
238
239 return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
240 }
241
242 /**
243 * Retrieve the actions that will be sent for this module during a full sync.
244 *
245 * @access public
246 *
247 * @return array Full sync actions of this module.
248 */
249 public function get_full_sync_actions() {
250 return array( 'jetpack_full_sync_terms' );
251 }
252
253 /**
254 * Handler for creating and updating terms.
255 *
256 * @access public
257 *
258 * @param int $term_id Term ID.
259 * @param int $tt_id Term taxonomy ID.
260 * @param string $taxonomy Taxonomy slug.
261 */
262 public function save_term_handler( $term_id, $tt_id, $taxonomy ) {
263 if ( class_exists( '\\WP_Term' ) ) {
264 $term_object = \WP_Term::get_instance( $term_id, $taxonomy );
265 } else {
266 $term_object = get_term_by( 'id', $term_id, $taxonomy );
267 }
268
269 $current_filter = current_filter();
270
271 if ( 'created_term' === $current_filter ) {
272 /**
273 * Fires when the client needs to add a new term
274 *
275 * @since 1.6.3
276 * @since-jetpack 5.0.0
277 *
278 * @param object the Term object
279 */
280 do_action( 'jetpack_sync_add_term', $term_object );
281 return;
282 }
283
284 /**
285 * Fires when the client needs to update a term
286 *
287 * @since 1.6.3
288 * @since-jetpack 4.2.0
289 *
290 * @param object the Term object
291 */
292 do_action( 'jetpack_sync_save_term', $term_object );
293 }
294
295 /**
296 * Filter blacklisted taxonomies.
297 *
298 * @access public
299 *
300 * @param array $args Hook args.
301 * @return array|boolean False if not whitelisted, the original hook args otherwise.
302 */
303 public function filter_blacklisted_taxonomies( $args ) {
304 $term = $args[0] ?? null;
305
306 if ( ! $term instanceof \WP_Term ) {
307 return false;
308 }
309
310 if ( in_array( $term->taxonomy, Settings::get_setting( 'taxonomies_blacklist' ), true ) ) {
311 return false;
312 }
313
314 return $args;
315 }
316
317 /**
318 * Filter out set_object_terms actions with blacklisted taxonomies or where the terms have not changed.
319 *
320 * @param array $args Hook args.
321 * @return array|boolean False if blacklisted taxonomy or no change in terms, the original hook args otherwise.
322 */
323 public function filter_set_object_terms_no_update( $args ) {
324 // Check if the taxonomy is blacklisted. $args[3] is the taxonomy.
325 if ( isset( $args[3] ) && in_array( $args[3], Settings::get_setting( 'taxonomies_blacklist' ), true ) ) {
326 return false;
327 }
328 // There is potential for other plugins to modify args, therefore lets validate # of and types.
329 // $args[2] is $tt_ids, $args[5] is $old_tt_ids see wp-includes/taxonomy.php L2740.
330 if ( 6 === count( $args ) && is_array( $args[2] ) && is_array( $args[5] ) ) {
331 if ( empty( array_diff( $args[2], $args[5] ) ) && empty( array_diff( $args[5], $args[2] ) ) ) {
332 return false;
333 }
334 }
335 return $args;
336 }
337
338 /**
339 * Expand the term taxonomy IDs to terms within a hook before they are serialized and sent to the server.
340 *
341 * @access public
342 *
343 * @param array $args The hook parameters.
344 * @return array $args The expanded hook parameters.
345 */
346 public function expand_term_taxonomy_id( $args ) {
347 list( $term_taxonomy_ids, $previous_end ) = $args;
348
349 return array(
350 'terms' => get_terms(
351 array(
352 'hide_empty' => false,
353 'orderby' => 'term_taxonomy_id',
354 'order' => 'DESC',
355 'taxonomy' => array(),
356 'term_taxonomy_id' => $term_taxonomy_ids,
357 )
358 ),
359 'previous_end' => $previous_end,
360 );
361 }
362
363 /**
364 * Gets a term object based on a given row from the term_relationships database table.
365 *
366 * @access public
367 *
368 * @deprecated since 4.8.1
369 *
370 * @param object $relationship A row object from the term_relationships table.
371 * @return object|bool A term object, or false if term taxonomy doesn't exist.
372 */
373 public function expand_terms_for_relationship( $relationship ) {
374 _deprecated_function( __METHOD__, '4.8.1' );
375
376 return get_term_by( 'term_taxonomy_id', $relationship->term_taxonomy_id );
377 }
378
379 /**
380 * Prepare raw terms and return them in a standard format.
381 *
382 * @param array $terms An array of raw term objects.
383 * @return array An array of term objects.
384 */
385 private function expand_raw_terms( array $terms ) {
386 $objects = array();
387 $columns = array(
388 'term_id' => 'int',
389 'name' => 'string',
390 'slug' => 'string',
391 'taxonomy' => 'string',
392 'description' => 'string',
393 'term_group' => 'int',
394 'term_taxonomy_id' => 'int',
395 'parent' => 'int',
396 'count' => 'int',
397 );
398
399 foreach ( $terms as $term ) {
400 if ( ! array_key_exists( $term->term_id, $objects ) ) {
401 $t_array = array();
402
403 foreach ( $columns as $field => $type ) {
404 $value = $term->$field ?? '';
405 $t_array[ $field ] = 'int' === $type ? (int) $value : $value;
406 }
407 // This will allow us to know on WPCOM that the term name is the raw one, coming from the DB. Useful with backwards compatibility in mind.
408 $t_array['raw_name'] = $t_array['name'];
409
410 $objects[ $term->term_id ] = (object) $t_array;
411 }
412 }
413
414 return $objects;
415 }
416
417 /**
418 * Prepare raw term taxonomies and return them in a standard format.
419 *
420 * @param array $term_taxonomies An array of raw term_taxonomy objects.
421 * @return array An array of term_taxonomy objects.
422 */
423 private function expand_raw_term_taxonomies( array $term_taxonomies ) {
424 $objects = array();
425 $columns = array(
426 'term_id' => 'int',
427 'taxonomy' => 'string',
428 'description' => 'string',
429 'term_taxonomy_id' => 'int',
430 'parent' => 'int',
431 'count' => 'int',
432 );
433
434 foreach ( $term_taxonomies as $tt ) {
435 if ( ! array_key_exists( $tt->term_taxonomy_id, $objects ) ) {
436 $t_array = array();
437
438 foreach ( $columns as $field => $type ) {
439 $value = $tt->$field ?? '';
440 $t_array[ $field ] = 'int' === $type ? (int) $value : $value;
441 }
442
443 $objects[ $tt->term_taxonomy_id ] = (object) $t_array;
444 }
445 }
446
447 return $objects;
448 }
449
450 /**
451 * Prepare raw term taxonomies and return them in a standard format.
452 *
453 * @param array $term_relationships An array of raw term_taxonomy objects.
454 * @return array An array of term_taxonomy objects or false.
455 */
456 private function expand_raw_term_relationships( array $term_relationships ) {
457 $objects = array();
458 $columns = array(
459 'object_id' => 'int',
460 'term_id' => 'int',
461 'taxonomy' => 'string',
462 'term_taxonomy_id' => 'int',
463 'term_order' => 'int',
464 'parent' => 'int',
465 'count' => 'int',
466 );
467
468 foreach ( $term_relationships as $tt ) {
469 $object_id = (int) $tt->object_id;
470
471 $relationship = array();
472 foreach ( $columns as $field => $type ) {
473 $value = $tt->$field ?? '';
474 $relationship[ $field ] = 'int' === $type ? (int) $value : $value;
475 }
476
477 $relationship = (object) $relationship;
478
479 if ( ! array_key_exists( $object_id, $objects ) ) {
480 $objects[ $object_id ] = (object) array(
481 'object_id' => $object_id,
482 'relationships' => array( $relationship ),
483 );
484 } else {
485 $objects[ $object_id ]->relationships[] = $relationship;
486 }
487 }
488
489 return $objects;
490 }
491 }
492