WordPress.org

Make WordPress Core

Ticket #38412: 38412.4.diff

File 38412.4.diff, 81.2 KB (added by boonebgorges, 5 years ago)
  • src/wp-includes/capabilities.php

    diff --git a/src/wp-includes/capabilities.php b/src/wp-includes/capabilities.php
    index fe87bc8..4027379 100644
    a b function map_meta_cap( $cap, $user_id ) { 
    242242        case 'edit_post_meta':
    243243        case 'delete_post_meta':
    244244        case 'add_post_meta':
    245                 $post = get_post( $args[0] );
    246                 if ( ! $post ) {
     245        case 'edit_comment_meta':
     246        case 'delete_comment_meta':
     247        case 'add_comment_meta':
     248        case 'edit_term_meta':
     249        case 'delete_term_meta':
     250        case 'add_term_meta':
     251        case 'edit_user_meta':
     252        case 'delete_user_meta':
     253        case 'add_user_meta':
     254                list( $_, $object_type, $_ ) = explode( '_', $cap );
     255                $object_id = (int) $args[0];
     256
     257                switch ( $object_type ) {
     258                        case 'post':
     259                                $post = get_post( $object_id );
     260                                if ( ! $post ) {
     261                                        break;
     262                                }
     263
     264                                $sub_type = get_post_type( $post );
     265                                break;
     266
     267                        case 'comment':
     268                                $comment = get_comment( $object_id );
     269                                if ( ! $comment ) {
     270                                        break;
     271                                }
     272
     273                                $sub_type = empty( $comment->comment_type ) ? 'comment' : $comment->comment_type;
     274                                break;
     275
     276                        case 'term':
     277                                $term = get_term( $object_id );
     278                                if ( ! $term ) {
     279                                        break;
     280                                }
     281
     282                                $sub_type = $term->taxonomy;
     283                                break;
     284
     285                        case 'user':
     286                                $user = get_user_by( 'id', $object_id );
     287                                if ( ! $user ) {
     288                                        break;
     289                                }
     290
     291                                $sub_type = 'user';
     292                                break;
     293                }
     294
     295                if ( empty( $sub_type ) ) {
    247296                        $caps[] = 'do_not_allow';
    248297                        break;
    249298                }
    250299
    251                 $post_type = get_post_type( $post );
     300                $caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id );
    252301
    253                 $caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
     302                $meta_key = isset( $args[1] ) ? $args[1] : false;
    254303
    255                 $meta_key = isset( $args[ 1 ] ) ? $args[ 1 ] : false;
     304                $has_filter = has_filter( "auth_{$object_type}_meta_{$meta_key}" ) || has_filter( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}" );
     305                if ( $meta_key && $has_filter ) {
     306                        /** This filter is documented in wp-includes/meta.php */
     307                        $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", false, $meta_key, $object_id, $user_id, $cap, $caps );
    256308
    257                 if ( $meta_key && ( has_filter( "auth_post_meta_{$meta_key}" ) || has_filter( "auth_post_{$post_type}_meta_{$meta_key}" ) ) ) {
    258                         /**
    259                          * Filters whether the user is allowed to add post meta to a post.
    260                          *
    261                          * The dynamic portion of the hook name, `$meta_key`, refers to the
    262                          * meta key passed to map_meta_cap().
    263                          *
    264                          * @since 3.3.0
    265                          *
    266                          * @param bool   $allowed  Whether the user can add the post meta. Default false.
    267                          * @param string $meta_key The meta key.
    268                          * @param int    $post_id  Post ID.
    269                          * @param int    $user_id  User ID.
    270                          * @param string $cap      Capability name.
    271                          * @param array  $caps     User capabilities.
    272                          */
    273                         $allowed = apply_filters( "auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps );
     309                        /** This filter is documented in wp-includes/meta.php */
     310                        $allowed = apply_filters( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
    274311
    275                         /**
    276                          * Filters whether the user is allowed to add post meta to a post of a given type.
    277                          *
    278                          * The dynamic portions of the hook name, `$meta_key` and `$post_type`,
    279                          * refer to the meta key passed to map_meta_cap() and the post type, respectively.
    280                          *
    281                          * @since 4.6.0
    282                          *
    283                          * @param bool   $allowed  Whether the user can add the post meta. Default false.
    284                          * @param string $meta_key The meta key.
    285                          * @param int    $post_id  Post ID.
    286                          * @param int    $user_id  User ID.
    287                          * @param string $cap      Capability name.
    288                          * @param array  $caps     User capabilities.
    289                          */
    290                         $allowed = apply_filters( "auth_post_{$post_type}_meta_{$meta_key}", $allowed, $meta_key, $post->ID, $user_id, $cap, $caps );
    291 
    292                         if ( ! $allowed )
     312                        if ( ! $allowed ) {
    293313                                $caps[] = $cap;
    294                 } elseif ( $meta_key && is_protected_meta( $meta_key, 'post' ) ) {
     314                        }
     315                } elseif ( $meta_key && is_protected_meta( $meta_key, $object_type ) ) {
    295316                        $caps[] = $cap;
    296317                }
    297318                break;
  • src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
    index e6f7920..255667e 100644
    a b class WP_REST_Comments_Controller extends WP_REST_Controller { 
    631631                        if ( ! $change ) {
    632632                                return new WP_Error( 'rest_comment_failed_edit', __( 'Updating comment status failed.' ), array( 'status' => 500 ) );
    633633                        }
    634                 } else {
     634                } elseif ( ! empty( $prepared_args ) ) {
    635635                        if ( is_wp_error( $prepared_args ) ) {
    636636                                return $prepared_args;
    637637                        }
  • src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php

    diff --git a/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php b/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
    index 2c765ca..e48a307 100644
    a b abstract class WP_REST_Meta_Fields { 
    122122         */
    123123        public function update_value( $request, $object_id ) {
    124124                $fields = $this->get_registered_fields();
    125 
    126125                foreach ( $fields as $name => $args ) {
    127126                        if ( ! array_key_exists( $name, $request ) ) {
    128127                                continue;
    abstract class WP_REST_Meta_Fields { 
    159158         * @return bool|WP_Error True if meta field is deleted, WP_Error otherwise.
    160159         */
    161160        protected function delete_meta_value( $object_id, $name ) {
    162                 if ( ! current_user_can( 'delete_post_meta', $object_id, $name ) ) {
     161                $meta_type = $this->get_meta_type();
     162                if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $name ) ) {
    163163                        return new WP_Error(
    164164                                'rest_cannot_delete',
    165165                                sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
    abstract class WP_REST_Meta_Fields { 
    167167                        );
    168168                }
    169169
    170                 if ( ! delete_metadata( $this->get_meta_type(), $object_id, wp_slash( $name ) ) ) {
     170                if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $name ) ) ) {
    171171                        return new WP_Error(
    172172                                'rest_meta_database_error',
    173173                                __( 'Could not delete meta value from database.' ),
    abstract class WP_REST_Meta_Fields { 
    192192         * @return bool|WP_Error True if meta fields are updated, WP_Error otherwise.
    193193         */
    194194        protected function update_multi_meta_value( $object_id, $name, $values ) {
    195                 if ( ! current_user_can( 'edit_post_meta', $object_id, $name ) ) {
     195                $meta_type = $this->get_meta_type();
     196                if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $name ) ) {
    196197                        return new WP_Error(
    197198                                'rest_cannot_update',
    198199                                sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
    abstract class WP_REST_Meta_Fields { 
    200201                        );
    201202                }
    202203
    203                 $current = get_metadata( $this->get_meta_type(), $object_id, $name, false );
     204                $current = get_metadata( $meta_type, $object_id, $name, false );
    204205
    205206                $to_remove = $current;
    206207                $to_add    = $values;
    abstract class WP_REST_Meta_Fields { 
    227228                $to_remove = array_unique( $to_remove );
    228229
    229230                foreach ( $to_remove as $value ) {
    230                         if ( ! delete_metadata( $this->get_meta_type(), $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
     231                        if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
    231232                                return new WP_Error(
    232233                                        'rest_meta_database_error',
    233234                                        __( 'Could not update meta value in database.' ),
    abstract class WP_REST_Meta_Fields { 
    237238                }
    238239
    239240                foreach ( $to_add as $value ) {
    240                         if ( ! add_metadata( $this->get_meta_type(), $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
     241                        if ( ! add_metadata( $meta_type, $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
    241242                                return new WP_Error(
    242243                                        'rest_meta_database_error',
    243244                                        __( 'Could not update meta value in database.' ),
    abstract class WP_REST_Meta_Fields { 
    261262         * @return bool|WP_Error True if the meta field was updated, WP_Error otherwise.
    262263         */
    263264        protected function update_meta_value( $object_id, $name, $value ) {
    264                 if ( ! current_user_can( 'edit_post_meta', $object_id, $name ) ) {
     265                $meta_type = $this->get_meta_type();
     266                if ( ! current_user_can(  "edit_{$meta_type}_meta", $object_id, $name ) ) {
    265267                        return new WP_Error(
    266268                                'rest_cannot_update',
    267269                                sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
    abstract class WP_REST_Meta_Fields { 
    269271                        );
    270272                }
    271273
    272                 $meta_type  = $this->get_meta_type();
    273274                $meta_key   = wp_slash( $name );
    274275                $meta_value = wp_slash( $value );
    275276
  • new file tests/phpunit/tests/comment/capabilities.php

    diff --git a/tests/phpunit/tests/comment/capabilities.php b/tests/phpunit/tests/comment/capabilities.php
    new file mode 100644
    index 0000000..7d82b18
    - +  
     1<?php
     2
     3/**
     4 * @group comment
     5 * @group capabilities
     6 */
     7
     8class Tests_Comment_Capabilities extends WP_UnitTestCase {
     9        protected static $admin;
     10        protected static $u1;
     11        protected static $u2;
     12        protected static $post_id;
     13        protected static $comment_id;
     14
     15        public static function wpSetUpBeforeClass( $factory ) {
     16                self::$admin = $factory->user->create( array( 'role' => 'administrator' ) );
     17                self::$u1 = $factory->user->create( array( 'role' => 'author' ) );
     18                self::$u2 = $factory->user->create( array( 'role' => 'author' ) );
     19
     20                self::$post_id = $factory->post->create( array( 'post_author' => self::$u1 ) );
     21                self::$comment_id = $factory->comment->create( array( 'comment_post_ID' => self::$post_id ) );
     22        }
     23
     24        public static function wpTearDownAfterClass() {
     25                self::delete_user( self::$u1 );
     26                self::delete_user( self::$u2 );
     27                self::delete_user( self::$admin );
     28
     29                wp_delete_post( self::$post_id, true );
     30                wp_delete_comment( self::$comment_id, true );
     31        }
     32
     33        public function test_no_one_can_edit_comment_meta_for_non_existent_comment() {
     34                wp_set_current_user( self::$admin );
     35                $this->assertFalse( current_user_can( 'edit_comment_meta', 999999, 'foo' ) );
     36        }
     37
     38        public function test_user_can_edit_comment_meta() {
     39                wp_set_current_user( self::$u1 );
     40                $this->assertTrue( current_user_can( 'edit_comment_meta', self::$comment_id, 'foo' ) );
     41        }
     42
     43        public function test_user_cannot_edit_comment_meta() {
     44                wp_set_current_user( self::$u2 );
     45                $this->assertFalse( current_user_can( 'edit_comment_meta', self::$comment_id, 'foo' ) );
     46        }
     47
     48        public function test_no_one_can_delete_comment_meta_for_non_existent_comment() {
     49                wp_set_current_user( self::$admin );
     50                $this->assertFalse( current_user_can( 'delete_comment_meta', 999999, 'foo' ) );
     51        }
     52
     53        public function test_user_can_delete_comment_meta() {
     54                wp_set_current_user( self::$u1 );
     55                $this->assertTrue( current_user_can( 'delete_comment_meta', self::$comment_id, 'foo' ) );
     56        }
     57
     58        public function test_user_cannot_delete_comment_meta() {
     59                wp_set_current_user( self::$u2 );
     60                $this->assertFalse( current_user_can( 'delete_comment_meta', self::$comment_id, 'foo' ) );
     61        }
     62
     63        public function test_no_one_can_add_comment_meta_for_non_existent_comment() {
     64                wp_set_current_user( self::$admin );
     65                $this->assertFalse( current_user_can( 'add_comment_meta', 999999, 'foo' ) );
     66        }
     67
     68        public function test_user_can_add_comment_meta() {
     69                wp_set_current_user( self::$u1 );
     70                $this->assertTrue( current_user_can( 'add_comment_meta', self::$comment_id, 'foo' ) );
     71        }
     72
     73        public function test_user_cannot_add_comment_meta() {
     74                wp_set_current_user( self::$u2 );
     75                $this->assertFalse( current_user_can( 'add_comment_meta', self::$comment_id, 'foo' ) );
     76        }
     77}
  • new file tests/phpunit/tests/post/capabilities.php

    diff --git a/tests/phpunit/tests/post/capabilities.php b/tests/phpunit/tests/post/capabilities.php
    new file mode 100644
    index 0000000..9e6503e
    - +  
     1<?php
     2
     3/**
     4 * @group post
     5 * @group capabilities
     6 */
     7
     8class Tests_Post_Capabilities extends WP_UnitTestCase {
     9        protected static $admin;
     10        protected static $u1;
     11        protected static $u2;
     12        protected static $post_id;
     13
     14        public static function wpSetUpBeforeClass( $factory ) {
     15                self::$admin = $factory->user->create( array( 'role' => 'administrator' ) );
     16                self::$u1 = $factory->user->create( array( 'role' => 'author' ) );
     17                self::$u2 = $factory->user->create( array( 'role' => 'author' ) );
     18
     19                self::$post_id = $factory->post->create( array( 'post_author' => self::$u1 ) );
     20        }
     21
     22        public static function wpTearDownAfterClass() {
     23                self::delete_user( self::$u1 );
     24                self::delete_user( self::$u2 );
     25                self::delete_user( self::$admin );
     26
     27                wp_delete_post( self::$post_id, true );
     28        }
     29
     30        public function test_no_one_can_edit_post_meta_for_non_existent_post() {
     31                wp_set_current_user( self::$admin );
     32                $this->assertFalse( current_user_can( 'edit_post_meta', 999999, 'foo' ) );
     33        }
     34
     35        public function test_user_can_edit_post_meta() {
     36                wp_set_current_user( self::$u1 );
     37                $this->assertTrue( current_user_can( 'edit_post_meta', self::$post_id, 'foo' ) );
     38        }
     39
     40        public function test_user_cannot_edit_post_meta() {
     41                wp_set_current_user( self::$u2 );
     42                $this->assertFalse( current_user_can( 'edit_post_meta', self::$post_id, 'foo' ) );
     43        }
     44
     45        public function test_no_one_can_delete_post_meta_for_non_existent_post() {
     46                wp_set_current_user( self::$admin );
     47                $this->assertFalse( current_user_can( 'delete_post_meta', 999999, 'foo' ) );
     48        }
     49
     50        public function test_user_can_delete_post_meta() {
     51                wp_set_current_user( self::$u1 );
     52                $this->assertTrue( current_user_can( 'delete_post_meta', self::$post_id, 'foo' ) );
     53        }
     54
     55        public function test_user_cannot_delete_post_meta() {
     56                wp_set_current_user( self::$u2 );
     57                $this->assertFalse( current_user_can( 'delete_post_meta', self::$post_id, 'foo' ) );
     58        }
     59
     60        public function test_no_one_can_add_post_meta_for_non_existent_post() {
     61                wp_set_current_user( self::$admin );
     62                $this->assertFalse( current_user_can( 'add_post_meta', 999999, 'foo' ) );
     63        }
     64
     65        public function test_user_can_add_post_meta() {
     66                wp_set_current_user( self::$u1 );
     67                $this->assertTrue( current_user_can( 'add_post_meta', self::$post_id, 'foo' ) );
     68        }
     69
     70        public function test_user_cannot_add_post_meta() {
     71                wp_set_current_user( self::$u2 );
     72                $this->assertFalse( current_user_can( 'add_post_meta', self::$post_id, 'foo' ) );
     73        }
     74}
  • new file tests/phpunit/tests/rest-api/rest-comment-meta-fields.php

    diff --git a/tests/phpunit/tests/rest-api/rest-comment-meta-fields.php b/tests/phpunit/tests/rest-api/rest-comment-meta-fields.php
    new file mode 100644
    index 0000000..c7ec51c
    - +  
     1<?php
     2/**
     3 * Unit tests covering WP_REST_Posts meta functionality.
     4 *
     5 * @package WordPress
     6 * @subpackage REST API
     7 */
     8
     9 /**
     10  * @group restapi
     11  */
     12class WP_Test_REST_Comment_Meta_Fields extends WP_Test_REST_TestCase {
     13        protected static $editor_id;
     14        protected static $post_id;
     15        protected static $comment_id;
     16
     17        public static function wpSetUpBeforeClass( $factory ) {
     18                // Ensure we have write permission.
     19                self::$editor_id = $factory->user->create( array(
     20                        'role' => 'editor',
     21                ) );
     22                self::$post_id = $factory->post->create();
     23                self::$comment_id = $factory->comment->create_post_comments( self::$post_id, 1 )[0];
     24        }
     25
     26        public static function wpTearDownAfterClass() {
     27                wp_delete_comment( self::$comment_id );
     28                wp_delete_post( self::$post_id );
     29        }
     30
     31        public function setUp() {
     32                parent::setUp();
     33
     34                register_meta( 'comment', 'test_single', array(
     35                        'show_in_rest' => true,
     36                        'single' => true,
     37                ));
     38                register_meta( 'comment', 'test_multi', array(
     39                        'show_in_rest' => true,
     40                        'single' => false,
     41                ));
     42                register_meta( 'comment', 'test_bad_auth', array(
     43                        'show_in_rest' => true,
     44                        'single' => true,
     45                        'auth_callback' => '__return_false',
     46                ));
     47                register_meta( 'comment', 'test_bad_auth_multi', array(
     48                        'show_in_rest' => true,
     49                        'single' => false,
     50                        'auth_callback' => '__return_false',
     51                ));
     52                register_meta( 'comment', 'test_no_rest', array() );
     53                register_meta( 'comment', 'test_rest_disabled', array(
     54                        'show_in_rest' => false,
     55                ));
     56                register_meta( 'comment', 'test_custom_schema', array(
     57                        'single' => true,
     58                        'type' => 'integer',
     59                        'show_in_rest' => array(
     60                                'schema' => array(
     61                                        'type' => 'number',
     62                                ),
     63                        ),
     64                ));
     65                register_meta( 'comment', 'test_invalid_type', array(
     66                        'single' => true,
     67                        'type' => false,
     68                        'show_in_rest' => true,
     69                ));
     70
     71                /** @var WP_REST_Server $wp_rest_server */
     72                global $wp_rest_server;
     73                $this->server = $wp_rest_server = new Spy_REST_Server;
     74                do_action( 'rest_api_init' );
     75        }
     76
     77        public function test_get_value() {
     78                add_comment_meta( self::$comment_id, 'test_single', 'testvalue' );
     79
     80                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     81                $response = $this->server->dispatch( $request );
     82
     83                $this->assertEquals( 200, $response->get_status() );
     84
     85                $data = $response->get_data();
     86                $this->assertArrayHasKey( 'meta', $data );
     87
     88                $meta = (array) $data['meta'];
     89                $this->assertArrayHasKey( 'test_single', $meta );
     90                $this->assertEquals( 'testvalue', $meta['test_single'] );
     91        }
     92
     93        /**
     94         * @depends test_get_value
     95         */
     96        public function test_get_multi_value() {
     97                add_comment_meta( self::$comment_id, 'test_multi', 'value1' );
     98                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     99
     100                $response = $this->server->dispatch( $request );
     101                $this->assertEquals( 200, $response->get_status() );
     102
     103                $data = $response->get_data();
     104                $meta = (array) $data['meta'];
     105                $this->assertArrayHasKey( 'test_multi', $meta );
     106                $this->assertInternalType( 'array', $meta['test_multi'] );
     107                $this->assertContains( 'value1', $meta['test_multi'] );
     108
     109                // Check after an update.
     110                add_comment_meta( self::$comment_id, 'test_multi', 'value2' );
     111
     112                $response = $this->server->dispatch( $request );
     113                $this->assertEquals( 200, $response->get_status() );
     114                $data = $response->get_data();
     115                $meta = (array) $data['meta'];
     116                $this->assertContains( 'value1', $meta['test_multi'] );
     117                $this->assertContains( 'value2', $meta['test_multi'] );
     118        }
     119
     120        /**
     121         * @depends test_get_value
     122         */
     123        public function test_get_unregistered() {
     124                add_comment_meta( self::$comment_id, 'test_unregistered', 'value1' );
     125                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     126
     127                $response = $this->server->dispatch( $request );
     128                $this->assertEquals( 200, $response->get_status() );
     129
     130                $data = $response->get_data();
     131                $meta = (array) $data['meta'];
     132                $this->assertArrayNotHasKey( 'test_unregistered', $meta );
     133        }
     134
     135        /**
     136         * @depends test_get_value
     137         */
     138        public function test_get_registered_no_api_access() {
     139                add_comment_meta( self::$comment_id, 'test_no_rest', 'for_the_wicked' );
     140                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     141
     142                $response = $this->server->dispatch( $request );
     143                $this->assertEquals( 200, $response->get_status() );
     144
     145                $data = $response->get_data();
     146                $meta = (array) $data['meta'];
     147                $this->assertArrayNotHasKey( 'test_no_rest', $meta );
     148        }
     149
     150        /**
     151         * @depends test_get_value
     152         */
     153        public function test_get_registered_api_disabled() {
     154                add_comment_meta( self::$comment_id, 'test_rest_disabled', 'sleepless_nights' );
     155                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     156
     157                $response = $this->server->dispatch( $request );
     158                $this->assertEquals( 200, $response->get_status() );
     159
     160                $data = $response->get_data();
     161                $meta = (array) $data['meta'];
     162                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta );
     163        }
     164
     165        public function test_get_value_types() {
     166                register_meta( 'comment', 'test_string', array(
     167                        'show_in_rest' => true,
     168                        'single' => true,
     169                        'type' => 'string',
     170                ));
     171                register_meta( 'comment', 'test_number', array(
     172                        'show_in_rest' => true,
     173                        'single' => true,
     174                        'type' => 'number',
     175                ));
     176                register_meta( 'comment', 'test_bool', array(
     177                        'show_in_rest' => true,
     178                        'single' => true,
     179                        'type' => 'boolean',
     180                ));
     181
     182                /** @var WP_REST_Server $wp_rest_server */
     183                global $wp_rest_server;
     184                $this->server = $wp_rest_server = new Spy_REST_Server;
     185                do_action( 'rest_api_init' );
     186
     187                add_comment_meta( self::$comment_id, 'test_string', 42 );
     188                add_comment_meta( self::$comment_id, 'test_number', '42' );
     189                add_comment_meta( self::$comment_id, 'test_bool', 1 );
     190
     191                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     192                $response = $this->server->dispatch( $request );
     193                $this->assertEquals( 200, $response->get_status() );
     194
     195                $data = $response->get_data();
     196                $meta = (array) $data['meta'];
     197
     198                $this->assertArrayHasKey( 'test_string', $meta );
     199                $this->assertInternalType( 'string', $meta['test_string'] );
     200                $this->assertSame( '42', $meta['test_string'] );
     201
     202                $this->assertArrayHasKey( 'test_number', $meta );
     203                $this->assertInternalType( 'float', $meta['test_number'] );
     204                $this->assertSame( 42.0, $meta['test_number'] );
     205
     206                $this->assertArrayHasKey( 'test_bool', $meta );
     207                $this->assertInternalType( 'boolean', $meta['test_bool'] );
     208                $this->assertSame( true, $meta['test_bool'] );
     209        }
     210
     211        /**
     212         * @depends test_get_value
     213         */
     214        public function test_set_value() {
     215                // Ensure no data exists currently.
     216                $values = get_comment_meta( self::$comment_id, 'test_single', false );
     217                $this->assertEmpty( $values );
     218
     219                wp_set_current_user( self::$editor_id );
     220
     221                $data = array(
     222                        'meta' => array(
     223                                'test_single' => 'test_value',
     224                        ),
     225                );
     226                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     227                $request->set_body_params( $data );
     228
     229                $response = $this->server->dispatch( $request );
     230                $this->assertEquals( 200, $response->get_status() );
     231
     232                $meta = get_comment_meta( self::$comment_id, 'test_single', false );
     233                $this->assertNotEmpty( $meta );
     234                $this->assertCount( 1, $meta );
     235                $this->assertEquals( 'test_value', $meta[0] );
     236
     237                $data = $response->get_data();
     238                $meta = (array) $data['meta'];
     239                $this->assertArrayHasKey( 'test_single', $meta );
     240                $this->assertEquals( 'test_value', $meta['test_single'] );
     241        }
     242
     243        /**
     244         * @depends test_get_value
     245         */
     246        public function test_set_duplicate_single_value() {
     247                // Start with an existing metakey and value.
     248                $values = update_comment_meta( self::$comment_id, 'test_single', 'test_value' );
     249                $this->assertEquals( 'test_value', get_comment_meta( self::$comment_id, 'test_single', true ) );
     250
     251                wp_set_current_user( self::$editor_id );
     252
     253                $data = array(
     254                        'meta' => array(
     255                                'test_single' => 'test_value',
     256                        ),
     257                );
     258                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     259                $request->set_body_params( $data );
     260
     261                $response = $this->server->dispatch( $request );
     262                $this->assertEquals( 200, $response->get_status() );
     263
     264                $meta = get_comment_meta( self::$comment_id, 'test_single', true );
     265                $this->assertNotEmpty( $meta );
     266                $this->assertEquals( 'test_value', $meta );
     267
     268                $data = $response->get_data();
     269                $meta = (array) $data['meta'];
     270                $this->assertArrayHasKey( 'test_single', $meta );
     271                $this->assertEquals( 'test_value', $meta['test_single'] );
     272        }
     273
     274        /**
     275         * @depends test_set_value
     276         */
     277        public function test_set_value_unauthenticated() {
     278                $data = array(
     279                        'meta' => array(
     280                                'test_single' => 'test_value',
     281                        ),
     282                );
     283
     284                wp_set_current_user( 0 );
     285
     286                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     287                $request->set_body_params( $data );
     288
     289                $response = $this->server->dispatch( $request );
     290                $this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
     291
     292                // Check that the value wasn't actually updated.
     293                $this->assertEmpty( get_comment_meta( self::$comment_id, 'test_single', false ) );
     294        }
     295
     296        /**
     297         * @depends test_set_value
     298         */
     299        public function test_set_value_blocked() {
     300                $data = array(
     301                        'meta' => array(
     302                                'test_bad_auth' => 'test_value',
     303                        ),
     304                );
     305
     306                wp_set_current_user( self::$editor_id );
     307
     308                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     309                $request->set_body_params( $data );
     310
     311                $response = $this->server->dispatch( $request );
     312                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     313                $this->assertEmpty( get_comment_meta( self::$comment_id, 'test_bad_auth', false ) );
     314        }
     315
     316        /**
     317         * @depends test_set_value
     318         */
     319        public function test_set_value_db_error() {
     320                $data = array(
     321                        'meta' => array(
     322                                'test_single' => 'test_value',
     323                        ),
     324                );
     325
     326                wp_set_current_user( self::$editor_id );
     327
     328                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     329                $request->set_body_params( $data );
     330
     331                /**
     332                 * Disable showing error as the below is going to intentionally
     333                 * trigger a DB error.
     334                 */
     335                global $wpdb;
     336                $wpdb->suppress_errors = true;
     337                add_filter( 'query', array( $this, 'error_insert_query' ) );
     338
     339                $response = $this->server->dispatch( $request );
     340                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     341                $wpdb->show_errors = true;
     342        }
     343
     344        public function test_set_value_multiple() {
     345                // Ensure no data exists currently.
     346                $values = get_comment_meta( self::$comment_id, 'test_multi', false );
     347                $this->assertEmpty( $values );
     348
     349                wp_set_current_user( self::$editor_id );
     350
     351                $data = array(
     352                        'meta' => array(
     353                                'test_multi' => array( 'val1' ),
     354                        ),
     355                );
     356                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     357                $request->set_body_params( $data );
     358
     359                $response = $this->server->dispatch( $request );
     360                $this->assertEquals( 200, $response->get_status() );
     361
     362                $meta = get_comment_meta( self::$comment_id, 'test_multi', false );
     363                $this->assertNotEmpty( $meta );
     364                $this->assertCount( 1, $meta );
     365                $this->assertEquals( 'val1', $meta[0] );
     366
     367                // Add another value.
     368                $data = array(
     369                        'meta' => array(
     370                                'test_multi' => array( 'val1', 'val2' ),
     371                        ),
     372                );
     373                $request->set_body_params( $data );
     374
     375                $response = $this->server->dispatch( $request );
     376                $this->assertEquals( 200, $response->get_status() );
     377
     378                $meta = get_comment_meta( self::$comment_id, 'test_multi', false );
     379                $this->assertNotEmpty( $meta );
     380                $this->assertCount( 2, $meta );
     381                $this->assertContains( 'val1', $meta );
     382                $this->assertContains( 'val2', $meta );
     383        }
     384
     385        /**
     386         * Test removing only one item with duplicate items.
     387         */
     388        public function test_set_value_remove_one() {
     389                add_comment_meta( self::$comment_id, 'test_multi', 'c' );
     390                add_comment_meta( self::$comment_id, 'test_multi', 'n' );
     391                add_comment_meta( self::$comment_id, 'test_multi', 'n' );
     392
     393                wp_set_current_user( self::$editor_id );
     394
     395                $data = array(
     396                        'meta' => array(
     397                                'test_multi' => array( 'c', 'n' ),
     398                        ),
     399                );
     400                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     401                $request->set_body_params( $data );
     402
     403                $response = $this->server->dispatch( $request );
     404                $this->assertEquals( 200, $response->get_status() );
     405
     406                $meta = get_comment_meta( self::$comment_id, 'test_multi', false );
     407                $this->assertNotEmpty( $meta );
     408                $this->assertCount( 2, $meta );
     409                $this->assertContains( 'c', $meta );
     410                $this->assertContains( 'n', $meta );
     411        }
     412
     413        /**
     414         * @depends test_set_value_multiple
     415         */
     416        public function test_set_value_multiple_unauthenticated() {
     417                // Ensure no data exists currently.
     418                $values = get_comment_meta( self::$comment_id, 'test_multi', false );
     419                $this->assertEmpty( $values );
     420
     421                wp_set_current_user( 0 );
     422
     423                $data = array(
     424                        'meta' => array(
     425                                'test_multi' => array( 'val1' ),
     426                        ),
     427                );
     428                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     429                $request->set_body_params( $data );
     430
     431                $response = $this->server->dispatch( $request );
     432                $this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
     433
     434                $meta = get_comment_meta( self::$comment_id, 'test_multi', false );
     435                $this->assertEmpty( $meta );
     436        }
     437
     438        /**
     439         * @depends test_set_value_multiple
     440         */
     441        public function test_set_value_multiple_blocked() {
     442                $data = array(
     443                        'meta' => array(
     444                                'test_bad_auth_multi' => array( 'test_value' ),
     445                        ),
     446                );
     447
     448                wp_set_current_user( self::$editor_id );
     449
     450                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     451                $request->set_body_params( $data );
     452
     453                $response = $this->server->dispatch( $request );
     454                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     455                $this->assertEmpty( get_comment_meta( self::$comment_id, 'test_bad_auth_multi', false ) );
     456        }
     457
     458        public function test_add_multi_value_db_error() {
     459                // Ensure no data exists currently.
     460                $values = get_comment_meta( self::$comment_id, 'test_multi', false );
     461                $this->assertEmpty( $values );
     462
     463                wp_set_current_user( self::$editor_id );
     464
     465                $data = array(
     466                        'meta' => array(
     467                                'test_multi' => array( 'val1' ),
     468                        ),
     469                );
     470                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     471                $request->set_body_params( $data );
     472
     473                /**
     474                 * Disable showing error as the below is going to intentionally
     475                 * trigger a DB error.
     476                 */
     477                global $wpdb;
     478                $wpdb->suppress_errors = true;
     479                add_filter( 'query', array( $this, 'error_insert_query' ) );
     480
     481                $response = $this->server->dispatch( $request );
     482                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     483                $wpdb->show_errors = true;
     484
     485                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     486        }
     487
     488        public function test_remove_multi_value_db_error() {
     489                add_comment_meta( self::$comment_id, 'test_multi', 'val1' );
     490                $values = get_comment_meta( self::$comment_id, 'test_multi', false );
     491                $this->assertEquals( array( 'val1' ), $values );
     492
     493                wp_set_current_user( self::$editor_id );
     494
     495                $data = array(
     496                        'meta' => array(
     497                                'test_multi' => array(),
     498                        ),
     499                );
     500                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     501                $request->set_body_params( $data );
     502
     503                /**
     504                 * Disable showing error as the below is going to intentionally
     505                 * trigger a DB error.
     506                 */
     507                global $wpdb;
     508                $wpdb->suppress_errors = true;
     509                add_filter( 'query', array( $this, 'error_delete_query' ) );
     510
     511                $response = $this->server->dispatch( $request );
     512                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     513                $wpdb->show_errors = true;
     514
     515                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     516        }
     517
     518        public function test_delete_value() {
     519                add_comment_meta( self::$comment_id, 'test_single', 'val1' );
     520                $current = get_comment_meta( self::$comment_id, 'test_single', true );
     521                $this->assertEquals( 'val1', $current );
     522
     523                wp_set_current_user( self::$editor_id );
     524
     525                $data = array(
     526                        'meta' => array(
     527                                'test_single' => null,
     528                        ),
     529                );
     530                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     531                $request->set_body_params( $data );
     532
     533                $response = $this->server->dispatch( $request );
     534                $this->assertEquals( 200, $response->get_status() );
     535
     536                $meta = get_comment_meta( self::$comment_id, 'test_single', false );
     537                $this->assertEmpty( $meta );
     538        }
     539
     540        /**
     541         * @depends test_delete_value
     542         */
     543        public function test_delete_value_blocked() {
     544                add_comment_meta( self::$comment_id, 'test_bad_auth', 'val1' );
     545                $current = get_comment_meta( self::$comment_id, 'test_bad_auth', true );
     546                $this->assertEquals( 'val1', $current );
     547
     548                wp_set_current_user( self::$editor_id );
     549
     550                $data = array(
     551                        'meta' => array(
     552                                'test_bad_auth' => null,
     553                        ),
     554                );
     555                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     556                $request->set_body_params( $data );
     557
     558                $response = $this->server->dispatch( $request );
     559                $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
     560
     561                $meta = get_comment_meta( self::$comment_id, 'test_bad_auth', true );
     562                $this->assertEquals( 'val1', $meta );
     563        }
     564
     565        /**
     566         * @depends test_delete_value
     567         */
     568        public function test_delete_value_db_error() {
     569                add_comment_meta( self::$comment_id, 'test_single', 'val1' );
     570                $current = get_comment_meta( self::$comment_id, 'test_single', true );
     571                $this->assertEquals( 'val1', $current );
     572
     573                wp_set_current_user( self::$editor_id );
     574
     575                $data = array(
     576                        'meta' => array(
     577                                'test_single' => null,
     578                        ),
     579                );
     580                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     581                $request->set_body_params( $data );
     582                /**
     583                 * Disable showing error as the below is going to intentionally
     584                 * trigger a DB error.
     585                 */
     586                global $wpdb;
     587                $wpdb->suppress_errors = true;
     588                add_filter( 'query', array( $this, 'error_delete_query' ) );
     589
     590                $response = $this->server->dispatch( $request );
     591                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     592                $wpdb->show_errors = true;
     593
     594                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     595        }
     596
     597        public function test_get_schema() {
     598                $request = new WP_REST_Request( 'OPTIONS', sprintf( '/wp/v2/comments/%d', self::$comment_id ) );
     599                $response = $this->server->dispatch( $request );
     600
     601                $data = $response->get_data();
     602                $schema = $data['schema'];
     603
     604                $this->assertArrayHasKey( 'meta', $schema['properties'] );
     605                $meta_schema = $schema['properties']['meta']['properties'];
     606
     607                $this->assertArrayHasKey( 'test_single', $meta_schema );
     608                $this->assertEquals( 'string', $meta_schema['test_single']['type'] );
     609
     610                $this->assertArrayHasKey( 'test_multi', $meta_schema );
     611                $this->assertEquals( 'array', $meta_schema['test_multi']['type'] );
     612                $this->assertArrayHasKey( 'items', $meta_schema['test_multi'] );
     613                $this->assertEquals( 'string', $meta_schema['test_multi']['items']['type'] );
     614
     615                $this->assertArrayHasKey( 'test_custom_schema', $meta_schema );
     616                $this->assertEquals( 'number', $meta_schema['test_custom_schema']['type'] );
     617
     618                $this->assertArrayNotHasKey( 'test_no_rest', $meta_schema );
     619                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta_schema );
     620                $this->assertArrayNotHasKey( 'test_invalid_type', $meta_schema );
     621        }
     622
     623        /**
     624         * Internal function used to disable an insert query which
     625         * will trigger a wpdb error for testing purposes.
     626         */
     627        public function error_insert_query( $query ) {
     628                if ( strpos( $query, 'INSERT' ) === 0 ) {
     629                        $query = '],';
     630                }
     631                return $query;
     632        }
     633
     634        /**
     635         * Internal function used to disable an insert query which
     636         * will trigger a wpdb error for testing purposes.
     637         */
     638        public function error_delete_query( $query ) {
     639                if ( strpos( $query, 'DELETE' ) === 0 ) {
     640                        $query = '],';
     641                }
     642                return $query;
     643        }
     644}
  • new file tests/phpunit/tests/rest-api/rest-term-meta-fields.php

    diff --git a/tests/phpunit/tests/rest-api/rest-term-meta-fields.php b/tests/phpunit/tests/rest-api/rest-term-meta-fields.php
    new file mode 100644
    index 0000000..bfc3418
    - +  
     1<?php
     2/**
     3 * Unit tests covering WP_REST_Taxonomies terms meta functionality.
     4 *
     5 * @package WordPress
     6 * @subpackage REST API
     7 */
     8
     9 /**
     10  * @group restapi
     11  */
     12class WP_Test_REST_Term_Meta_Fields extends WP_Test_REST_TestCase {
     13        protected static $administrator_id;
     14        protected static $term_id;
     15
     16        public static function wpSetUpBeforeClass( $factory ) {
     17                self::$administrator_id = $factory->user->create( array(
     18                        'role' => 'administrator',
     19                ) );
     20
     21                register_taxonomy( 'wptests_tax', 'post', array( 'show_in_rest' => true ) );
     22                self::$term_id = $factory->term->create( array( 'taxonomy' => 'wptests_tax' ) );
     23        }
     24
     25        public function setUp() {
     26                parent::setUp();
     27
     28                register_meta( 'term', 'test_single', array(
     29                        'show_in_rest' => true,
     30                        'single' => true,
     31                ) );
     32                register_meta( 'term', 'test_multi', array(
     33                        'show_in_rest' => true,
     34                        'single' => false,
     35                ) );
     36                register_meta( 'term', 'test_bad_auth', array(
     37                        'show_in_rest' => true,
     38                        'single' => true,
     39                        'auth_callback' => '__return_false',
     40                ) );
     41                register_meta( 'term', 'test_bad_auth_multi', array(
     42                        'show_in_rest' => true,
     43                        'single' => false,
     44                        'auth_callback' => '__return_false',
     45                ) );
     46                register_meta( 'term', 'test_no_rest', array() );
     47                register_meta( 'term', 'test_rest_disabled', array(
     48                        'show_in_rest' => false,
     49                ) );
     50                register_meta( 'term', 'test_custom_schema', array(
     51                        'single' => true,
     52                        'type' => 'integer',
     53                        'show_in_rest' => array(
     54                                'schema' => array(
     55                                        'type' => 'number',
     56                                ),
     57                        ),
     58                ) );
     59                register_meta( 'term', 'test_invalid_type', array(
     60                        'single' => true,
     61                        'type' => false,
     62                        'show_in_rest' => true,
     63                ) );
     64
     65                /** @var WP_REST_Server $wp_rest_server */
     66                global $wp_rest_server;
     67                $this->server = $wp_rest_server = new Spy_REST_Server;
     68                do_action( 'rest_api_init' );
     69
     70                register_taxonomy( 'wptests_tax', 'post', array( 'show_in_rest' => true ) );
     71                $controller = new WP_REST_Terms_Controller( 'wptests_tax' );
     72                $controller->register_routes();
     73        }
     74
     75        public function test_get_value() {
     76                add_term_meta( self::$term_id, 'test_single', 'testvalue' );
     77                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     78
     79                $response = $this->server->dispatch( $request );
     80
     81                $this->assertEquals( 200, $response->get_status() );
     82
     83                $data = $response->get_data();
     84                $this->assertArrayHasKey( 'meta', $data );
     85
     86                $meta = (array) $data['meta'];
     87                $this->assertArrayHasKey( 'test_single', $meta );
     88                $this->assertEquals( 'testvalue', $meta['test_single'] );
     89        }
     90
     91        /**
     92         * @depends test_get_value
     93         */
     94        public function test_get_multi_value() {
     95                add_term_meta( self::$term_id, 'test_multi', 'value1' );
     96                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     97
     98                $response = $this->server->dispatch( $request );
     99                $this->assertEquals( 200, $response->get_status() );
     100
     101                $data = $response->get_data();
     102                $meta = (array) $data['meta'];
     103                $this->assertArrayHasKey( 'test_multi', $meta );
     104                $this->assertInternalType( 'array', $meta['test_multi'] );
     105                $this->assertContains( 'value1', $meta['test_multi'] );
     106
     107                // Check after an update.
     108                add_term_meta( self::$term_id, 'test_multi', 'value2' );
     109
     110                $response = $this->server->dispatch( $request );
     111                $this->assertEquals( 200, $response->get_status() );
     112                $data = $response->get_data();
     113                $meta = (array) $data['meta'];
     114                $this->assertContains( 'value1', $meta['test_multi'] );
     115                $this->assertContains( 'value2', $meta['test_multi'] );
     116        }
     117
     118        /**
     119         * @depends test_get_value
     120         */
     121        public function test_get_unregistered() {
     122                add_term_meta( self::$term_id, 'test_unregistered', 'value1' );
     123                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     124
     125                $response = $this->server->dispatch( $request );
     126                $this->assertEquals( 200, $response->get_status() );
     127
     128                $data = $response->get_data();
     129                $meta = (array) $data['meta'];
     130                $this->assertArrayNotHasKey( 'test_unregistered', $meta );
     131        }
     132
     133        /**
     134         * @depends test_get_value
     135         */
     136        public function test_get_registered_no_api_access() {
     137                add_term_meta( self::$term_id, 'test_no_rest', 'for_the_wicked' );
     138                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     139
     140                $response = $this->server->dispatch( $request );
     141                $this->assertEquals( 200, $response->get_status() );
     142
     143                $data = $response->get_data();
     144                $meta = (array) $data['meta'];
     145                $this->assertArrayNotHasKey( 'test_no_rest', $meta );
     146        }
     147
     148        /**
     149         * @depends test_get_value
     150         */
     151        public function test_get_registered_api_disabled() {
     152                add_term_meta( self::$term_id, 'test_rest_disabled', 'sleepless_nights' );
     153                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     154
     155                $response = $this->server->dispatch( $request );
     156                $this->assertEquals( 200, $response->get_status() );
     157
     158                $data = $response->get_data();
     159                $meta = (array) $data['meta'];
     160                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta );
     161        }
     162
     163        public function test_get_value_types() {
     164                register_meta( 'term', 'test_string', array(
     165                        'show_in_rest' => true,
     166                        'single' => true,
     167                        'type' => 'string',
     168                ));
     169                register_meta( 'term', 'test_number', array(
     170                        'show_in_rest' => true,
     171                        'single' => true,
     172                        'type' => 'number',
     173                ));
     174                register_meta( 'term', 'test_bool', array(
     175                        'show_in_rest' => true,
     176                        'single' => true,
     177                        'type' => 'boolean',
     178                ));
     179
     180                /** @var WP_REST_Server $wp_rest_server */
     181                global $wp_rest_server;
     182                $this->server = $wp_rest_server = new Spy_REST_Server;
     183                do_action( 'rest_api_init' );
     184
     185                add_term_meta( self::$term_id, 'test_string', 42 );
     186                add_term_meta( self::$term_id, 'test_number', '42' );
     187                add_term_meta( self::$term_id, 'test_bool', 1 );
     188
     189                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     190                $response = $this->server->dispatch( $request );
     191                $this->assertEquals( 200, $response->get_status() );
     192
     193                $data = $response->get_data();
     194                $meta = (array) $data['meta'];
     195
     196                $this->assertArrayHasKey( 'test_string', $meta );
     197                $this->assertInternalType( 'string', $meta['test_string'] );
     198                $this->assertSame( '42', $meta['test_string'] );
     199
     200                $this->assertArrayHasKey( 'test_number', $meta );
     201                $this->assertInternalType( 'float', $meta['test_number'] );
     202                $this->assertSame( 42.0, $meta['test_number'] );
     203
     204                $this->assertArrayHasKey( 'test_bool', $meta );
     205                $this->assertInternalType( 'boolean', $meta['test_bool'] );
     206                $this->assertSame( true, $meta['test_bool'] );
     207        }
     208
     209        /**
     210         * @depends test_get_value
     211         */
     212        public function test_set_value() {
     213                // Ensure no data exists currently.
     214                $values = get_term_meta( self::$term_id, 'test_single', false );
     215                $this->assertEmpty( $values );
     216
     217                wp_set_current_user( self::$administrator_id );
     218
     219                $data = array(
     220                        'meta' => array(
     221                                'test_single' => 'test_value',
     222                        ),
     223                );
     224                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     225                $request->set_body_params( $data );
     226
     227                $response = $this->server->dispatch( $request );
     228                $this->assertEquals( 200, $response->get_status() );
     229
     230                $meta = get_term_meta( self::$term_id, 'test_single', false );
     231                $this->assertNotEmpty( $meta );
     232                $this->assertCount( 1, $meta );
     233                $this->assertEquals( 'test_value', $meta[0] );
     234
     235                $data = $response->get_data();
     236                $meta = (array) $data['meta'];
     237                $this->assertArrayHasKey( 'test_single', $meta );
     238                $this->assertEquals( 'test_value', $meta['test_single'] );
     239        }
     240
     241        /**
     242         * @depends test_get_value
     243         */
     244        public function test_set_duplicate_single_value() {
     245                // Start with an existing metakey and value.
     246                $values = update_term_meta( self::$term_id, 'test_single', 'test_value' );
     247                $this->assertEquals( 'test_value', get_term_meta( self::$term_id, 'test_single', true ) );
     248
     249                wp_set_current_user( self::$administrator_id );
     250
     251                $data = array(
     252                        'meta' => array(
     253                                'test_single' => 'test_value',
     254                        ),
     255                );
     256                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     257                $request->set_body_params( $data );
     258
     259                $response = $this->server->dispatch( $request );
     260                $this->assertEquals( 200, $response->get_status() );
     261
     262                $meta = get_term_meta( self::$term_id, 'test_single', true );
     263                $this->assertNotEmpty( $meta );
     264                $this->assertEquals( 'test_value', $meta );
     265
     266                $data = $response->get_data();
     267                $meta = (array) $data['meta'];
     268                $this->assertArrayHasKey( 'test_single', $meta );
     269                $this->assertEquals( 'test_value', $meta['test_single'] );
     270        }
     271
     272        /**
     273         * @depends test_set_value
     274         */
     275        public function test_set_value_unauthenticated() {
     276                $data = array(
     277                        'meta' => array(
     278                                'test_single' => 'test_value',
     279                        ),
     280                );
     281
     282                wp_set_current_user( 0 );
     283
     284                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     285                $request->set_body_params( $data );
     286
     287                $response = $this->server->dispatch( $request );
     288                $this->assertErrorResponse( 'rest_cannot_update', $response, 401 );
     289
     290                // Check that the value wasn't actually updated.
     291                $this->assertEmpty( get_term_meta( self::$term_id, 'test_single', false ) );
     292        }
     293
     294        /**
     295         * @depends test_set_value
     296         */
     297        public function test_set_value_blocked() {
     298                $data = array(
     299                        'meta' => array(
     300                                'test_bad_auth' => 'test_value',
     301                        ),
     302                );
     303
     304                wp_set_current_user( self::$administrator_id );
     305
     306                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     307                $request->set_body_params( $data );
     308
     309                $response = $this->server->dispatch( $request );
     310                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     311                $this->assertEmpty( get_term_meta( self::$term_id, 'test_bad_auth', false ) );
     312        }
     313
     314        /**
     315         * @depends test_set_value
     316         */
     317        public function test_set_value_db_error() {
     318                $data = array(
     319                        'meta' => array(
     320                                'test_single' => 'test_value',
     321                        ),
     322                );
     323
     324                wp_set_current_user( self::$administrator_id );
     325
     326                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     327                $request->set_body_params( $data );
     328
     329                /**
     330                 * Disable showing error as the below is going to intentionally
     331                 * trigger a DB error.
     332                 */
     333                global $wpdb;
     334                $wpdb->suppress_errors = true;
     335                add_filter( 'query', array( $this, 'error_insert_query' ) );
     336
     337                $response = $this->server->dispatch( $request );
     338                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     339                $wpdb->show_errors = true;
     340        }
     341
     342        public function test_set_value_multiple() {
     343                // Ensure no data exists currently.
     344                $values = get_term_meta( self::$term_id, 'test_multi', false );
     345                $this->assertEmpty( $values );
     346
     347                wp_set_current_user( self::$administrator_id );
     348
     349                $data = array(
     350                        'meta' => array(
     351                                'test_multi' => array( 'val1' ),
     352                        ),
     353                );
     354                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     355                $request->set_body_params( $data );
     356
     357                $response = $this->server->dispatch( $request );
     358                $this->assertEquals( 200, $response->get_status() );
     359
     360                $meta = get_term_meta( self::$term_id, 'test_multi', false );
     361                $this->assertNotEmpty( $meta );
     362                $this->assertCount( 1, $meta );
     363                $this->assertEquals( 'val1', $meta[0] );
     364
     365                // Add another value.
     366                $data = array(
     367                        'meta' => array(
     368                                'test_multi' => array( 'val1', 'val2' ),
     369                        ),
     370                );
     371                $request->set_body_params( $data );
     372
     373                $response = $this->server->dispatch( $request );
     374                $this->assertEquals( 200, $response->get_status() );
     375
     376                $meta = get_term_meta( self::$term_id, 'test_multi', false );
     377                $this->assertNotEmpty( $meta );
     378                $this->assertCount( 2, $meta );
     379                $this->assertContains( 'val1', $meta );
     380                $this->assertContains( 'val2', $meta );
     381        }
     382
     383        /**
     384         * Test removing only one item with duplicate items.
     385         */
     386        public function test_set_value_remove_one() {
     387                add_term_meta( self::$term_id, 'test_multi', 'c' );
     388                add_term_meta( self::$term_id, 'test_multi', 'n' );
     389                add_term_meta( self::$term_id, 'test_multi', 'n' );
     390
     391                wp_set_current_user( self::$administrator_id );
     392
     393                $data = array(
     394                        'meta' => array(
     395                                'test_multi' => array( 'c', 'n' ),
     396                        ),
     397                );
     398                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     399                $request->set_body_params( $data );
     400
     401                $response = $this->server->dispatch( $request );
     402                $this->assertEquals( 200, $response->get_status() );
     403
     404                $meta = get_term_meta( self::$term_id, 'test_multi', false );
     405                $this->assertNotEmpty( $meta );
     406                $this->assertCount( 2, $meta );
     407                $this->assertContains( 'c', $meta );
     408                $this->assertContains( 'n', $meta );
     409        }
     410
     411        /**
     412         * @depends test_set_value_multiple
     413         */
     414        public function test_set_value_multiple_unauthenticated() {
     415                // Ensure no data exists currently.
     416                $values = get_term_meta( self::$term_id, 'test_multi', false );
     417                $this->assertEmpty( $values );
     418
     419                wp_set_current_user( 0 );
     420
     421                $data = array(
     422                        'meta' => array(
     423                                'test_multi' => array( 'val1' ),
     424                        ),
     425                );
     426                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     427                $request->set_body_params( $data );
     428
     429                $response = $this->server->dispatch( $request );
     430                $this->assertErrorResponse( 'rest_cannot_update', $response, 401 );
     431
     432                $meta = get_term_meta( self::$term_id, 'test_multi', false );
     433                $this->assertEmpty( $meta );
     434        }
     435
     436        /**
     437         * @depends test_set_value_multiple
     438         */
     439        public function test_set_value_multiple_blocked() {
     440                $data = array(
     441                        'meta' => array(
     442                                'test_bad_auth_multi' => array( 'test_value' ),
     443                        ),
     444                );
     445
     446                wp_set_current_user( self::$administrator_id );
     447
     448                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     449                $request->set_body_params( $data );
     450
     451                $response = $this->server->dispatch( $request );
     452                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     453                $this->assertEmpty( get_term_meta( self::$term_id, 'test_bad_auth_multi', false ) );
     454        }
     455
     456        public function test_add_multi_value_db_error() {
     457                // Ensure no data exists currently.
     458                $values = get_term_meta( self::$term_id, 'test_multi', false );
     459                $this->assertEmpty( $values );
     460
     461                wp_set_current_user( self::$administrator_id );
     462
     463                $data = array(
     464                        'meta' => array(
     465                                'test_multi' => array( 'val1' ),
     466                        ),
     467                );
     468                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     469                $request->set_body_params( $data );
     470
     471                /**
     472                 * Disable showing error as the below is going to intentionally
     473                 * trigger a DB error.
     474                 */
     475                global $wpdb;
     476                $wpdb->suppress_errors = true;
     477                add_filter( 'query', array( $this, 'error_insert_query' ) );
     478
     479                $response = $this->server->dispatch( $request );
     480                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     481                $wpdb->show_errors = true;
     482
     483                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     484        }
     485
     486        public function test_remove_multi_value_db_error() {
     487                add_term_meta( self::$term_id, 'test_multi', 'val1' );
     488                $values = get_term_meta( self::$term_id, 'test_multi', false );
     489                $this->assertEquals( array( 'val1' ), $values );
     490
     491                wp_set_current_user( self::$administrator_id );
     492
     493                $data = array(
     494                        'meta' => array(
     495                                'test_multi' => array(),
     496                        ),
     497                );
     498                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     499                $request->set_body_params( $data );
     500
     501                /**
     502                 * Disable showing error as the below is going to intentionally
     503                 * trigger a DB error.
     504                 */
     505                global $wpdb;
     506                $wpdb->suppress_errors = true;
     507                add_filter( 'query', array( $this, 'error_delete_query' ) );
     508
     509                $response = $this->server->dispatch( $request );
     510                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     511                $wpdb->show_errors = true;
     512
     513                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     514        }
     515
     516        public function test_delete_value() {
     517                add_term_meta( self::$term_id, 'test_single', 'val1' );
     518                $current = get_term_meta( self::$term_id, 'test_single', true );
     519                $this->assertEquals( 'val1', $current );
     520
     521                wp_set_current_user( self::$administrator_id );
     522
     523                $data = array(
     524                        'meta' => array(
     525                                'test_single' => null,
     526                        ),
     527                );
     528                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     529                $request->set_body_params( $data );
     530
     531                $response = $this->server->dispatch( $request );
     532                $this->assertEquals( 200, $response->get_status() );
     533
     534                $meta = get_term_meta( self::$term_id, 'test_single', false );
     535                $this->assertEmpty( $meta );
     536        }
     537
     538        /**
     539         * @depends test_delete_value
     540         */
     541        public function test_delete_value_blocked() {
     542                add_term_meta( self::$term_id, 'test_bad_auth', 'val1' );
     543                $current = get_term_meta( self::$term_id, 'test_bad_auth', true );
     544                $this->assertEquals( 'val1', $current );
     545
     546                wp_set_current_user( self::$administrator_id );
     547
     548                $data = array(
     549                        'meta' => array(
     550                                'test_bad_auth' => null,
     551                        ),
     552                );
     553                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     554                $request->set_body_params( $data );
     555
     556                $response = $this->server->dispatch( $request );
     557                $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
     558
     559                $meta = get_term_meta( self::$term_id, 'test_bad_auth', true );
     560                $this->assertEquals( 'val1', $meta );
     561        }
     562
     563        /**
     564         * @depends test_delete_value
     565         */
     566        public function test_delete_value_db_error() {
     567                add_term_meta( self::$term_id, 'test_single', 'val1' );
     568                $current = get_term_meta( self::$term_id, 'test_single', true );
     569                $this->assertEquals( 'val1', $current );
     570
     571                wp_set_current_user( self::$administrator_id );
     572
     573                $data = array(
     574                        'meta' => array(
     575                                'test_single' => null,
     576                        ),
     577                );
     578                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     579                $request->set_body_params( $data );
     580                /**
     581                 * Disable showing error as the below is going to intentionally
     582                 * trigger a DB error.
     583                 */
     584                global $wpdb;
     585                $wpdb->suppress_errors = true;
     586                add_filter( 'query', array( $this, 'error_delete_query' ) );
     587
     588                $response = $this->server->dispatch( $request );
     589                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     590                $wpdb->show_errors = true;
     591
     592                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     593        }
     594
     595        public function test_get_schema() {
     596                $request = new WP_REST_Request( 'OPTIONS', sprintf( '/wp/v2/wptests_tax/%d', self::$term_id ) );
     597                $response = $this->server->dispatch( $request );
     598
     599                $data = $response->get_data();
     600                $schema = $data['schema'];
     601
     602                $this->assertArrayHasKey( 'meta', $schema['properties'] );
     603                $meta_schema = $schema['properties']['meta']['properties'];
     604
     605                $this->assertArrayHasKey( 'test_single', $meta_schema );
     606                $this->assertEquals( 'string', $meta_schema['test_single']['type'] );
     607
     608                $this->assertArrayHasKey( 'test_multi', $meta_schema );
     609                $this->assertEquals( 'array', $meta_schema['test_multi']['type'] );
     610                $this->assertArrayHasKey( 'items', $meta_schema['test_multi'] );
     611                $this->assertEquals( 'string', $meta_schema['test_multi']['items']['type'] );
     612
     613                $this->assertArrayHasKey( 'test_custom_schema', $meta_schema );
     614                $this->assertEquals( 'number', $meta_schema['test_custom_schema']['type'] );
     615
     616                $this->assertArrayNotHasKey( 'test_no_rest', $meta_schema );
     617                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta_schema );
     618                $this->assertArrayNotHasKey( 'test_invalid_type', $meta_schema );
     619        }
     620
     621        /**
     622         * Internal function used to disable an insert query which
     623         * will trigger a wpdb error for testing purposes.
     624         */
     625        public function error_insert_query( $query ) {
     626                if ( strpos( $query, 'INSERT' ) === 0 ) {
     627                        $query = '],';
     628                }
     629                return $query;
     630        }
     631
     632        /**
     633         * Internal function used to disable an insert query which
     634         * will trigger a wpdb error for testing purposes.
     635         */
     636        public function error_delete_query( $query ) {
     637                if ( strpos( $query, 'DELETE' ) === 0 ) {
     638                        $query = '],';
     639                }
     640                return $query;
     641        }
     642}
  • new file tests/phpunit/tests/rest-api/rest-user-meta-fields.php

    diff --git a/tests/phpunit/tests/rest-api/rest-user-meta-fields.php b/tests/phpunit/tests/rest-api/rest-user-meta-fields.php
    new file mode 100644
    index 0000000..a52898b
    - +  
     1<?php
     2/**
     3 * Unit tests covering WP_REST_Users meta functionality.
     4 *
     5 * @package WordPress
     6 * @subpackage REST API
     7 */
     8
     9 /**
     10  * @group restapi
     11  */
     12class WP_Test_REST_User_Meta_Fields extends WP_Test_REST_TestCase {
     13        protected static $administrator_id;
     14        protected static $user;
     15
     16        public static function wpSetUpBeforeClass( $factory ) {
     17                self::$administrator_id = $factory->user->create( array(
     18                        'role' => 'administrator',
     19                ) );
     20                self::$user = $factory->user->create( array(
     21                        'role' => 'author',
     22                ) );
     23        }
     24
     25        public static function wpTearDownAfterClass() {
     26                wp_delete_user( self::$administrator_id );
     27                wp_delete_user( self::$user );
     28        }
     29
     30        public function setUp() {
     31                parent::setUp();
     32
     33                // Editing users requires 'manage_network_users' on multisite.
     34                if ( is_multisite() ) {
     35                        add_filter( 'user_has_cap', array( $this, 'grant_manage_network_users_to_admin' ), 10, 4 );
     36                }
     37
     38                register_meta( 'user', 'test_single', array(
     39                        'show_in_rest' => true,
     40                        'single' => true,
     41                ) );
     42                register_meta( 'user', 'test_multi', array(
     43                        'show_in_rest' => true,
     44                        'single' => false,
     45                ) );
     46                register_meta( 'user', 'test_bad_auth', array(
     47                        'show_in_rest' => true,
     48                        'single' => true,
     49                        'auth_callback' => '__return_false',
     50                ) );
     51                register_meta( 'user', 'test_bad_auth_multi', array(
     52                        'show_in_rest' => true,
     53                        'single' => false,
     54                        'auth_callback' => '__return_false',
     55                ) );
     56                register_meta( 'user', 'test_no_rest', array() );
     57                register_meta( 'user', 'test_rest_disabled', array(
     58                        'show_in_rest' => false,
     59                ) );
     60                register_meta( 'user', 'test_custom_schema', array(
     61                        'single' => true,
     62                        'type' => 'integer',
     63                        'show_in_rest' => array(
     64                                'schema' => array(
     65                                        'type' => 'number',
     66                                ),
     67                        ),
     68                ) );
     69                register_meta( 'user', 'test_invalid_type', array(
     70                        'single' => true,
     71                        'type' => false,
     72                        'show_in_rest' => true,
     73                ) );
     74
     75                /** @var WP_REST_Server $wp_rest_server */
     76                global $wp_rest_server;
     77                $this->server = $wp_rest_server = new Spy_REST_Server;
     78                do_action( 'rest_api_init' );
     79        }
     80
     81        public function tearDown() {
     82                if ( is_multisite() ) {
     83                        remove_filter( 'user_has_cap', array( $this, 'grant_manage_network_users_to_admin' ), 10, 4 );
     84                }
     85        }
     86
     87        public function grant_manage_network_users_to_admin( $allcaps, $caps, $args, WP_User $user ) {
     88                if ( array( 'manage_network_users' ) == $caps && self::$administrator_id === $user->ID ) {
     89                        $allcaps['manage_network_users'] = 1;
     90                }
     91
     92                return $allcaps;
     93
     94        }
     95
     96        public function test_get_value() {
     97                add_user_meta( self::$user, 'test_single', 'testvalue' );
     98                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$user ) );
     99
     100                wp_set_current_user( self::$administrator_id );
     101
     102                $response = $this->server->dispatch( $request );
     103
     104                $this->assertEquals( 200, $response->get_status() );
     105
     106                $data = $response->get_data();
     107                $this->assertArrayHasKey( 'meta', $data );
     108
     109                $meta = (array) $data['meta'];
     110                $this->assertArrayHasKey( 'test_single', $meta );
     111                $this->assertEquals( 'testvalue', $meta['test_single'] );
     112        }
     113
     114        /**
     115         * @depends test_get_value
     116         */
     117        public function test_get_multi_value() {
     118                add_user_meta( self::$user, 'test_multi', 'value1' );
     119                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$user ) );
     120
     121                wp_set_current_user( self::$administrator_id );
     122
     123                $response = $this->server->dispatch( $request );
     124                $this->assertEquals( 200, $response->get_status() );
     125
     126                $data = $response->get_data();
     127                $meta = (array) $data['meta'];
     128                $this->assertArrayHasKey( 'test_multi', $meta );
     129                $this->assertInternalType( 'array', $meta['test_multi'] );
     130                $this->assertContains( 'value1', $meta['test_multi'] );
     131
     132                // Check after an update.
     133                add_user_meta( self::$user, 'test_multi', 'value2' );
     134
     135                $response = $this->server->dispatch( $request );
     136                $this->assertEquals( 200, $response->get_status() );
     137                $data = $response->get_data();
     138                $meta = (array) $data['meta'];
     139                $this->assertContains( 'value1', $meta['test_multi'] );
     140                $this->assertContains( 'value2', $meta['test_multi'] );
     141        }
     142
     143        /**
     144         * @depends test_get_value
     145         */
     146        public function test_get_unregistered() {
     147                add_user_meta( self::$user, 'test_unregistered', 'value1' );
     148                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$user ) );
     149
     150                wp_set_current_user( self::$administrator_id );
     151
     152                $response = $this->server->dispatch( $request );
     153                $this->assertEquals( 200, $response->get_status() );
     154
     155                $data = $response->get_data();
     156                $meta = (array) $data['meta'];
     157                $this->assertArrayNotHasKey( 'test_unregistered', $meta );
     158        }
     159
     160        /**
     161         * @depends test_get_value
     162         */
     163        public function test_get_registered_no_api_access() {
     164                add_user_meta( self::$user, 'test_no_rest', 'for_the_wicked' );
     165                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$user ) );
     166
     167                wp_set_current_user( self::$administrator_id );
     168
     169                $response = $this->server->dispatch( $request );
     170                $this->assertEquals( 200, $response->get_status() );
     171
     172                $data = $response->get_data();
     173                $meta = (array) $data['meta'];
     174                $this->assertArrayNotHasKey( 'test_no_rest', $meta );
     175        }
     176
     177        /**
     178         * @depends test_get_value
     179         */
     180        public function test_get_registered_api_disabled() {
     181                add_user_meta( self::$user, 'test_rest_disabled', 'sleepless_nights' );
     182                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$user ) );
     183
     184                wp_set_current_user( self::$administrator_id );
     185
     186                $response = $this->server->dispatch( $request );
     187                $this->assertEquals( 200, $response->get_status() );
     188
     189                $data = $response->get_data();
     190                $meta = (array) $data['meta'];
     191                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta );
     192        }
     193
     194        public function test_get_value_types() {
     195                register_meta( 'user', 'test_string', array(
     196                        'show_in_rest' => true,
     197                        'single' => true,
     198                        'type' => 'string',
     199                ));
     200                register_meta( 'user', 'test_number', array(
     201                        'show_in_rest' => true,
     202                        'single' => true,
     203                        'type' => 'number',
     204                ));
     205                register_meta( 'user', 'test_bool', array(
     206                        'show_in_rest' => true,
     207                        'single' => true,
     208                        'type' => 'boolean',
     209                ));
     210
     211                /** @var WP_REST_Server $wp_rest_server */
     212                global $wp_rest_server;
     213                $this->server = $wp_rest_server = new Spy_REST_Server;
     214                do_action( 'rest_api_init' );
     215
     216                add_user_meta( self::$user, 'test_string', 42 );
     217                add_user_meta( self::$user, 'test_number', '42' );
     218                add_user_meta( self::$user, 'test_bool', 1 );
     219
     220                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/users/%d', self::$user ) );
     221
     222                wp_set_current_user( self::$administrator_id );
     223
     224                $response = $this->server->dispatch( $request );
     225                $this->assertEquals( 200, $response->get_status() );
     226
     227                $data = $response->get_data();
     228                $meta = (array) $data['meta'];
     229
     230                $this->assertArrayHasKey( 'test_string', $meta );
     231                $this->assertInternalType( 'string', $meta['test_string'] );
     232                $this->assertSame( '42', $meta['test_string'] );
     233
     234                $this->assertArrayHasKey( 'test_number', $meta );
     235                $this->assertInternalType( 'float', $meta['test_number'] );
     236                $this->assertSame( 42.0, $meta['test_number'] );
     237
     238                $this->assertArrayHasKey( 'test_bool', $meta );
     239                $this->assertInternalType( 'boolean', $meta['test_bool'] );
     240                $this->assertSame( true, $meta['test_bool'] );
     241        }
     242
     243        /**
     244         * @depends test_get_value
     245         */
     246        public function test_set_value() {
     247                // Ensure no data exists currently.
     248                $values = get_user_meta( self::$user, 'test_single', false );
     249                $this->assertEmpty( $values );
     250
     251                wp_set_current_user( self::$administrator_id );
     252
     253                $data = array(
     254                        'meta' => array(
     255                                'test_single' => 'test_value',
     256                        ),
     257                );
     258                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     259                $request->set_body_params( $data );
     260
     261                $response = $this->server->dispatch( $request );
     262                $this->assertEquals( 200, $response->get_status() );
     263
     264                $meta = get_user_meta( self::$user, 'test_single', false );
     265                $this->assertNotEmpty( $meta );
     266                $this->assertCount( 1, $meta );
     267                $this->assertEquals( 'test_value', $meta[0] );
     268
     269                $data = $response->get_data();
     270                $meta = (array) $data['meta'];
     271                $this->assertArrayHasKey( 'test_single', $meta );
     272                $this->assertEquals( 'test_value', $meta['test_single'] );
     273        }
     274
     275        /**
     276         * @depends test_get_value
     277         */
     278        public function test_set_duplicate_single_value() {
     279                // Start with an existing metakey and value.
     280                $values = update_user_meta( self::$user, 'test_single', 'test_value' );
     281                $this->assertEquals( 'test_value', get_user_meta( self::$user, 'test_single', true ) );
     282
     283                wp_set_current_user( self::$administrator_id );
     284
     285                $data = array(
     286                        'meta' => array(
     287                                'test_single' => 'test_value',
     288                        ),
     289                );
     290                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     291                $request->set_body_params( $data );
     292
     293                $response = $this->server->dispatch( $request );
     294                $this->assertEquals( 200, $response->get_status() );
     295
     296                $meta = get_user_meta( self::$user, 'test_single', true );
     297                $this->assertNotEmpty( $meta );
     298                $this->assertEquals( 'test_value', $meta );
     299
     300                $data = $response->get_data();
     301                $meta = (array) $data['meta'];
     302                $this->assertArrayHasKey( 'test_single', $meta );
     303                $this->assertEquals( 'test_value', $meta['test_single'] );
     304        }
     305
     306        /**
     307         * @depends test_set_value
     308         */
     309        public function test_set_value_unauthenticated() {
     310                $data = array(
     311                        'meta' => array(
     312                                'test_single' => 'test_value',
     313                        ),
     314                );
     315
     316                wp_set_current_user( 0 );
     317
     318                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     319                $request->set_body_params( $data );
     320
     321                $response = $this->server->dispatch( $request );
     322                $this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
     323
     324                // Check that the value wasn't actually updated.
     325                $this->assertEmpty( get_user_meta( self::$user, 'test_single', false ) );
     326        }
     327
     328        /**
     329         * @depends test_set_value
     330         */
     331        public function test_set_value_blocked() {
     332                $data = array(
     333                        'meta' => array(
     334                                'test_bad_auth' => 'test_value',
     335                        ),
     336                );
     337
     338                wp_set_current_user( self::$administrator_id );
     339
     340                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     341                $request->set_body_params( $data );
     342
     343                $response = $this->server->dispatch( $request );
     344                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     345                $this->assertEmpty( get_user_meta( self::$user, 'test_bad_auth', false ) );
     346        }
     347
     348        /**
     349         * @depends test_set_value
     350         */
     351        public function test_set_value_db_error() {
     352                $data = array(
     353                        'meta' => array(
     354                                'test_single' => 'test_value',
     355                        ),
     356                );
     357
     358                wp_set_current_user( self::$administrator_id );
     359
     360                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     361                $request->set_body_params( $data );
     362
     363                /**
     364                 * Disable showing error as the below is going to intentionally
     365                 * trigger a DB error.
     366                 */
     367                global $wpdb;
     368                $wpdb->suppress_errors = true;
     369                add_filter( 'query', array( $this, 'error_insert_query' ) );
     370
     371                $response = $this->server->dispatch( $request );
     372                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     373                $wpdb->show_errors = true;
     374        }
     375
     376        public function test_set_value_multiple() {
     377                // Ensure no data exists currently.
     378                $values = get_user_meta( self::$user, 'test_multi', false );
     379                $this->assertEmpty( $values );
     380
     381                wp_set_current_user( self::$administrator_id );
     382
     383                $data = array(
     384                        'meta' => array(
     385                                'test_multi' => array( 'val1' ),
     386                        ),
     387                );
     388                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     389                $request->set_body_params( $data );
     390
     391                $response = $this->server->dispatch( $request );
     392                $this->assertEquals( 200, $response->get_status() );
     393
     394                $meta = get_user_meta( self::$user, 'test_multi', false );
     395                $this->assertNotEmpty( $meta );
     396                $this->assertCount( 1, $meta );
     397                $this->assertEquals( 'val1', $meta[0] );
     398
     399                // Add another value.
     400                $data = array(
     401                        'meta' => array(
     402                                'test_multi' => array( 'val1', 'val2' ),
     403                        ),
     404                );
     405                $request->set_body_params( $data );
     406
     407                $response = $this->server->dispatch( $request );
     408                $this->assertEquals( 200, $response->get_status() );
     409
     410                $meta = get_user_meta( self::$user, 'test_multi', false );
     411                $this->assertNotEmpty( $meta );
     412                $this->assertCount( 2, $meta );
     413                $this->assertContains( 'val1', $meta );
     414                $this->assertContains( 'val2', $meta );
     415        }
     416
     417        /**
     418         * Test removing only one item with duplicate items.
     419         */
     420        public function test_set_value_remove_one() {
     421                add_user_meta( self::$user, 'test_multi', 'c' );
     422                add_user_meta( self::$user, 'test_multi', 'n' );
     423                add_user_meta( self::$user, 'test_multi', 'n' );
     424
     425                wp_set_current_user( self::$administrator_id );
     426
     427                $data = array(
     428                        'meta' => array(
     429                                'test_multi' => array( 'c', 'n' ),
     430                        ),
     431                );
     432                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     433                $request->set_body_params( $data );
     434
     435                $response = $this->server->dispatch( $request );
     436                $this->assertEquals( 200, $response->get_status() );
     437
     438                $meta = get_user_meta( self::$user, 'test_multi', false );
     439                $this->assertNotEmpty( $meta );
     440                $this->assertCount( 2, $meta );
     441                $this->assertContains( 'c', $meta );
     442                $this->assertContains( 'n', $meta );
     443        }
     444
     445        /**
     446         * @depends test_set_value_multiple
     447         */
     448        public function test_set_value_multiple_unauthenticated() {
     449                // Ensure no data exists currently.
     450                $values = get_user_meta( self::$user, 'test_multi', false );
     451                $this->assertEmpty( $values );
     452
     453                wp_set_current_user( 0 );
     454
     455                $data = array(
     456                        'meta' => array(
     457                                'test_multi' => array( 'val1' ),
     458                        ),
     459                );
     460                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     461                $request->set_body_params( $data );
     462
     463                $response = $this->server->dispatch( $request );
     464                $this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
     465
     466                $meta = get_user_meta( self::$user, 'test_multi', false );
     467                $this->assertEmpty( $meta );
     468        }
     469
     470        /**
     471         * @depends test_set_value_multiple
     472         */
     473        public function test_set_value_multiple_blocked() {
     474                $data = array(
     475                        'meta' => array(
     476                                'test_bad_auth_multi' => array( 'test_value' ),
     477                        ),
     478                );
     479
     480                wp_set_current_user( self::$administrator_id );
     481
     482                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     483                $request->set_body_params( $data );
     484
     485                $response = $this->server->dispatch( $request );
     486                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     487                $this->assertEmpty( get_user_meta( self::$user, 'test_bad_auth_multi', false ) );
     488        }
     489
     490        public function test_add_multi_value_db_error() {
     491                // Ensure no data exists currently.
     492                $values = get_user_meta( self::$user, 'test_multi', false );
     493                $this->assertEmpty( $values );
     494
     495                wp_set_current_user( self::$administrator_id );
     496
     497                $data = array(
     498                        'meta' => array(
     499                                'test_multi' => array( 'val1' ),
     500                        ),
     501                );
     502                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     503                $request->set_body_params( $data );
     504
     505                /**
     506                 * Disable showing error as the below is going to intentionally
     507                 * trigger a DB error.
     508                 */
     509                global $wpdb;
     510                $wpdb->suppress_errors = true;
     511                add_filter( 'query', array( $this, 'error_insert_query' ) );
     512
     513                $response = $this->server->dispatch( $request );
     514                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     515                $wpdb->show_errors = true;
     516
     517                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     518        }
     519
     520        public function test_remove_multi_value_db_error() {
     521                add_user_meta( self::$user, 'test_multi', 'val1' );
     522                $values = get_user_meta( self::$user, 'test_multi', false );
     523                $this->assertEquals( array( 'val1' ), $values );
     524
     525                wp_set_current_user( self::$administrator_id );
     526
     527                $data = array(
     528                        'meta' => array(
     529                                'test_multi' => array(),
     530                        ),
     531                );
     532                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     533                $request->set_body_params( $data );
     534
     535                /**
     536                 * Disable showing error as the below is going to intentionally
     537                 * trigger a DB error.
     538                 */
     539                global $wpdb;
     540                $wpdb->suppress_errors = true;
     541                add_filter( 'query', array( $this, 'error_delete_query' ) );
     542
     543                $response = $this->server->dispatch( $request );
     544                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     545                $wpdb->show_errors = true;
     546
     547                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     548        }
     549
     550        public function test_delete_value() {
     551                add_user_meta( self::$user, 'test_single', 'val1' );
     552                $current = get_user_meta( self::$user, 'test_single', true );
     553                $this->assertEquals( 'val1', $current );
     554
     555                wp_set_current_user( self::$administrator_id );
     556
     557                $data = array(
     558                        'meta' => array(
     559                                'test_single' => null,
     560                        ),
     561                );
     562                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     563                $request->set_body_params( $data );
     564
     565                $response = $this->server->dispatch( $request );
     566                $this->assertEquals( 200, $response->get_status() );
     567
     568                $meta = get_user_meta( self::$user, 'test_single', false );
     569                $this->assertEmpty( $meta );
     570        }
     571
     572        /**
     573         * @depends test_delete_value
     574         */
     575        public function test_delete_value_blocked() {
     576                add_user_meta( self::$user, 'test_bad_auth', 'val1' );
     577                $current = get_user_meta( self::$user, 'test_bad_auth', true );
     578                $this->assertEquals( 'val1', $current );
     579
     580                wp_set_current_user( self::$administrator_id );
     581
     582                $data = array(
     583                        'meta' => array(
     584                                'test_bad_auth' => null,
     585                        ),
     586                );
     587                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     588                $request->set_body_params( $data );
     589
     590                $response = $this->server->dispatch( $request );
     591                $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
     592
     593                $meta = get_user_meta( self::$user, 'test_bad_auth', true );
     594                $this->assertEquals( 'val1', $meta );
     595        }
     596
     597        /**
     598         * @depends test_delete_value
     599         */
     600        public function test_delete_value_db_error() {
     601                add_user_meta( self::$user, 'test_single', 'val1' );
     602                $current = get_user_meta( self::$user, 'test_single', true );
     603                $this->assertEquals( 'val1', $current );
     604
     605                wp_set_current_user( self::$administrator_id );
     606
     607                $data = array(
     608                        'meta' => array(
     609                                'test_single' => null,
     610                        ),
     611                );
     612                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/users/%d', self::$user ) );
     613                $request->set_body_params( $data );
     614                /**
     615                 * Disable showing error as the below is going to intentionally
     616                 * trigger a DB error.
     617                 */
     618                global $wpdb;
     619                $wpdb->suppress_errors = true;
     620                add_filter( 'query', array( $this, 'error_delete_query' ) );
     621
     622                $response = $this->server->dispatch( $request );
     623                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     624                $wpdb->show_errors = true;
     625
     626                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     627        }
     628
     629        public function test_get_schema() {
     630                $request = new WP_REST_Request( 'OPTIONS', sprintf( '/wp/v2/users/%d', self::$user ) );
     631                $response = $this->server->dispatch( $request );
     632
     633                $data = $response->get_data();
     634                $schema = $data['schema'];
     635
     636                $this->assertArrayHasKey( 'meta', $schema['properties'] );
     637                $meta_schema = $schema['properties']['meta']['properties'];
     638
     639                $this->assertArrayHasKey( 'test_single', $meta_schema );
     640                $this->assertEquals( 'string', $meta_schema['test_single']['type'] );
     641
     642                $this->assertArrayHasKey( 'test_multi', $meta_schema );
     643                $this->assertEquals( 'array', $meta_schema['test_multi']['type'] );
     644                $this->assertArrayHasKey( 'items', $meta_schema['test_multi'] );
     645                $this->assertEquals( 'string', $meta_schema['test_multi']['items']['type'] );
     646
     647                $this->assertArrayHasKey( 'test_custom_schema', $meta_schema );
     648                $this->assertEquals( 'number', $meta_schema['test_custom_schema']['type'] );
     649
     650                $this->assertArrayNotHasKey( 'test_no_rest', $meta_schema );
     651                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta_schema );
     652                $this->assertArrayNotHasKey( 'test_invalid_type', $meta_schema );
     653        }
     654
     655        /**
     656         * Internal function used to disable an insert query which
     657         * will trigger a wpdb error for testing purposes.
     658         */
     659        public function error_insert_query( $query ) {
     660                if ( strpos( $query, 'INSERT' ) === 0 ) {
     661                        $query = '],';
     662                }
     663                return $query;
     664        }
     665
     666        /**
     667         * Internal function used to disable an insert query which
     668         * will trigger a wpdb error for testing purposes.
     669         */
     670        public function error_delete_query( $query ) {
     671                if ( strpos( $query, 'DELETE' ) === 0 ) {
     672                        $query = '],';
     673                }
     674                return $query;
     675        }
     676}
  • new file tests/phpunit/tests/term/capabilities.php

    diff --git a/tests/phpunit/tests/term/capabilities.php b/tests/phpunit/tests/term/capabilities.php
    new file mode 100644
    index 0000000..b6b4c2f
    - +  
     1<?php
     2
     3/**
     4 * @group taxonomy
     5 * @group capabilities
     6 */
     7
     8class Tests_Term_Capabilities extends WP_UnitTestCase {
     9        protected static $admin;
     10        protected static $u1;
     11        protected static $u2;
     12        protected static $tag;
     13
     14        public static function wpSetUpBeforeClass( $factory ) {
     15                self::$admin = $factory->user->create( array( 'role' => 'administrator' ) );
     16                self::$u1 = $factory->user->create( array( 'role' => 'subscriber' ) );
     17                self::$u2 = $factory->user->create( array( 'role' => 'subscriber' ) );
     18
     19                self::$tag = $factory->tag->create();
     20        }
     21
     22        public static function wpTearDownAfterClass() {
     23                self::delete_user( self::$admin );
     24                self::delete_user( self::$u1 );
     25                self::delete_user( self::$u2 );
     26
     27                wp_delete_term( self::$tag, 'post_tag' );
     28        }
     29
     30        public function setUp() {
     31                parent::setUp();
     32                add_filter( 'user_has_cap', array( $this, 'grant_edit_term_to_u1' ), 10, 4 );
     33        }
     34
     35        public function tearDown() {
     36                parent::tearDown();
     37                remove_filter( 'user_has_cap', array( $this, 'grant_edit_term_to_u1' ), 10, 4 );
     38        }
     39
     40        public function grant_edit_term_to_u1( $allcaps, $caps, $args, WP_User $user ) {
     41                if ( array( 'manage_categories' ) == $caps && self::$u1 === $user->ID ) {
     42                        $allcaps['manage_categories'] = 1;
     43                }
     44
     45                return $allcaps;
     46        }
     47
     48        public function test_no_one_can_edit_term_meta_for_non_existent_term() {
     49                wp_set_current_user( self::$admin );
     50                $this->assertFalse( current_user_can( 'edit_term_meta', 999999 ) );
     51        }
     52
     53        public function test_user_can_edit_term_meta() {
     54                wp_set_current_user( self::$u1 );
     55                $this->assertTrue( current_user_can( 'edit_term_meta', self::$tag, 'foo' ) );
     56        }
     57
     58        public function test_user_cannot_edit_term_meta() {
     59                wp_set_current_user( self::$u2 );
     60                $this->assertFalse( current_user_can( 'edit_term_meta', self::$tag, 'foo' ) );
     61        }
     62
     63        public function test_no_one_can_delete_term_meta_for_non_existent_term() {
     64                wp_set_current_user( self::$admin );
     65                $this->assertFalse( current_user_can( 'delete_term_meta', 999999, 'foo' ) );
     66        }
     67
     68        public function test_user_can_delete_term_meta() {
     69                wp_set_current_user( self::$u1 );
     70                $this->assertTrue( current_user_can( 'delete_term_meta', self::$tag, 'foo' ) );
     71        }
     72
     73        public function test_user_cannot_delete_term_meta() {
     74                wp_set_current_user( self::$u2 );
     75                $this->assertFalse( current_user_can( 'delete_term_meta', self::$tag, 'foo' ) );
     76        }
     77
     78        public function test_no_one_can_add_term_meta_for_non_existent_term() {
     79                wp_set_current_user( self::$admin );
     80                $this->assertFalse( current_user_can( 'add_term_meta', 999999, 'foo' ) );
     81        }
     82
     83        public function test_user_can_add_term_meta() {
     84                wp_set_current_user( self::$u1 );
     85                $this->assertTrue( current_user_can( 'add_term_meta', self::$tag, 'foo' ) );
     86        }
     87
     88        public function test_user_cannot_add_term_meta() {
     89                wp_set_current_user( self::$u2 );
     90                $this->assertFalse( current_user_can( 'add_term_meta', self::$tag, 'foo' ) );
     91        }
     92}
  • tests/phpunit/tests/user/capabilities.php

    diff --git a/tests/phpunit/tests/user/capabilities.php b/tests/phpunit/tests/user/capabilities.php
    index 8ed2c65..b440e67 100644
    a b class Tests_User_Capabilities extends WP_UnitTestCase { 
    431431                        $expected['delete_post_meta'],
    432432                        $expected['add_post_meta'],
    433433                        $expected['edit_comment'],
     434                        $expected['edit_comment_meta'],
     435                        $expected['delete_comment_meta'],
     436                        $expected['add_comment_meta'],
    434437                        $expected['edit_term'],
    435438                        $expected['delete_term'],
    436439                        $expected['assign_term'],
    437                         $expected['delete_user']
     440                        $expected['edit_term_meta'],
     441                        $expected['delete_term_meta'],
     442                        $expected['add_term_meta'],
     443                        $expected['delete_user'],
     444                        $expected['edit_user_meta'],
     445                        $expected['delete_user_meta'],
     446                        $expected['add_user_meta']
    438447                );
    439448
    440449                $expected = array_keys( $expected );
    class Tests_User_Capabilities extends WP_UnitTestCase { 
    16631672                $wp_roles = new WP_Roles();
    16641673                $wp_roles->reinit();
    16651674        }
     1675
     1676        /**
     1677         * @ticket 38412
     1678         */
     1679        public function test_no_one_can_edit_user_meta_for_non_existent_term() {
     1680                wp_set_current_user( self::$super_admin->ID );
     1681                $this->assertFalse( current_user_can( 'edit_user_meta', 999999 ) );
     1682        }
     1683
     1684        /**
     1685         * @ticket 38412
     1686         */
     1687        public function test_user_can_edit_user_meta() {
     1688                wp_set_current_user( self::$users['administrator']->ID );
     1689                if ( is_multisite() ) {
     1690                        grant_super_admin( self::$users['administrator']->ID );
     1691                }
     1692                $this->assertTrue( current_user_can( 'edit_user_meta', self::$users['subscriber']->ID, 'foo' ) );
     1693        }
     1694
     1695        /**
     1696         * @ticket 38412
     1697         */
     1698        public function test_user_cannot_edit_user_meta() {
     1699                wp_set_current_user( self::$users['editor']->ID );
     1700                $this->assertFalse( current_user_can( 'edit_user_meta', self::$users['subscriber']->ID, 'foo' ) );
     1701        }
     1702
     1703        /**
     1704         * @ticket 38412
     1705         */
     1706        public function test_no_one_can_delete_user_meta_for_non_existent_term() {
     1707                wp_set_current_user( self::$super_admin->ID );
     1708                $this->assertFalse( current_user_can( 'delete_user_meta', 999999, 'foo' ) );
     1709        }
     1710
     1711        /**
     1712         * @ticket 38412
     1713         */
     1714        public function test_user_can_delete_user_meta() {
     1715                wp_set_current_user( self::$users['administrator']->ID );
     1716                if ( is_multisite() ) {
     1717                        grant_super_admin( self::$users['administrator']->ID );
     1718                }
     1719                $this->assertTrue( current_user_can( 'delete_user_meta', self::$users['subscriber']->ID, 'foo' ) );
     1720        }
     1721
     1722        /**
     1723         * @ticket 38412
     1724         */
     1725        public function test_user_cannot_delete_user_meta() {
     1726                wp_set_current_user( self::$users['editor']->ID );
     1727                $this->assertFalse( current_user_can( 'delete_user_meta', self::$users['subscriber']->ID, 'foo' ) );
     1728        }
     1729
     1730        /**
     1731         * @ticket 38412
     1732         */
     1733        public function test_no_one_can_add_user_meta_for_non_existent_term() {
     1734                wp_set_current_user( self::$super_admin->ID );
     1735                $this->assertFalse( current_user_can( 'add_user_meta', 999999, 'foo' ) );
     1736        }
     1737
     1738        /**
     1739         * @ticket 38412
     1740         */
     1741        public function test_user_can_add_user_meta() {
     1742                wp_set_current_user( self::$users['administrator']->ID );
     1743                if ( is_multisite() ) {
     1744                        grant_super_admin( self::$users['administrator']->ID );
     1745                }
     1746                $this->assertTrue( current_user_can( 'add_user_meta', self::$users['subscriber']->ID, 'foo' ) );
     1747        }
     1748
     1749        /**
     1750         * @ticket 38412
     1751         */
     1752        public function test_user_cannot_add_user_meta() {
     1753                wp_set_current_user( self::$users['editor']->ID );
     1754                $this->assertFalse( current_user_can( 'add_user_meta', self::$users['subscriber']->ID, 'foo' ) );
     1755        }
    16661756}