Changeset 63526
- Timestamp:
- 09/08/2026 08:41:22 AM (less than one hour ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
src/wp-includes/default-filters.php (modified) (1 diff)
-
src/wp-includes/option.php (modified) (2 diffs)
-
src/wp-includes/rest-api.php (modified) (1 diff)
-
tests/phpunit/tests/rest-api/rest-settings-controller.php (modified) (3 diffs)
-
tests/qunit/fixtures/wp-api-generated.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/default-filters.php
r63012 r63526 546 546 add_action( 'rest_api_init', 'rest_api_default_filters', 10, 1 ); 547 547 add_action( 'rest_api_init', 'register_initial_settings', 10 ); 548 add_filter( 'rest_pre_update_setting', 'rest_restrict_privacy_policy_page_setting_update', 10, 2 ); 548 549 add_action( 'rest_api_init', 'create_initial_rest_routes', 99 ); 549 550 add_action( 'parse_request', 'rest_api_loaded' ); -
trunk/src/wp-includes/option.php
r63491 r63526 2740 2740 * @since 4.7.0 2741 2741 * @since 6.0.1 The `show_on_front`, `page_on_front`, and `page_for_posts` options were added. 2742 * @since 7.2.0 The `wp_page_for_privacy_policy` option was registered, exposed as `page_for_privacy_policy`. 2742 2743 */ 2743 2744 function register_initial_settings() { … … 2933 2934 2934 2935 register_setting( 2936 'reading', 2937 'wp_page_for_privacy_policy', 2938 array( 2939 'show_in_rest' => array( 2940 'name' => 'page_for_privacy_policy', 2941 ), 2942 'type' => 'integer', 2943 'description' => __( 'The ID of the page that should be displayed as the privacy policy page' ), 2944 ) 2945 ); 2946 2947 register_setting( 2935 2948 'discussion', 2936 2949 'default_ping_status', -
trunk/src/wp-includes/rest-api.php
r63509 r63526 3448 3448 } 3449 3449 3450 /** 3451 * Prevents users without the `manage_privacy_options` capability from 3452 * changing the privacy policy page through the REST API. 3453 * 3454 * The settings endpoint only checks `manage_options`. On multisite the 3455 * `manage_privacy_options` capability maps to `manage_network`, so a site 3456 * administrator can read the setting but must not change it, matching the 3457 * Settings > Privacy screen. 3458 * 3459 * @since 7.2.0 3460 * 3461 * @param bool $updated Whether the setting update has already been handled. 3462 * @param string $name Setting name (as shown in REST API responses). 3463 * @return bool Whether to short-circuit the update. 3464 */ 3465 function rest_restrict_privacy_policy_page_setting_update( $updated, $name ) { 3466 if ( 'page_for_privacy_policy' === $name && ! current_user_can( 'manage_privacy_options' ) ) { 3467 return true; 3468 } 3469 return $updated; 3470 } 3450 3471 3451 3472 /** -
trunk/tests/phpunit/tests/rest-api/rest-settings-controller.php
r63161 r63526 58 58 } 59 59 60 remove_filter( 'map_meta_cap', array( $this, 'deny_manage_privacy_options' ), 10 ); 61 60 62 parent::tear_down(); 63 } 64 65 /** 66 * Maps `manage_privacy_options` to `do_not_allow`, as happens for a site 67 * administrator on multisite. 68 * 69 * @param string[] $caps Primitive capabilities required. 70 * @param string $cap Capability being checked. 71 * @return string[] Primitive capabilities required. 72 */ 73 public function deny_manage_privacy_options( $caps, $cap ) { 74 if ( 'manage_privacy_options' === $cap ) { 75 return array( 'do_not_allow' ); 76 } 77 return $caps; 61 78 } 62 79 … … 117 134 'page_on_front', 118 135 'page_for_posts', 136 'page_for_privacy_policy', 119 137 'default_ping_status', 120 138 'default_comment_status', … … 402 420 $this->assertSame( 'The new title!', $data['title'] ); 403 421 $this->assertSame( get_option( 'blogname' ), $data['title'] ); 422 } 423 424 public function test_update_item_privacy_policy_page() { 425 wp_set_current_user( self::$administrator ); 426 if ( is_multisite() ) { 427 grant_super_admin( self::$administrator ); 428 } 429 $page_id = self::factory()->post->create( array( 'post_type' => 'page' ) ); 430 431 $request = new WP_REST_Request( 'PUT', '/wp/v2/settings' ); 432 $request->set_param( 'page_for_privacy_policy', $page_id ); 433 $response = rest_get_server()->dispatch( $request ); 434 $data = $response->get_data(); 435 436 $this->assertSame( 200, $response->get_status() ); 437 $this->assertSame( $page_id, $data['page_for_privacy_policy'] ); 438 $this->assertSame( $page_id, (int) get_option( 'wp_page_for_privacy_policy' ) ); 439 } 440 441 public function test_update_item_privacy_policy_page_without_capability() { 442 wp_set_current_user( self::$administrator ); 443 $page_id = self::factory()->post->create( array( 'post_type' => 'page' ) ); 444 update_option( 'wp_page_for_privacy_policy', $page_id ); 445 $other_page_id = self::factory()->post->create( array( 'post_type' => 'page' ) ); 446 add_filter( 'map_meta_cap', array( $this, 'deny_manage_privacy_options' ), 10, 2 ); 447 448 $request = new WP_REST_Request( 'PUT', '/wp/v2/settings' ); 449 $request->set_param( 'page_for_privacy_policy', $other_page_id ); 450 $response = rest_get_server()->dispatch( $request ); 451 $data = $response->get_data(); 452 453 $this->assertSame( 200, $response->get_status() ); 454 $this->assertSame( $page_id, $data['page_for_privacy_policy'], 'The response should still report the previous page.' ); 455 $this->assertSame( $page_id, (int) get_option( 'wp_page_for_privacy_policy' ), 'The option should not change.' ); 404 456 } 405 457 -
trunk/tests/qunit/fixtures/wp-api-generated.js
r63200 r63526 11238 11238 "required": false 11239 11239 }, 11240 "page_for_privacy_policy": { 11241 "title": "", 11242 "description": "The ID of the page that should be displayed as the privacy policy page", 11243 "type": "integer", 11244 "required": false 11245 }, 11240 11246 "default_ping_status": { 11241 11247 "title": "", … … 14933 14939 "page_on_front": 0, 14934 14940 "page_for_posts": 0, 14941 "page_for_privacy_policy": 0, 14935 14942 "default_ping_status": "open", 14936 14943 "default_comment_status": "open",
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)