PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.5
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.5
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
← All changes | jetpack_vendor/automattic/jetpack-sync/src/modules/class-terms.php +212 -34 12.7.3 → 16.3-a.5 View file →
@@ -6,11 +6,14 @@
6 6 */
7 7
8 8 namespace Automattic\Jetpack\Sync\Modules;
9 9
10 -use Automattic\Jetpack\Sync\Defaults;
11 10 use Automattic\Jetpack\Sync\Settings;
12 11
12 +if ( ! defined( 'ABSPATH' ) ) {
13 + exit( 0 );
14 +}
15 +
13 16 /**
14 17 * Class to handle sync for terms.
15 18 */
16 19 class Terms extends Module {
@@ -37,57 +40,106 @@
37 40 return 'term_taxonomy_id';
38 41 }
39 42
40 43 /**
41 - * The table in the database.
44 + * The table name.
42 45 *
43 46 * @access public
44 47 *
45 48 * @return string
49 + * @deprecated since 3.11.0 Use table() instead.
46 50 */
47 51 public function table_name() {
52 + _deprecated_function( __METHOD__, '3.11.0', 'Automattic\\Jetpack\\Sync\\Terms->table' );
48 53 return 'term_taxonomy';
49 54 }
50 55
51 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 + /**
52 69 * Allows WordPress.com servers to retrieve term-related objects via the sync API.
53 70 *
54 - * @param string $object_type The type of object.
71 + * @param string $object_type The type of object. Accepts: 'term', 'term_taxonomy', 'term_relationships'.
55 72 * @param int $id The id of the object.
56 73 *
57 - * @return bool|object A WP_Term object, or a row from term_taxonomy table depending on object type.
74 + * @return false|object A term or term_taxonomy object, depending on object type.
58 75 */
59 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 ) {
60 99 global $wpdb;
61 - $object = false;
62 - if ( 'term' === $object_type ) {
63 - $object = get_term( (int) $id );
64 100
65 - if ( is_wp_error( $object ) && $object->get_error_code() === 'invalid_taxonomy' ) {
66 - // Fetch raw term.
67 - $columns = implode( ', ', array_unique( array_merge( Defaults::$default_term_checksum_columns, array( 'term_group' ) ) ) );
68 - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
69 - $object = $wpdb->get_row( $wpdb->prepare( "SELECT $columns FROM $wpdb->terms WHERE term_id = %d", $id ) );
70 - }
101 + $objects = array();
102 +
103 + if ( ! is_array( $ids ) || empty( $ids ) || empty( $object_type ) ) {
104 + return $objects;
71 105 }
72 106
73 - if ( 'term_taxonomy' === $object_type ) {
74 - $columns = implode( ', ', array_unique( array_merge( Defaults::$default_term_taxonomy_checksum_columns, array( 'description' ) ) ) );
75 - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
76 - $object = $wpdb->get_row( $wpdb->prepare( "SELECT $columns FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $id ) );
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();
77 128 }
78 129
79 - if ( 'term_relationships' === $object_type ) {
80 - $columns = implode( ', ', Defaults::$default_term_relationships_checksum_columns );
81 - // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
82 - $objects = $wpdb->get_results( $wpdb->prepare( "SELECT $columns FROM $wpdb->term_relationships WHERE object_id = %d", $id ) );
83 - $object = (object) array(
84 - 'object_id' => $id,
85 - 'relationships' => array_map( array( $this, 'expand_terms_for_relationship' ), $objects ),
86 - );
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();
87 137 }
88 138
89 - return $object ? $object : false;
139 + $objects = $this->$callback( $results );
140 +
141 + return $objects ?? array();
90 142 }
91 143
92 144 /**
93 145 * Initialize terms action listeners.
@@ -155,9 +207,9 @@
155 207 */
156 208 public function get_where_sql( $config ) {
157 209 $where_sql = Settings::get_blacklisted_taxonomies_sql();
158 210
159 - if ( is_array( $config ) ) {
211 + if ( is_array( $config ) && ! empty( $config ) ) {
160 212 $where_sql .= ' AND term_taxonomy_id IN (' . implode( ',', array_map( 'intval', $config ) ) . ')';
161 213 }
162 214
163 215 return $where_sql;
@@ -180,10 +232,10 @@
180 232 if ( $where_sql ) {
181 233 $query .= ' WHERE ' . $where_sql;
182 234 }
183 235
184 - // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
185 - $count = $wpdb->get_var( $query );
236 + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
237 + $count = (int) $wpdb->get_var( $query );
186 238
187 239 return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
188 240 }
189 241
@@ -248,10 +300,14 @@
248 300 * @param array $args Hook args.
249 301 * @return array|boolean False if not whitelisted, the original hook args otherwise.
250 302 */
251 303 public function filter_blacklisted_taxonomies( $args ) {
252 - $term = $args[0];
304 + $term = $args[0] ?? null;
253 305
306 + if ( ! $term instanceof \WP_Term ) {
307 + return false;
308 + }
309 +
254 310 if ( in_array( $term->taxonomy, Settings::get_setting( 'taxonomies_blacklist' ), true ) ) {
255 311 return false;
256 312 }
257 313
@@ -258,14 +314,18 @@
258 314 return $args;
259 315 }
260 316
261 317 /**
262 - * Filter out set_object_terms actions where the terms have not changed.
318 + * Filter out set_object_terms actions with blacklisted taxonomies or where the terms have not changed.
263 319 *
264 320 * @param array $args Hook args.
265 - * @return array|boolean False if no change in terms, the original hook args otherwise.
321 + * @return array|boolean False if blacklisted taxonomy or no change in terms, the original hook args otherwise.
266 322 */
267 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 + }
268 328 // There is potential for other plugins to modify args, therefore lets validate # of and types.
269 329 // $args[2] is $tt_ids, $args[5] is $old_tt_ids see wp-includes/taxonomy.php L2740.
270 330 if ( 6 === count( $args ) && is_array( $args[2] ) && is_array( $args[5] ) ) {
271 331 if ( empty( array_diff( $args[2], $args[5] ) ) && empty( array_diff( $args[5], $args[2] ) ) ) {
@@ -283,17 +343,18 @@
283 343 * @param array $args The hook parameters.
284 344 * @return array $args The expanded hook parameters.
285 345 */
286 346 public function expand_term_taxonomy_id( $args ) {
287 - list( $term_taxonomy_ids, $previous_end ) = $args;
347 + list( $term_taxonomy_ids, $previous_end ) = $args;
288 348
289 349 return array(
290 350 'terms' => get_terms(
291 351 array(
292 352 'hide_empty' => false,
293 - 'term_taxonomy_id' => $term_taxonomy_ids,
294 353 'orderby' => 'term_taxonomy_id',
295 354 'order' => 'DESC',
355 + 'taxonomy' => array(),
356 + 'term_taxonomy_id' => $term_taxonomy_ids,
296 357 )
297 358 ),
298 359 'previous_end' => $previous_end,
299 360 );
@@ -303,11 +364,128 @@
303 364 * Gets a term object based on a given row from the term_relationships database table.
304 365 *
305 366 * @access public
306 367 *
368 + * @deprecated since 4.8.1
369 + *
307 370 * @param object $relationship A row object from the term_relationships table.
308 371 * @return object|bool A term object, or false if term taxonomy doesn't exist.
309 372 */
310 373 public function expand_terms_for_relationship( $relationship ) {
374 + _deprecated_function( __METHOD__, '4.8.1' );
375 +
311 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;
312 490 }
313 491 }