← All changes
|
jetpack_vendor/automattic/jetpack-sync/src/class-settings.php
+174
-15
12.2.3
→
16.3-a.7
View file →
| @@ -7,8 +7,9 @@ | ||
| 7 | 7 | |
| 8 | 8 | namespace Automattic\Jetpack\Sync; |
| 9 | 9 | |
| 10 | 10 | use Automattic\Jetpack\Constants; |
| 11 | +use Automattic\Jetpack\Sync\Queue\Queue_Storage_Table; | |
| 11 | 12 | |
| 12 | 13 | /** |
| 13 | 14 | * Class to manage the sync settings. |
| 14 | 15 | */ |
| @@ -58,8 +59,11 @@ | ||
| 58 | 59 | 'full_sync_send_duration' => true, |
| 59 | 60 | 'full_sync_limits' => true, |
| 60 | 61 | 'checksum_disable' => true, |
| 61 | 62 | 'dedicated_sync_enabled' => true, |
| 63 | + 'custom_queue_table_enabled' => true, | |
| 64 | + 'wpcom_rest_api_enabled' => true, | |
| 65 | + 'sync_actions_blacklist' => true, | |
| 62 | 66 | ); |
| 63 | 67 | |
| 64 | 68 | /** |
| 65 | 69 | * Whether WordPress is currently running an import. |
| @@ -111,9 +115,9 @@ | ||
| 111 | 115 | */ |
| 112 | 116 | public static function get_settings() { |
| 113 | 117 | $settings = array(); |
| 114 | 118 | foreach ( array_keys( self::$valid_settings ) as $setting ) { |
| 115 | - $settings[ $setting ] = self::get_setting( $setting ); | |
| 119 | + $settings[ $setting ] = static::get_setting( $setting ); | |
| 116 | 120 | } |
| 117 | 121 | |
| 118 | 122 | return $settings; |
| 119 | 123 | } |
| @@ -198,8 +202,90 @@ | ||
| 198 | 202 | public static function update_settings( $new_settings ) { |
| 199 | 203 | $validated_settings = array_intersect_key( $new_settings, self::$valid_settings ); |
| 200 | 204 | foreach ( $validated_settings as $setting => $value ) { |
| 201 | 205 | |
| 206 | + /** | |
| 207 | + * Custom table migration logic. | |
| 208 | + * | |
| 209 | + * This needs to happen before the option is updated, to avoid race conditions where we update the option, | |
| 210 | + * but haven't yet created the table or can't create it. | |
| 211 | + * | |
| 212 | + * On high-traffic sites this can lead to Sync trying to write in a non-existent table. | |
| 213 | + * | |
| 214 | + * So to avoid this, we're going to first try to initialize everything and then update the option. | |
| 215 | + */ | |
| 216 | + if ( 'custom_queue_table_enabled' === $setting ) { | |
| 217 | + // Need to check the current value in the database to make sure we're not doing anything weird. | |
| 218 | + $old_value = get_option( self::SETTINGS_OPTION_PREFIX . $setting, null ); | |
| 219 | + | |
| 220 | + if ( ! $old_value && $value ) { | |
| 221 | + /** | |
| 222 | + * The custom table has been enabled. | |
| 223 | + * | |
| 224 | + * - Initialize the custom table | |
| 225 | + * - Migrate the data | |
| 226 | + * | |
| 227 | + * If something fails, migrate back to the options table and clean up everything about the custom table. | |
| 228 | + */ | |
| 229 | + $init_result = Queue_Storage_Table::initialize_custom_sync_table(); | |
| 230 | + | |
| 231 | + /** | |
| 232 | + * Check if there was a problem when initializing the table. | |
| 233 | + */ | |
| 234 | + if ( is_wp_error( $init_result ) ) { | |
| 235 | + /** | |
| 236 | + * Unable to initialize the table properly. Set the value to `false` as we can't enable it. | |
| 237 | + */ | |
| 238 | + $value = false; | |
| 239 | + | |
| 240 | + /** | |
| 241 | + * Send error to WPCOM, so we can track and take an appropriate action. | |
| 242 | + */ | |
| 243 | + $data = array( | |
| 244 | + 'timestamp' => microtime( true ), | |
| 245 | + 'error_code' => $init_result->get_error_code(), | |
| 246 | + 'response_body' => $init_result->get_error_message(), | |
| 247 | + ); | |
| 248 | + | |
| 249 | + $sender = Sender::get_instance(); | |
| 250 | + $sender->send_action( 'jetpack_sync_storage_error_custom_init', $data ); | |
| 251 | + | |
| 252 | + } elseif ( ! Queue_Storage_Table::migrate_from_options_table_to_custom_table() ) { | |
| 253 | + /** | |
| 254 | + * If the migration fails, do a reverse migration and set the value to `false` as we can't | |
| 255 | + * safely enable the table. | |
| 256 | + */ | |
| 257 | + Queue_Storage_Table::migrate_from_custom_table_to_options_table(); | |
| 258 | + | |
| 259 | + // Set $value to `false` as we couldn't do the migration, and we can't continue enabling the table. | |
| 260 | + $value = false; | |
| 261 | + | |
| 262 | + /** | |
| 263 | + * Send error to WPCOM, so we can track and take an appropriate action. | |
| 264 | + */ | |
| 265 | + $data = array( | |
| 266 | + 'timestamp' => microtime( true ), | |
| 267 | + // TODO: Maybe add more details here for the migration, i.e. how many items where in the queue? | |
| 268 | + ); | |
| 269 | + | |
| 270 | + $sender = Sender::get_instance(); | |
| 271 | + $sender->send_action( 'jetpack_sync_storage_error_custom_migrate', $data ); | |
| 272 | + } | |
| 273 | + } elseif ( $old_value && ! $value ) { | |
| 274 | + if ( ! get_transient( Queue_Storage_Table::CUSTOM_QUEUE_TABLE_DISABLE_WPDB_ERROR_NOT_EXIST_FLAG ) ) { | |
| 275 | + /** | |
| 276 | + * The custom table has been disabled, migrate what we can from the custom table to the options table unless | |
| 277 | + * the custom table doesn't exist in the DB. | |
| 278 | + */ | |
| 279 | + Queue_Storage_Table::migrate_from_custom_table_to_options_table(); | |
| 280 | + } | |
| 281 | + } | |
| 282 | + } | |
| 283 | + | |
| 284 | + /** | |
| 285 | + * Regular option update and handling | |
| 286 | + */ | |
| 287 | + $updated = false; | |
| 202 | 288 | if ( self::is_network_setting( $setting ) ) { |
| 203 | 289 | if ( is_multisite() && is_main_site() ) { |
| 204 | 290 | $updated = update_site_option( self::SETTINGS_OPTION_PREFIX . $setting, $value ); |
| 205 | 291 | } |
| @@ -217,8 +303,23 @@ | ||
| 217 | 303 | // Do not enable Dedicated Sync if we cannot spawn a Dedicated Sync request. |
| 218 | 304 | if ( 'dedicated_sync_enabled' === $setting && $updated && (bool) $value ) { |
| 219 | 305 | if ( ! Dedicated_Sender::can_spawn_dedicated_sync_request() ) { |
| 220 | 306 | update_option( self::SETTINGS_OPTION_PREFIX . $setting, 0, true ); |
| 307 | + $listener = Listener::get_instance(); | |
| 308 | + // Remove the last two actions from the queue since we failed to enable Dedicated Sync. | |
| 309 | + // Those would be `updated_option` with `jetpack_sync_settings_dedicated_sync_enabled` set to 1 and then 0 again. | |
| 310 | + $queue = $listener->get_sync_queue(); | |
| 311 | + $items = $queue->peek_newest( 2 ); | |
| 312 | + $key = 'jetpack_sync_settings_dedicated_sync_enabled'; | |
| 313 | + | |
| 314 | + if ( | |
| 315 | + isset( $items[0][1][0] ) | |
| 316 | + && isset( $items[1][1][0] ) | |
| 317 | + && $items[0][1][0] === $key | |
| 318 | + && $items[1][1][0] === $key | |
| 319 | + ) { | |
| 320 | + $queue->pop_newest( 2 ); | |
| 321 | + } | |
| 221 | 322 | } |
| 222 | 323 | } |
| 223 | 324 | } |
| 224 | 325 | } |
| @@ -232,9 +333,9 @@ | ||
| 232 | 333 | * @param string $setting Setting name. |
| 233 | 334 | * @return boolean Whether the setting is a network setting. |
| 234 | 335 | */ |
| 235 | 336 | public static function is_network_setting( $setting ) { |
| 236 | - return strpos( $setting, 'network_' ) === 0; | |
| 337 | + return str_starts_with( $setting, 'network_' ); | |
| 237 | 338 | } |
| 238 | 339 | |
| 239 | 340 | /** |
| 240 | 341 | * Returns escaped SQL for blacklisted post types. |
| @@ -245,9 +346,9 @@ | ||
| 245 | 346 | * |
| 246 | 347 | * @return string SQL WHERE clause. |
| 247 | 348 | */ |
| 248 | 349 | public static function get_blacklisted_post_types_sql() { |
| 249 | - return 'post_type NOT IN (\'' . implode( '\', \'', array_map( 'esc_sql', self::get_setting( 'post_types_blacklist' ) ) ) . '\')'; | |
| 350 | + return 'post_type NOT IN (\'' . implode( '\', \'', array_map( 'esc_sql', static::get_setting( 'post_types_blacklist' ) ) ) . '\')'; | |
| 250 | 351 | } |
| 251 | 352 | |
| 252 | 353 | /** |
| 253 | 354 | * Returns escaped values for disallowed post types. |
| @@ -260,9 +361,9 @@ | ||
| 260 | 361 | public static function get_disallowed_post_types_structured() { |
| 261 | 362 | return array( |
| 262 | 363 | 'post_type' => array( |
| 263 | 364 | 'operator' => 'NOT IN', |
| 264 | - 'values' => array_map( 'esc_sql', self::get_setting( 'post_types_blacklist' ) ), | |
| 365 | + 'values' => array_map( 'esc_sql', static::get_setting( 'post_types_blacklist' ) ), | |
| 265 | 366 | ), |
| 266 | 367 | ); |
| 267 | 368 | } |
| 268 | 369 | |
| @@ -275,12 +376,30 @@ | ||
| 275 | 376 | * |
| 276 | 377 | * @return string SQL WHERE clause. |
| 277 | 378 | */ |
| 278 | 379 | public static function get_blacklisted_taxonomies_sql() { |
| 279 | - return "taxonomy NOT IN ('" . implode( "', '", array_map( 'esc_sql', self::get_setting( 'taxonomies_blacklist' ) ) ) . "')"; | |
| 380 | + return "taxonomy NOT IN ('" . implode( "', '", array_map( 'esc_sql', static::get_setting( 'taxonomies_blacklist' ) ) ) . "')"; | |
| 280 | 381 | } |
| 281 | 382 | |
| 282 | 383 | /** |
| 384 | + * Returns escaped SQL for whitelisted taxonomies. | |
| 385 | + * Can be injected directly into a WHERE clause. | |
| 386 | + * | |
| 387 | + * @access public | |
| 388 | + * @static | |
| 389 | + * | |
| 390 | + * @return string SQL WHERE clause. | |
| 391 | + */ | |
| 392 | + public static function get_whitelisted_taxonomies_sql() { | |
| 393 | + global $wp_taxonomies; | |
| 394 | + | |
| 395 | + $allowed_taxonomies = array_keys( $wp_taxonomies ); | |
| 396 | + $allowed_taxonomies = array_diff( $allowed_taxonomies, static::get_setting( 'taxonomies_blacklist' ) ); | |
| 397 | + | |
| 398 | + return "taxonomy IN ('" . implode( "', '", array_map( 'esc_sql', $allowed_taxonomies ) ) . "')"; | |
| 399 | + } | |
| 400 | + | |
| 401 | + /** | |
| 283 | 402 | * Returns escaped SQL for blacklisted post meta. |
| 284 | 403 | * Can be injected directly into a WHERE clause. |
| 285 | 404 | * |
| 286 | 405 | * @access public |
| @@ -288,9 +407,9 @@ | ||
| 288 | 407 | * |
| 289 | 408 | * @return string SQL WHERE clause. |
| 290 | 409 | */ |
| 291 | 410 | public static function get_whitelisted_post_meta_sql() { |
| 292 | - return 'meta_key IN (\'' . implode( '\', \'', array_map( 'esc_sql', self::get_setting( 'post_meta_whitelist' ) ) ) . '\')'; | |
| 411 | + return 'meta_key IN (\'' . implode( '\', \'', array_map( 'esc_sql', static::get_setting( 'post_meta_whitelist' ) ) ) . '\')'; | |
| 293 | 412 | } |
| 294 | 413 | |
| 295 | 414 | /** |
| 296 | 415 | * Returns escaped SQL for allowed post meta keys. |
| @@ -303,9 +422,9 @@ | ||
| 303 | 422 | public static function get_allowed_post_meta_structured() { |
| 304 | 423 | return array( |
| 305 | 424 | 'meta_key' => array( |
| 306 | 425 | 'operator' => 'IN', |
| 307 | - 'values' => array_map( 'esc_sql', self::get_setting( 'post_meta_whitelist' ) ), | |
| 426 | + 'values' => array_map( 'esc_sql', static::get_setting( 'post_meta_whitelist' ) ), | |
| 308 | 427 | ), |
| 309 | 428 | ); |
| 310 | 429 | } |
| 311 | 430 | |
| @@ -320,9 +439,9 @@ | ||
| 320 | 439 | public static function get_blacklisted_taxonomies_structured() { |
| 321 | 440 | return array( |
| 322 | 441 | 'taxonomy' => array( |
| 323 | 442 | 'operator' => 'NOT IN', |
| 324 | - 'values' => array_map( 'esc_sql', self::get_setting( 'taxonomies_blacklist' ) ), | |
| 443 | + 'values' => array_map( 'esc_sql', static::get_setting( 'taxonomies_blacklist' ) ), | |
| 325 | 444 | ), |
| 326 | 445 | ); |
| 327 | 446 | } |
| 328 | 447 | |
| @@ -337,9 +456,9 @@ | ||
| 337 | 456 | public static function get_allowed_taxonomies_structured() { |
| 338 | 457 | global $wp_taxonomies; |
| 339 | 458 | |
| 340 | 459 | $allowed_taxonomies = array_keys( $wp_taxonomies ); |
| 341 | - $allowed_taxonomies = array_diff( $allowed_taxonomies, self::get_setting( 'taxonomies_blacklist' ) ); | |
| 460 | + $allowed_taxonomies = array_diff( $allowed_taxonomies, static::get_setting( 'taxonomies_blacklist' ) ); | |
| 342 | 461 | return array( |
| 343 | 462 | 'taxonomy' => array( |
| 344 | 463 | 'operator' => 'IN', |
| 345 | 464 | 'values' => array_map( 'esc_sql', $allowed_taxonomies ), |
| @@ -356,9 +475,9 @@ | ||
| 356 | 475 | * |
| 357 | 476 | * @return string SQL WHERE clause. |
| 358 | 477 | */ |
| 359 | 478 | public static function get_whitelisted_comment_meta_sql() { |
| 360 | - return 'meta_key IN (\'' . implode( '\', \'', array_map( 'esc_sql', self::get_setting( 'comment_meta_whitelist' ) ) ) . '\')'; | |
| 479 | + return 'meta_key IN (\'' . implode( '\', \'', array_map( 'esc_sql', static::get_setting( 'comment_meta_whitelist' ) ) ) . '\')'; | |
| 361 | 480 | } |
| 362 | 481 | |
| 363 | 482 | /** |
| 364 | 483 | * Returns SQL-escaped values for allowed post meta keys. |
| @@ -371,9 +490,9 @@ | ||
| 371 | 490 | public static function get_allowed_comment_meta_structured() { |
| 372 | 491 | return array( |
| 373 | 492 | 'meta_key' => array( |
| 374 | 493 | 'operator' => 'IN', |
| 375 | - 'values' => array_map( 'esc_sql', self::get_setting( 'comment_meta_whitelist' ) ), | |
| 494 | + 'values' => array_map( 'esc_sql', static::get_setting( 'comment_meta_whitelist' ) ), | |
| 376 | 495 | ), |
| 377 | 496 | ); |
| 378 | 497 | } |
| 379 | 498 | |
| @@ -401,8 +520,25 @@ | ||
| 401 | 520 | ); |
| 402 | 521 | } |
| 403 | 522 | |
| 404 | 523 | /** |
| 524 | + * Returns structured filter values for allowed comment types. | |
| 525 | + * | |
| 526 | + * @access public | |
| 527 | + * @static | |
| 528 | + * | |
| 529 | + * @return array Comment type filter values. | |
| 530 | + */ | |
| 531 | + public static function get_allowed_comment_types_structured() { | |
| 532 | + return array( | |
| 533 | + 'comment_type' => array( | |
| 534 | + 'operator' => 'IN', | |
| 535 | + 'values' => array_map( 'esc_sql', Defaults::get_comment_types_whitelist() ), | |
| 536 | + ), | |
| 537 | + ); | |
| 538 | + } | |
| 539 | + | |
| 540 | + /** | |
| 405 | 541 | * Returns escaped SQL for comments, excluding any spam comments. |
| 406 | 542 | * Can be injected directly into a WHERE clause. |
| 407 | 543 | * |
| 408 | 544 | * @access public |
| @@ -468,9 +604,9 @@ | ||
| 468 | 604 | * |
| 469 | 605 | * @return boolean Whether sync is enabled. |
| 470 | 606 | */ |
| 471 | 607 | public static function is_sync_enabled() { |
| 472 | - return ! ( self::get_setting( 'disable' ) || self::get_setting( 'network_disable' ) ); | |
| 608 | + return ! ( static::get_setting( 'disable' ) || static::get_setting( 'network_disable' ) ); | |
| 473 | 609 | } |
| 474 | 610 | |
| 475 | 611 | /** |
| 476 | 612 | * Set the WP cron state. |
| @@ -559,9 +695,9 @@ | ||
| 559 | 695 | * |
| 560 | 696 | * @return boolean Whether sync is enabled. |
| 561 | 697 | */ |
| 562 | 698 | public static function is_sender_enabled( $queue_id ) { |
| 563 | - return (bool) self::get_setting( $queue_id . '_sender_enabled' ); | |
| 699 | + return (bool) static::get_setting( $queue_id . '_sender_enabled' ); | |
| 564 | 700 | } |
| 565 | 701 | |
| 566 | 702 | /** |
| 567 | 703 | * Whether checksums are enabled. |
| @@ -571,9 +707,9 @@ | ||
| 571 | 707 | * |
| 572 | 708 | * @return boolean Whether sync is enabled. |
| 573 | 709 | */ |
| 574 | 710 | public static function is_checksum_enabled() { |
| 575 | - return ! (bool) self::get_setting( 'checksum_disable' ); | |
| 711 | + return ! (bool) static::get_setting( 'checksum_disable' ); | |
| 576 | 712 | } |
| 577 | 713 | |
| 578 | 714 | /** |
| 579 | 715 | * Whether dedicated Sync flow is enabled. |
| @@ -583,8 +719,31 @@ | ||
| 583 | 719 | * |
| 584 | 720 | * @return boolean Whether dedicated Sync flow is enabled. |
| 585 | 721 | */ |
| 586 | 722 | public static function is_dedicated_sync_enabled() { |
| 587 | - return (bool) self::get_setting( 'dedicated_sync_enabled' ); | |
| 723 | + return (bool) static::get_setting( 'dedicated_sync_enabled' ); | |
| 588 | 724 | } |
| 589 | 725 | |
| 726 | + /** | |
| 727 | + * Whether custom queue table is enabled. | |
| 728 | + * | |
| 729 | + * @access public | |
| 730 | + * @static | |
| 731 | + * | |
| 732 | + * @return boolean Whether custom queue table is enabled. | |
| 733 | + */ | |
| 734 | + public static function is_custom_queue_table_enabled() { | |
| 735 | + return (bool) static::get_setting( 'custom_queue_table_enabled' ); | |
| 736 | + } | |
| 737 | + | |
| 738 | + /** | |
| 739 | + * Whether wpcom rest api is enabled. | |
| 740 | + * | |
| 741 | + * @access public | |
| 742 | + * @static | |
| 743 | + * | |
| 744 | + * @return boolean Whether wpcom rest api is enabled. | |
| 745 | + */ | |
| 746 | + public static function is_wpcom_rest_api_enabled() { | |
| 747 | + return (bool) static::get_setting( 'wpcom_rest_api_enabled' ); | |
| 748 | + } | |
| 590 | 749 | } |