Automattic /
jetpack
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 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\Defaults; |
||
| 11 | use Automattic\Jetpack\Sync\Settings; |
||
| 12 | |||
| 13 | /** |
||
| 14 | * Class to handle sync for terms. |
||
| 15 | */ |
||
| 16 | class Terms extends Module { |
||
| 17 | /** |
||
| 18 | * Whitelist for taxonomies we want to sync. |
||
| 19 | * |
||
| 20 | * @access private |
||
| 21 | * |
||
| 22 | * @var array |
||
| 23 | */ |
||
| 24 | private $taxonomy_whitelist; |
||
| 25 | |||
| 26 | /** |
||
| 27 | * Sync module name. |
||
| 28 | * |
||
| 29 | * @access public |
||
| 30 | * |
||
| 31 | * @return string |
||
| 32 | */ |
||
| 33 | public function name() { |
||
| 34 | return 'terms'; |
||
| 35 | } |
||
| 36 | |||
| 37 | /** |
||
| 38 | * The id field in the database. |
||
| 39 | * |
||
| 40 | * @access public |
||
| 41 | * |
||
| 42 | * @return string |
||
| 43 | */ |
||
| 44 | public function id_field() { |
||
| 45 | return 'term_id'; |
||
| 46 | } |
||
| 47 | |||
| 48 | /** |
||
| 49 | * The table in the database. |
||
| 50 | * |
||
| 51 | * @access public |
||
| 52 | * |
||
| 53 | * @return string |
||
| 54 | */ |
||
| 55 | public function table_name() { |
||
| 56 | return 'terms'; |
||
| 57 | } |
||
| 58 | |||
| 59 | /** |
||
| 60 | * Allows WordPress.com servers to retrieve term-related objects via the sync API. |
||
| 61 | * |
||
| 62 | * @param string $object_type The type of object. |
||
| 63 | * @param int $id The id of the object. |
||
| 64 | * |
||
| 65 | * @return bool|object A WP_Term object, or a row from term_taxonomy table depending on object type. |
||
| 66 | */ |
||
| 67 | public function get_object_by_id( $object_type, $id ) { |
||
| 68 | global $wpdb; |
||
| 69 | $object = false; |
||
| 70 | if ( 'term' === $object_type ) { |
||
| 71 | $object = get_term( intval( $id ) ); |
||
| 72 | |||
| 73 | View Code Duplication | if ( is_wp_error( $object ) && $object->get_error_code() === 'invalid_taxonomy' ) { |
|
| 74 | // Fetch raw term. |
||
| 75 | $columns = implode( ', ', array_unique( array_merge( Defaults::$default_term_checksum_columns, array( 'term_group' ) ) ) ); |
||
| 76 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
| 77 | $object = $wpdb->get_row( $wpdb->prepare( "SELECT $columns FROM $wpdb->terms WHERE term_id = %d", $id ) ); |
||
| 78 | } |
||
| 79 | } |
||
| 80 | |||
| 81 | View Code Duplication | if ( 'term_taxonomy' === $object_type ) { |
|
| 82 | $columns = implode( ', ', array_unique( array_merge( Defaults::$default_term_taxonomy_checksum_columns, array( 'description' ) ) ) ); |
||
|
0 ignored issues
–
show
|
|||
| 83 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
| 84 | $object = $wpdb->get_row( $wpdb->prepare( "SELECT $columns FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $id ) ); |
||
| 85 | } |
||
| 86 | |||
| 87 | if ( 'term_relationships' === $object_type ) { |
||
| 88 | $columns = implode( ', ', Defaults::$default_term_relationships_checksum_columns ); |
||
|
0 ignored issues
–
show
The property
default_term_relationships_checksum_columns cannot be accessed from this context as it is declared private in class Automattic\Jetpack\Sync\Defaults.
This check looks for access to properties that are not accessible from the current context. If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class. Loading history...
|
|||
| 89 | // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
||
| 90 | $objects = $wpdb->get_results( $wpdb->prepare( "SELECT $columns FROM $wpdb->term_relationships WHERE object_id = %d", $id ) ); |
||
| 91 | $object = (object) array( |
||
| 92 | 'object_id' => $id, |
||
| 93 | 'relationships' => array_map( array( $this, 'expand_terms_for_relationship' ), $objects ), |
||
| 94 | ); |
||
| 95 | } |
||
| 96 | |||
| 97 | return $object ? $object : false; |
||
| 98 | } |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Initialize terms action listeners. |
||
| 102 | * |
||
| 103 | * @access public |
||
| 104 | * |
||
| 105 | * @param callable $callable Action handler callable. |
||
| 106 | */ |
||
| 107 | public function init_listeners( $callable ) { |
||
| 108 | add_action( 'created_term', array( $this, 'save_term_handler' ), 10, 3 ); |
||
| 109 | add_action( 'edited_term', array( $this, 'save_term_handler' ), 10, 3 ); |
||
| 110 | add_action( 'jetpack_sync_save_term', $callable ); |
||
| 111 | add_action( 'jetpack_sync_add_term', $callable ); |
||
| 112 | add_action( 'delete_term', $callable, 10, 4 ); |
||
| 113 | add_action( 'set_object_terms', $callable, 10, 6 ); |
||
| 114 | add_action( 'deleted_term_relationships', $callable, 10, 2 ); |
||
| 115 | add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_save_term', array( $this, 'filter_blacklisted_taxonomies' ) ); |
||
| 116 | add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_add_term', array( $this, 'filter_blacklisted_taxonomies' ) ); |
||
| 117 | } |
||
| 118 | |||
| 119 | /** |
||
| 120 | * Initialize terms action listeners for full sync. |
||
| 121 | * |
||
| 122 | * @access public |
||
| 123 | * |
||
| 124 | * @param callable $callable Action handler callable. |
||
| 125 | */ |
||
| 126 | public function init_full_sync_listeners( $callable ) { |
||
| 127 | add_action( 'jetpack_full_sync_terms', $callable, 10, 2 ); |
||
| 128 | } |
||
| 129 | |||
| 130 | /** |
||
| 131 | * Initialize the module in the sender. |
||
| 132 | * |
||
| 133 | * @access public |
||
| 134 | */ |
||
| 135 | public function init_before_send() { |
||
| 136 | // Full sync. |
||
| 137 | add_filter( 'jetpack_sync_before_send_jetpack_full_sync_terms', array( $this, 'expand_term_taxonomy_id' ) ); |
||
| 138 | } |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Enqueue the terms actions for full sync. |
||
| 142 | * |
||
| 143 | * @access public |
||
| 144 | * |
||
| 145 | * @param array $config Full sync configuration for this sync module. |
||
| 146 | * @param int $max_items_to_enqueue Maximum number of items to enqueue. |
||
| 147 | * @param boolean $state True if full sync has finished enqueueing this module, false otherwise. |
||
| 148 | * @return array Number of actions enqueued, and next module state. |
||
| 149 | */ |
||
| 150 | public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) { |
||
| 151 | global $wpdb; |
||
| 152 | 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 ); |
||
| 153 | } |
||
| 154 | |||
| 155 | /** |
||
| 156 | * Retrieve the WHERE SQL clause based on the module config. |
||
| 157 | * |
||
| 158 | * @access public |
||
| 159 | * |
||
| 160 | * @param array $config Full sync configuration for this sync module. |
||
| 161 | * @return string WHERE SQL clause, or `null` if no comments are specified in the module config. |
||
| 162 | */ |
||
| 163 | View Code Duplication | public function get_where_sql( $config ) { |
|
| 164 | $where_sql = Settings::get_blacklisted_taxonomies_sql(); |
||
| 165 | |||
| 166 | if ( is_array( $config ) ) { |
||
| 167 | $where_sql .= ' AND term_taxonomy_id IN (' . implode( ',', array_map( 'intval', $config ) ) . ')'; |
||
| 168 | } |
||
| 169 | |||
| 170 | return $where_sql; |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Retrieve an estimated number of actions that will be enqueued. |
||
| 175 | * |
||
| 176 | * @access public |
||
| 177 | * |
||
| 178 | * @param array $config Full sync configuration for this sync module. |
||
| 179 | * @return int Number of items yet to be enqueued. |
||
| 180 | */ |
||
| 181 | View Code Duplication | public function estimate_full_sync_actions( $config ) { |
|
| 182 | global $wpdb; |
||
| 183 | |||
| 184 | $query = "SELECT count(*) FROM $wpdb->term_taxonomy"; |
||
| 185 | |||
| 186 | $where_sql = $this->get_where_sql( $config ); |
||
| 187 | if ( $where_sql ) { |
||
| 188 | $query .= ' WHERE ' . $where_sql; |
||
| 189 | } |
||
| 190 | |||
| 191 | // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared |
||
| 192 | $count = $wpdb->get_var( $query ); |
||
| 193 | |||
| 194 | return (int) ceil( $count / self::ARRAY_CHUNK_SIZE ); |
||
| 195 | } |
||
| 196 | |||
| 197 | /** |
||
| 198 | * Retrieve the actions that will be sent for this module during a full sync. |
||
| 199 | * |
||
| 200 | * @access public |
||
| 201 | * |
||
| 202 | * @return array Full sync actions of this module. |
||
| 203 | */ |
||
| 204 | public function get_full_sync_actions() { |
||
| 205 | return array( 'jetpack_full_sync_terms' ); |
||
| 206 | } |
||
| 207 | |||
| 208 | /** |
||
| 209 | * Handler for creating and updating terms. |
||
| 210 | * |
||
| 211 | * @access public |
||
| 212 | * |
||
| 213 | * @param int $term_id Term ID. |
||
| 214 | * @param int $tt_id Term taxonomy ID. |
||
| 215 | * @param string $taxonomy Taxonomy slug. |
||
| 216 | */ |
||
| 217 | public function save_term_handler( $term_id, $tt_id, $taxonomy ) { |
||
| 218 | if ( class_exists( '\\WP_Term' ) ) { |
||
| 219 | $term_object = \WP_Term::get_instance( $term_id, $taxonomy ); |
||
| 220 | } else { |
||
| 221 | $term_object = get_term_by( 'id', $term_id, $taxonomy ); |
||
| 222 | } |
||
| 223 | |||
| 224 | $current_filter = current_filter(); |
||
| 225 | |||
| 226 | if ( 'created_term' === $current_filter ) { |
||
| 227 | /** |
||
| 228 | * Fires when the client needs to add a new term |
||
| 229 | * |
||
| 230 | * @since 5.0.0 |
||
| 231 | * |
||
| 232 | * @param object the Term object |
||
| 233 | */ |
||
| 234 | do_action( 'jetpack_sync_add_term', $term_object ); |
||
| 235 | return; |
||
| 236 | } |
||
| 237 | |||
| 238 | /** |
||
| 239 | * Fires when the client needs to update a term |
||
| 240 | * |
||
| 241 | * @since 4.2.0 |
||
| 242 | * |
||
| 243 | * @param object the Term object |
||
| 244 | */ |
||
| 245 | do_action( 'jetpack_sync_save_term', $term_object ); |
||
| 246 | } |
||
| 247 | |||
| 248 | /** |
||
| 249 | * Filter blacklisted taxonomies. |
||
| 250 | * |
||
| 251 | * @access public |
||
| 252 | * |
||
| 253 | * @param array $args Hook args. |
||
| 254 | * @return array|boolean False if not whitelisted, the original hook args otherwise. |
||
| 255 | */ |
||
| 256 | public function filter_blacklisted_taxonomies( $args ) { |
||
| 257 | $term = $args[0]; |
||
| 258 | |||
| 259 | if ( in_array( $term->taxonomy, Settings::get_setting( 'taxonomies_blacklist' ), true ) ) { |
||
| 260 | return false; |
||
| 261 | } |
||
| 262 | |||
| 263 | return $args; |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * Set the taxonomy whitelist. |
||
| 268 | * |
||
| 269 | * @access public |
||
| 270 | * |
||
| 271 | * @param array $taxonomies The new taxonomyy whitelist. |
||
| 272 | */ |
||
| 273 | public function set_taxonomy_whitelist( $taxonomies ) { |
||
| 274 | $this->taxonomy_whitelist = $taxonomies; |
||
| 275 | } |
||
| 276 | |||
| 277 | /** |
||
| 278 | * Set module defaults. |
||
| 279 | * Define the taxonomy whitelist to be the default one. |
||
| 280 | * |
||
| 281 | * @access public |
||
| 282 | */ |
||
| 283 | public function set_defaults() { |
||
| 284 | $this->taxonomy_whitelist = Defaults::$default_taxonomy_whitelist; |
||
| 285 | } |
||
| 286 | |||
| 287 | /** |
||
| 288 | * Expand the term taxonomy IDs to terms within a hook before they are serialized and sent to the server. |
||
| 289 | * |
||
| 290 | * @access public |
||
| 291 | * |
||
| 292 | * @param array $args The hook parameters. |
||
| 293 | * @return array $args The expanded hook parameters. |
||
| 294 | */ |
||
| 295 | public function expand_term_taxonomy_id( $args ) { |
||
| 296 | list( $term_taxonomy_ids, $previous_end ) = $args; |
||
| 297 | |||
| 298 | return array( |
||
| 299 | 'terms' => get_terms( |
||
| 300 | array( |
||
| 301 | 'hide_empty' => false, |
||
| 302 | 'term_taxonomy_id' => $term_taxonomy_ids, |
||
| 303 | 'orderby' => 'term_taxonomy_id', |
||
| 304 | 'order' => 'DESC', |
||
| 305 | ) |
||
| 306 | ), |
||
| 307 | 'previous_end' => $previous_end, |
||
| 308 | ); |
||
| 309 | } |
||
| 310 | |||
| 311 | /** |
||
| 312 | * Gets a term object based on a given row from the term_relationships database table. |
||
| 313 | * |
||
| 314 | * @access public |
||
| 315 | * |
||
| 316 | * @param object $relationship A row object from the term_relationships table. |
||
| 317 | * @return object|bool A term object, or false if term taxonomy doesn't exist. |
||
| 318 | */ |
||
| 319 | public function expand_terms_for_relationship( $relationship ) { |
||
| 320 | return get_term_by( 'term_taxonomy_id', $relationship->term_taxonomy_id ); |
||
| 321 | } |
||
| 322 | } |
||
| 323 |
This check looks for access to properties that are not accessible from the current context.
If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.