WordPress.org

Make WordPress Core

Ticket #38786: 38786.diff

File 38786.diff, 10.9 KB (added by tharsheblows, 4 years ago)

support for custom names in get / update / delete meta

  • src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php

     
    6666                $response = array();
    6767
    6868                foreach ( $fields as $name => $args ) {
    69                         $all_values = get_metadata( $this->get_meta_type(), $object_id, $name, false );
     69                        $meta_key = $args['name'];
     70                        if ( empty( $meta_key ) ) {
     71                                return new WP_Error( 'rest_cannot_get', sprintf( __( 'The %s field does not have a meta key.' ), $name ) );
     72                        }
     73
     74                        $all_values = get_metadata( $this->get_meta_type(), $object_id, $meta_key, false );
    7075                        if ( $args['single'] ) {
    7176                                if ( empty( $all_values ) ) {
    7277                                        $value = $args['schema']['default'];
     
    127132                                continue;
    128133                        }
    129134
     135                        $meta_key = $args['name'];
     136                        if ( empty( $meta_key ) ) {
     137                                return new WP_Error( 'rest_cannot_get', sprintf( __( 'The %s field does not have a meta key.' ), $name ) );
     138                        }
     139
    130140                        /*
    131141                         * A null value means reset the field, which is essentially deleting it
    132142                         * from the database and then relying on the default value.
    133143                         */
    134144                        if ( is_null( $request[ $name ] ) ) {
    135                                 $result = $this->delete_meta_value( $object_id, $name );
     145                                $result = $this->delete_meta_value( $object_id, $meta_key, $name );
    136146                                if ( is_wp_error( $result ) ) {
    137147                                        return $result;
    138148                                }
     
    148158                        $value = rest_sanitize_value_from_schema( $request[ $name ], $args['schema'] );
    149159
    150160                        if ( $args['single'] ) {
    151                                 $result = $this->update_meta_value( $object_id, $name, $value );
     161                                $result = $this->update_meta_value( $object_id, $meta_key, $value, $name );
    152162                        } else {
    153                                 $result = $this->update_multi_meta_value( $object_id, $name, $value );
     163                                $result = $this->update_multi_meta_value( $object_id, $meta_key, $value, $name );
    154164                        }
    155165
    156166                        if ( is_wp_error( $result ) ) {
     
    171181         * @param string $name      Key for the field.
    172182         * @return bool|WP_Error True if meta field is deleted, WP_Error otherwise.
    173183         */
    174         protected function delete_meta_value( $object_id, $name ) {
     184        protected function delete_meta_value( $object_id, $meta_key, $name ) {
    175185                $meta_type = $this->get_meta_type();
    176                 if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $name ) ) {
     186                if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $meta_key ) ) {
    177187                        return new WP_Error(
    178188                                'rest_cannot_delete',
    179189                                sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
     
    181191                        );
    182192                }
    183193
    184                 if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $name ) ) ) {
     194                if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ) ) ) {
    185195                        return new WP_Error(
    186196                                'rest_meta_database_error',
    187197                                __( 'Could not delete meta value from database.' ),
     
    205215         * @param array  $values    List of values to update to.
    206216         * @return bool|WP_Error True if meta fields are updated, WP_Error otherwise.
    207217         */
    208         protected function update_multi_meta_value( $object_id, $name, $values ) {
     218        protected function update_multi_meta_value( $object_id, $meta_key, $values, $name ) {
    209219                $meta_type = $this->get_meta_type();
    210                 if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $name ) ) {
     220                if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
    211221                        return new WP_Error(
    212222                                'rest_cannot_update',
    213223                                sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
     
    215225                        );
    216226                }
    217227
    218                 $current = get_metadata( $meta_type, $object_id, $name, false );
     228                $current = get_metadata( $meta_type, $object_id, $meta_key, false );
    219229
    220230                $to_remove = $current;
    221231                $to_add    = $values;
     
    242252                $to_remove = array_unique( $to_remove );
    243253
    244254                foreach ( $to_remove as $value ) {
    245                         if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
     255                        if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
    246256                                return new WP_Error(
    247257                                        'rest_meta_database_error',
    248258                                        __( 'Could not update meta value in database.' ),
     
    252262                }
    253263
    254264                foreach ( $to_add as $value ) {
    255                         if ( ! add_metadata( $meta_type, $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
     265                        if ( ! add_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
    256266                                return new WP_Error(
    257267                                        'rest_meta_database_error',
    258268                                        __( 'Could not update meta value in database.' ),
     
    275285         * @param mixed  $value     Updated value.
    276286         * @return bool|WP_Error True if the meta field was updated, WP_Error otherwise.
    277287         */
    278         protected function update_meta_value( $object_id, $name, $value ) {
     288        protected function update_meta_value( $object_id, $meta_key, $value, $name ) {
    279289                $meta_type = $this->get_meta_type();
    280                 if ( ! current_user_can(  "edit_{$meta_type}_meta", $object_id, $name ) ) {
     290                if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
    281291                        return new WP_Error(
    282292                                'rest_cannot_update',
    283293                                sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
     
    285295                        );
    286296                }
    287297
    288                 $meta_key   = wp_slash( $name );
     298                $meta_key   = wp_slash( $meta_key );
    289299                $meta_value = wp_slash( $value );
    290300
    291301                // Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false.
     
    330340                                $rest_args = $args['show_in_rest'];
    331341                        }
    332342
     343                        $property_name = ( ! empty( $rest_args['name'] ) ) ? $rest_args['name'] : $name;
     344
    333345                        $default_args = array(
    334                                 'name'             => $name,
    335346                                'single'           => $args['single'],
    336347                                'type'             => ! empty( $args['type'] ) ? $args['type'] : null,
    337348                                'schema'           => array(),
     
    361372                                $rest_args['schema']['type'] = 'array';
    362373                        }
    363374
    364                         $registered[ $rest_args['name'] ] = $rest_args;
     375                        $rest_args['name'] = $name;
     376
     377                        $registered[ $property_name ] = $rest_args;
    365378                }
    366379
    367380                return $registered;
  • tests/phpunit/tests/rest-api/rest-post-meta-fields.php

     
    7979                        'show_in_rest' => true,
    8080                ));
    8181
     82                register_meta( 'post', 'test_custom_name', array(
     83                        'single' => true,
     84                        'type' => 'string',
     85                        'show_in_rest' => array(
     86                                'name'  => 'new_name',
     87                        ),
     88                ));
     89
     90                register_meta( 'post', 'test_custom_name_multi', array(
     91                        'single' => false,
     92                        'type' => 'string',
     93                        'show_in_rest' => array(
     94                                'name'  => 'new_name_multi',
     95                        ),
     96                ));
     97
    8298                /** @var WP_REST_Server $wp_rest_server */
    8399                global $wp_rest_server;
    84100                $this->server = $wp_rest_server = new Spy_REST_Server;
     
    227243                $this->assertSame( true, $meta['test_bool'] );
    228244        }
    229245
     246        public function test_get_value_custom_name() {
     247                add_post_meta( self::$post_id, 'test_custom_name', 'janet' );
     248
     249                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     250                $response = $this->server->dispatch( $request );
     251
     252                $this->assertEquals( 200, $response->get_status() );
     253
     254                $data = $response->get_data();
     255                $this->assertArrayHasKey( 'meta', $data );
     256
     257                $meta = (array) $data['meta'];
     258                $this->assertArrayHasKey( 'new_name', $meta );
     259                $this->assertEquals( 'janet', $meta['new_name'] );
     260        }
     261
    230262        /**
    231263         * @depends test_get_value
    232264         */
     
    681713                $this->assertContains( 8, $meta );
    682714        }
    683715
     716        /**
     717         * @depends test_get_value_custom_name
     718         */
     719        public function test_set_value_custom_name() {
     720                // Ensure no data exists currently.
     721                $values = get_post_meta( self::$post_id, 'test_custom_name', false );
     722                $this->assertEmpty( $values );
     723
     724                $this->grant_write_permission();
     725
     726                $data = array(
     727                        'meta' => array(
     728                                'new_name' => 'janet',
     729                        ),
     730                );
     731                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     732                $request->set_body_params( $data );
     733
     734                $response = $this->server->dispatch( $request );
     735                $this->assertEquals( 200, $response->get_status() );
     736
     737                $meta = get_post_meta( self::$post_id, 'test_custom_name', false );
     738                $this->assertNotEmpty( $meta );
     739                $this->assertCount( 1, $meta );
     740                $this->assertEquals( 'janet', $meta[0] );
     741
     742                $data = $response->get_data();
     743                $meta = (array) $data['meta'];
     744                $this->assertArrayHasKey( 'new_name', $meta );
     745                $this->assertEquals( 'janet', $meta['new_name'] );
     746        }
     747
     748        public function test_set_value_custom_name_multiple() {
     749                // Ensure no data exists currently.
     750                $values = get_post_meta( self::$post_id, 'test_custom_name_multi', false );
     751                $this->assertEmpty( $values );
     752
     753                $this->grant_write_permission();
     754
     755                $data = array(
     756                        'meta' => array(
     757                                'new_name_multi' => array( 'janet' ),
     758                        ),
     759                );
     760                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     761                $request->set_body_params( $data );
     762
     763                $response = $this->server->dispatch( $request );
     764                $this->assertEquals( 200, $response->get_status() );
     765
     766                $meta = get_post_meta( self::$post_id, 'test_custom_name_multi', false );
     767                $this->assertNotEmpty( $meta );
     768                $this->assertCount( 1, $meta );
     769                $this->assertEquals( 'janet', $meta[0] );
     770
     771                // Add another value.
     772                $data = array(
     773                        'meta' => array(
     774                                'new_name_multi' => array( 'janet', 'graeme' ),
     775                        ),
     776                );
     777                $request->set_body_params( $data );
     778
     779                $response = $this->server->dispatch( $request );
     780                $this->assertEquals( 200, $response->get_status() );
     781
     782                $meta = get_post_meta( self::$post_id, 'test_custom_name_multi', false );
     783                $this->assertNotEmpty( $meta );
     784                $this->assertCount( 2, $meta );
     785                $this->assertContains( 'janet', $meta );
     786                $this->assertContains( 'graeme', $meta );
     787        }
     788
    684789        public function test_remove_multi_value_db_error() {
    685790                add_post_meta( self::$post_id, 'test_multi', 'val1' );
    686791                $values = get_post_meta( self::$post_id, 'test_multi', false );
     
    791896                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
    792897        }
    793898
     899        public function test_delete_value_custom_name() {
     900                add_post_meta( self::$post_id, 'test_custom_name', 'janet' );
     901                $current = get_post_meta( self::$post_id, 'test_custom_name', true );
     902                $this->assertEquals( 'janet', $current );
     903
     904                $this->grant_write_permission();
     905
     906                $data = array(
     907                        'meta' => array(
     908                                'new_name' => null,
     909                        ),
     910                );
     911                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     912                $request->set_body_params( $data );
     913
     914                $response = $this->server->dispatch( $request );
     915                $this->assertEquals( 200, $response->get_status() );
     916
     917                $meta = get_post_meta( self::$post_id, 'test_custom_name', false );
     918                $this->assertEmpty( $meta );
     919        }
     920
    794921        public function test_get_schema() {
    795922                $request = new WP_REST_Request( 'OPTIONS', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
    796923                $response = $this->server->dispatch( $request );