Skip to content

Commit 9f5fc08

Browse files
committed
Route ability reads through the network option on network-activated multisite
E2E surfaced a read/write mismatch: update-settings and create-exclusion-rule correctly wrote to wp_stream_network on network-activated installs, but get-settings and get-exclusion-rules still read from $plugin->settings->options (per-site, populated via Settings::get_options() which gates on is_network_admin() and falls back to get_option() in REST). After a write, the read endpoint returned the old per-site value instead of the just- persisted network value. Route both read abilities through Settings::get_all_setting_values() and make sure the in-memory cache that update_all_setting_values() refreshes also reads from the network option (Settings::get_options() can't be trusted on network-activated REST because is_network_admin() is always false there). Also return from update-settings via get_all_setting_values() so the response reflects the authoritative store.
1 parent 0f8e5a0 commit 9f5fc08

4 files changed

Lines changed: 48 additions & 10 deletions

File tree

abilities/class-ability-get-exclusion-rules.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,12 @@ public function get_output_schema() {
7777
public function execute( $input = null ) {
7878
unset( $input );
7979

80-
$options = (array) $this->plugin->settings->options;
80+
// Route through Settings::get_all_setting_values() so reads hit the
81+
// network option on network-activated multisite (where create-
82+
// exclusion-rule's writes land). A direct read of
83+
// $plugin->settings->options would return the empty per-site option
84+
// in REST contexts, so newly-created rules would not appear.
85+
$options = $this->plugin->settings->get_all_setting_values();
8186
$rules = isset( $options['exclude_rules'] ) ? (array) $options['exclude_rules'] : array();
8287

8388
// Reuse Log's row pivot so output matches how Stream applies the rules internally.

abilities/class-ability-get-settings.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99

1010
/**
1111
* Class - Ability_Get_Settings
12+
*
13+
* Unlike the other read abilities (get-records, get-record, get-alerts,
14+
* get-connectors, get-exclusion-rules) which gate on `view_stream`, this
15+
* one inherits the base permission_callback that requires
16+
* `WP_STREAM_SETTINGS_CAPABILITY` (defaults to `manage_options`). The
17+
* settings payload can include role allowlists and other configuration
18+
* that's intentionally restricted to administrators, so the same cap that
19+
* gates the wp-admin settings screen guards this ability too.
1220
*/
1321
class Ability_Get_Settings extends Ability {
1422

@@ -70,6 +78,13 @@ public function get_output_schema() {
7078
public function execute( $input = null ) {
7179
unset( $input );
7280

73-
return (array) $this->plugin->settings->options;
81+
// Route through Settings::get_all_setting_values() so the network
82+
// option is consulted on network-activated multisite. A direct read
83+
// of $plugin->settings->options would return the (typically empty)
84+
// per-site option in REST contexts (is_network_admin() is always
85+
// false there), making get-settings disagree with update-settings,
86+
// which routes writes to the network option via
87+
// Settings::update_all_setting_values().
88+
return $this->plugin->settings->get_all_setting_values();
7489
}
7590
}

abilities/class-ability-update-settings.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,14 @@ public function execute( $input = null ) {
138138
$sanitized = $this->plugin->settings->sanitize_settings( $filtered );
139139
$merged = array_merge( $current, $sanitized );
140140

141-
// Settings::update_all_setting_values() also refreshes
142-
// $plugin->settings->options so subsequent reads in the same request
143-
// see the fully-populated array (defaults merged in).
141+
// update_all_setting_values() persists to the correct store and
142+
// refreshes $plugin->settings->options for callers in the same
143+
// request. We still return via get_all_setting_values() so the
144+
// response reflects the authoritative store on network-activated
145+
// multisite (where $plugin->settings->options would be the per-site
146+
// option and could disagree with what was just persisted).
144147
$this->plugin->settings->update_all_setting_values( $merged );
145148

146-
return $this->plugin->settings->options;
149+
return $this->plugin->settings->get_all_setting_values();
147150
}
148151
}

classes/class-settings.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,19 +514,34 @@ public function get_all_setting_values() {
514514
* @return bool True on a successful write, false on no-op or failure.
515515
*/
516516
public function update_all_setting_values( array $options ) {
517-
if (
517+
$is_network = (
518518
is_multisite()
519519
&& isset( $this->plugin )
520520
&& $this->plugin->is_network_activated()
521-
) {
521+
);
522+
523+
if ( $is_network ) {
522524
$result = update_site_option( $this->network_options_key, $options );
523525
} else {
524526
$result = update_option( $this->option_key, $options );
525527
}
526528

527529
// Refresh the in-memory copy so subsequent reads in the same request
528-
// see the updated values.
529-
$this->options = $this->get_options();
530+
// see the updated values. On network-activated installs we re-read
531+
// from the network option directly because Settings::get_options()
532+
// gates on is_network_admin() and would return the (now-stale)
533+
// per-site option in REST contexts. Merge defaults on top so callers
534+
// reading $plugin->settings->options keep seeing a fully-populated
535+
// array (matches get_options()'s historical contract).
536+
if ( $is_network ) {
537+
$defaults = $this->get_defaults( $this->option_key );
538+
$this->options = wp_parse_args(
539+
(array) get_site_option( $this->network_options_key, array() ),
540+
$defaults
541+
);
542+
} else {
543+
$this->options = $this->get_options();
544+
}
530545

531546
return (bool) $result;
532547
}

0 commit comments

Comments
 (0)