Skip to content

Commit bff6522

Browse files
authored
Introduce Sync blacklist for jetpack_options (#46852)
* Introduce Sync blacklist for 'jetpack_options'
1 parent 0000326 commit bff6522

File tree

5 files changed

+84
-0
lines changed

5 files changed

+84
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: added
3+
4+
Introduce Sync blacklist for `jetpack_options`.

projects/packages/sync/src/class-defaults.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,4 +1385,13 @@ public static function is_multi_network() {
13851385
* @var int Bool-ish. Default 1.
13861386
*/
13871387
public static $default_wpcom_rest_api_enabled = 1;
1388+
1389+
/**
1390+
* A list of 'jetpack_options' specific keys we want to ignore.
1391+
*
1392+
* @var array
1393+
*/
1394+
public static $jetpack_options_blacklist = array(
1395+
'last_heartbeat',
1396+
);
13881397
}

projects/packages/sync/src/modules/class-options.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,15 @@ public function whitelist_options( $args ) {
317317
return false;
318318
}
319319

320+
// Check if 'jetpack_options' were updated and reject if the change affected only blacklisted keys.
321+
if ( 'jetpack_options' === $args[0] && 3 === count( $args ) ) {
322+
if ( ! $this->should_enqueue_jetpack_options_update( $args[1], $args[2] ) ) {
323+
return false;
324+
}
325+
326+
return $args;
327+
}
328+
320329
// Filter our weird array( false ) value for theme_mods_*.
321330
if ( str_starts_with( $args[0], 'theme_mods_' ) ) {
322331
$this->filter_theme_mods( $args[1] );
@@ -487,4 +496,49 @@ public function get_object_by_id( $object_type, $id ) {
487496

488497
return 'OPTION-DOES-NOT-EXIST';
489498
}
499+
500+
/**
501+
* Check if 'jetpack_options' option update should be processed based on excluded keys.
502+
*
503+
* @param mixed $old_value The old option value.
504+
* @param mixed $value The new option value.
505+
* @return bool False if only excluded keys changed (or no change), true otherwise.
506+
*/
507+
private function should_enqueue_jetpack_options_update( $old_value, $value ) {
508+
// No changes at all.
509+
if ( $old_value === $value ) {
510+
return false;
511+
}
512+
// Values are different but not both arrays - meaningful change.
513+
if ( ! is_array( $old_value ) || ! is_array( $value ) ) {
514+
return true;
515+
}
516+
// Determine all top-level keys present in either the old or new value.
517+
$all_keys = array_unique(
518+
array_merge(
519+
array_keys( $old_value ),
520+
array_keys( $value )
521+
)
522+
);
523+
// Short-circuit as soon as we find a changed key that is not blacklisted.
524+
foreach ( $all_keys as $key ) {
525+
$old_has_key = array_key_exists( $key, $old_value );
526+
$new_has_key = array_key_exists( $key, $value );
527+
// Key was added or removed.
528+
if ( ! $old_has_key || ! $new_has_key ) {
529+
if ( ! in_array( $key, Defaults::$jetpack_options_blacklist, true ) ) {
530+
return true;
531+
}
532+
continue;
533+
}
534+
// Key exists in both arrays but the value changed.
535+
if ( $old_value[ $key ] !== $value[ $key ] ) {
536+
if ( ! in_array( $key, Defaults::$jetpack_options_blacklist, true ) ) {
537+
return true;
538+
}
539+
}
540+
}
541+
// Either there were no effective changes, or all changed keys are excluded.
542+
return false;
543+
}
490544
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Significance: patch
2+
Type: other
3+
Comment: Note that there are no user-facing changes; update Sync-related unit tests only.
4+
5+

projects/plugins/jetpack/tests/php/sync/Jetpack_Sync_Options_Test.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,18 @@ public function test_sync_default_contentless_options() {
343343
);
344344
}
345345

346+
public function test_don_t_sync_jetpack_options_if_changed_key_is_blacklisted() {
347+
$this->setSyncClientDefaults();
348+
349+
$this->server_replica_storage->reset();
350+
351+
Jetpack_Options::update_option( 'last_heartbeat', microtime( true ) );
352+
353+
$this->sender->do_sync();
354+
355+
$this->assertFalse( $this->server_replica_storage->get_option( 'jetpack_options' ) );
356+
}
357+
346358
public function assertOptionIsSynced( $option_name, $value ) {
347359
$this->assertEqualsObject( $value, $this->server_replica_storage->get_option( $option_name ), 'Option ' . $option_name . ' didn\'t have the expected value of ' . wp_json_encode( $value, JSON_UNESCAPED_SLASHES ) );
348360
}

0 commit comments

Comments
 (0)