Make WordPress Core

Ticket #48885: patch.3.diff

File patch.3.diff, 11.8 KB (added by scruffian, 5 years ago)

Remove the hacks for testing

  • src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php

     
    4141                        array(
    4242                                array(
    4343                                        'methods'             => WP_REST_Server::READABLE,
    44                                         'callback'            => array( $this, 'get_item' ),
     44                                        'callback'            => array( $this, 'get_items' ),
    4545                                        'args'                => array(),
    46                                         'permission_callback' => array( $this, 'get_item_permissions_check' ),
     46                                        'permission_callback' => array( $this, 'get_items_permissions_check' ),
    4747                                ),
    4848                                array(
    4949                                        'methods'             => WP_REST_Server::EDITABLE,
    50                                         'callback'            => array( $this, 'update_item' ),
     50                                        'callback'            => array( $this, 'update_items' ),
    5151                                        'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
     52                                        'permission_callback' => array( $this, 'get_items_permissions_check' ),
     53                                ),
     54                                'schema' => array( $this, 'get_public_item_schema' ),
     55                        )
     56                );
     57
     58                register_rest_route(
     59                        $this->namespace,
     60                        '/' . $this->rest_base . '/(?P<option>.+)',
     61                        array(
     62                                'args'   => array(
     63                                        'id' => array(
     64                                                'description' => __( 'The option to fetch.' ),
     65                                                'type'        => 'string',
     66                                        ),
     67                                ),
     68                                array(
     69                                        'methods'             => WP_REST_Server::READABLE,
     70                                        'callback'            => array( $this, 'get_item' ),
    5271                                        'permission_callback' => array( $this, 'get_item_permissions_check' ),
     72                                        'args'                => array(),
    5373                                ),
     74                                array(
     75                                        'methods'             => WP_REST_Server::EDITABLE,
     76                                        'callback'            => array( $this, 'update_item' ),
     77                                        'permission_callback' => array( $this, 'update_item_permissions_check' ),
     78                                        'args'                => array(),
     79                                ),
    5480                                'schema' => array( $this, 'get_public_item_schema' ),
    5581                        )
    5682                );
    57 
    5883        }
    5984
    6085        /**
     
    6590         * @param WP_REST_Request $request Full details about the request.
    6691         * @return bool True if the request has read access for the item, otherwise false.
    6792         */
     93        public function get_items_permissions_check( $request ) {
     94                return current_user_can( 'manage_options' );
     95        }
     96
     97        /**
     98         * Checks if a given request has access to read a setting.
     99         *
     100         * @since 4.7.0
     101         *
     102         * @param WP_REST_Request $request Full details about the request.
     103         * @return bool True if the request has read access for the item, otherwise false.
     104         */
    68105        public function get_item_permissions_check( $request ) {
     106                return current_user_can( 'edit_posts' );
     107        }
     108
     109        /**
     110         * Checks if a given request has access to update a setting.
     111         *
     112         * @since 4.7.0
     113         *
     114         * @param WP_REST_Request $request Full details about the request.
     115         * @return bool True if the request has update access for the item, otherwise false.
     116         */
     117        public function update_item_permissions_check( $request ) {
    69118                return current_user_can( 'manage_options' );
    70119        }
    71120
     121
    72122        /**
     123         * Filters the value of a setting recognized by the REST API.
     124         *
     125         * Allow hijacking the setting value and overriding the built-in behavior by returning a
     126         * non-null value.  The returned value will be presented as the setting value instead.
     127         *
     128         * @since 4.7.0
     129         *
     130         * @param mixed  $result Value to use for the requested setting. Can be a scalar
     131         *                       matching the registered schema for the setting, or null to
     132         *                       follow the default get_option() behavior.
     133         * @param string $name   Setting name (as shown in REST API responses).
     134         * @param array  $args   Arguments passed to register_setting() for this setting.
     135         */
     136        private function get_filtered_setting( $name, $args ) {
     137                $response = apply_filters( 'rest_pre_get_setting', null, $name, $args );
     138
     139                if ( is_null( $response) ) {
     140                        // Default to a null value as "null" in the response means "not set".
     141                        $response = get_option( $args['option_name'], $args['schema']['default'] );
     142                }
     143
     144                /*
     145                        * Because get_option() is lossy, we have to
     146                        * cast values to the type they are registered with.
     147                        */
     148                return $this->prepare_value( $response, $args['schema'] );
     149        }
     150
     151        /**
    73152         * Retrieves the settings.
    74153         *
    75154         * @since 4.7.0
     
    77156         * @param WP_REST_Request $request Full details about the request.
    78157         * @return array|WP_Error Array on success, or WP_Error object on failure.
    79158         */
    80         public function get_item( $request ) {
     159        public function get_items( $request ) {
    81160                $options  = $this->get_registered_options();
    82161                $response = array();
    83162
    84163                foreach ( $options as $name => $args ) {
    85                         /**
    86                          * Filters the value of a setting recognized by the REST API.
    87                          *
    88                          * Allow hijacking the setting value and overriding the built-in behavior by returning a
    89                          * non-null value.  The returned value will be presented as the setting value instead.
    90                          *
    91                          * @since 4.7.0
    92                          *
    93                          * @param mixed  $result Value to use for the requested setting. Can be a scalar
    94                          *                       matching the registered schema for the setting, or null to
    95                          *                       follow the default get_option() behavior.
    96                          * @param string $name   Setting name (as shown in REST API responses).
    97                          * @param array  $args   Arguments passed to register_setting() for this setting.
    98                          */
    99                         $response[ $name ] = apply_filters( 'rest_pre_get_setting', null, $name, $args );
    100 
    101                         if ( is_null( $response[ $name ] ) ) {
    102                                 // Default to a null value as "null" in the response means "not set".
    103                                 $response[ $name ] = get_option( $args['option_name'], $args['schema']['default'] );
    104                         }
    105 
    106                         /*
    107                          * Because get_option() is lossy, we have to
    108                          * cast values to the type they are registered with.
    109                          */
    110                         $response[ $name ] = $this->prepare_value( $response[ $name ], $args['schema'] );
     164                        $response[ $name ] = $this->get_filtered_setting( $name, $args );
    111165                }
    112166
    113167                return $response;
     
    135189        }
    136190
    137191        /**
     192         * Filters whether to preempt a setting value update.
     193         *
     194         * Allows hijacking the setting update logic and overriding the built-in behavior by
     195         * returning true.
     196         *
     197         * @since 4.7.0
     198         *
     199         * @param bool   $result Whether to override the default behavior for updating the
     200         *                       value of a setting.
     201         * @param string $name   Setting name (as shown in REST API responses).
     202         * @param mixed  $value  Updated setting value.
     203         * @param array  $args   Arguments passed to register_setting() for this setting.
     204         */
     205        private function filtered_update_option( $name, $value, $args ) {
     206                $updated = apply_filters( 'rest_pre_update_setting', false, $name, $value, $args );
     207
     208                if ( $updated ) {
     209                        return;
     210                }
     211
     212                /*
     213                * A null value for an option would have the same effect as
     214                * deleting the option from the database, and relying on the
     215                * default value.
     216                */
     217                if ( is_null( $value ) ) {
     218                        /*
     219                        * A null value is returned in the response for any option
     220                        * that has a non-scalar value.
     221                        *
     222                        * To protect clients from accidentally including the null
     223                        * values from a response object in a request, we do not allow
     224                        * options with values that don't pass validation to be updated to null.
     225                        * Without this added protection a client could mistakenly
     226                        * delete all options that have invalid values from the
     227                        * database.
     228                        */
     229                        if ( is_wp_error( rest_validate_value_from_schema( get_option( $args['option_name'], false ), $args['schema'] ) ) ) {
     230                                return new WP_Error(
     231                                        'rest_invalid_stored_value',
     232                                        /* translators: %s: Property name. */
     233                                        sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
     234                                        array( 'status' => 500 )
     235                                );
     236                        }
     237
     238                        delete_option( $args['option_name'] );
     239                } else {
     240                        update_option( $args['option_name'], $value );
     241                }
     242        }
     243
     244        /**
    138245         * Updates settings for the settings object.
    139246         *
    140247         * @since 4.7.0
     
    142249         * @param WP_REST_Request $request Full details about the request.
    143250         * @return array|WP_Error Array on success, or error object on failure.
    144251         */
    145         public function update_item( $request ) {
     252        public function update_items( $request ) {
    146253                $options = $this->get_registered_options();
    147254
    148255                $params = $request->get_params();
     
    152259                                continue;
    153260                        }
    154261
    155                         /**
    156                          * Filters whether to preempt a setting value update.
    157                          *
    158                          * Allows hijacking the setting update logic and overriding the built-in behavior by
    159                          * returning true.
    160                          *
    161                          * @since 4.7.0
    162                          *
    163                          * @param bool   $result Whether to override the default behavior for updating the
    164                          *                       value of a setting.
    165                          * @param string $name   Setting name (as shown in REST API responses).
    166                          * @param mixed  $value  Updated setting value.
    167                          * @param array  $args   Arguments passed to register_setting() for this setting.
    168                          */
    169                         $updated = apply_filters( 'rest_pre_update_setting', false, $name, $request[ $name ], $args );
    170 
    171                         if ( $updated ) {
    172                                 continue;
    173                         }
    174 
    175                         /*
    176                          * A null value for an option would have the same effect as
    177                          * deleting the option from the database, and relying on the
    178                          * default value.
    179                          */
    180                         if ( is_null( $request[ $name ] ) ) {
    181                                 /*
    182                                  * A null value is returned in the response for any option
    183                                  * that has a non-scalar value.
    184                                  *
    185                                  * To protect clients from accidentally including the null
    186                                  * values from a response object in a request, we do not allow
    187                                  * options with values that don't pass validation to be updated to null.
    188                                  * Without this added protection a client could mistakenly
    189                                  * delete all options that have invalid values from the
    190                                  * database.
    191                                  */
    192                                 if ( is_wp_error( rest_validate_value_from_schema( get_option( $args['option_name'], false ), $args['schema'] ) ) ) {
    193                                         return new WP_Error(
    194                                                 'rest_invalid_stored_value',
    195                                                 /* translators: %s: Property name. */
    196                                                 sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
    197                                                 array( 'status' => 500 )
    198                                         );
    199                                 }
    200 
    201                                 delete_option( $args['option_name'] );
    202                         } else {
    203                                 update_option( $args['option_name'], $request[ $name ] );
    204                         }
     262                        $this->filtered_update_option( $name, $request[ $name ], $args );
    205263                }
    206264
    207                 return $this->get_item( $request );
     265                return $this->get_items( $request );
    208266        }
    209267
    210268        /**
     
    345403
    346404                return $schema;
    347405        }
     406
     407        /**
     408         * Retrieves a single option
     409         *
     410         * @since ?
     411         *
     412         * @param WP_REST_Request $request Full details about the request.
     413         * @return array|WP_Error Array on success, or WP_Error object on failure.
     414         */
     415        public function get_item( $request ) {
     416                $name = $request['option'];
     417                $options  = $this->get_registered_options();
     418                if ( ! isset( $options[ $name ] ) ) {
     419                        return new WP_Error(
     420                                'rest_invalid_setting',
     421                                /* translators: %s: Settings name. */
     422                                sprintf( __( '%s is not a registered setting.' ), $name ),
     423                                array( 'status' => 500 )
     424                        );
     425                }
     426
     427                $response = array();
     428                $response[ $name ] = $this->get_filtered_setting( $name, $options[ $name ] );
     429                return $response;
     430        }
     431
     432        /**
     433         * Updates a given setting
     434         *
     435         * @since 4.7.0
     436         *
     437         * @param WP_REST_Request $request Full details about the request.
     438         * @return array|WP_Error Array on success, or error object on failure.
     439         */
     440        public function update_item( $request ) {
     441                $name = $request['option'];
     442                $options = $this->get_registered_options();
     443
     444                $params = $request->get_params();
     445
     446                if ( ! array_key_exists( $name, $params ) ) {
     447                        return new WP_Error(
     448                                'rest_invalid_setting',
     449                                /* translators: %s: Settings name. */
     450                                sprintf( __( '%s is not a registered setting.' ), $name ),
     451                                array( 'status' => 500 )
     452                        );
     453                }
     454
     455                $this->filtered_update_option( $name, $request[ $name ], $options[ $name ] );
     456
     457                return $this->get_item( $request );
     458        }
    348459}