Make WordPress Core

Ticket #43392: 43392.8.diff

File 43392.8.diff, 30.1 KB (added by kadamwhite, 5 years ago)

Adjust some typos, clarify language, and swap [] to array()

  • src/wp-includes/rest-api.php

    diff --git src/wp-includes/rest-api.php src/wp-includes/rest-api.php
    index 5ec557547c..3054d61ea4 100644
    function rest_validate_value_from_schema( $value, $args, $param = '' ) { 
    11591159                if ( $value instanceof stdClass ) {
    11601160                        $value = (array) $value;
    11611161                }
     1162
     1163                if ( $value instanceof JsonSerializable ) {
     1164                        $value = $value->jsonSerialize();
     1165                }
     1166
    11621167                if ( ! is_array( $value ) ) {
    11631168                        /* translators: 1: parameter, 2: type name */
    11641169                        return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'object' ) );
    function rest_validate_value_from_schema( $value, $args, $param = '' ) { 
    11701175                                if ( is_wp_error( $is_valid ) ) {
    11711176                                        return $is_valid;
    11721177                                }
    1173                         } elseif ( isset( $args['additionalProperties'] ) && false === $args['additionalProperties'] ) {
    1174                                 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not a valid property of Object.' ), $property ) );
     1178                        } elseif ( isset( $args['additionalProperties'] ) ) {
     1179                                if ( false === $args['additionalProperties'] ) {
     1180                                        return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not a valid property of Object.' ), $property ) );
     1181                                }
     1182
     1183                                if ( is_array( $args['additionalProperties'] ) ) {
     1184                                        $is_valid = rest_validate_value_from_schema( $v, $args['additionalProperties'], $param . '[' . $property . ']' );
     1185                                        if ( is_wp_error( $is_valid ) ) {
     1186                                                return $is_valid;
     1187                                        }
     1188                                }
    11751189                        }
    11761190                }
    11771191        }
    function rest_sanitize_value_from_schema( $value, $args ) { 
    12981312                if ( $value instanceof stdClass ) {
    12991313                        $value = (array) $value;
    13001314                }
     1315
     1316                if ( $value instanceof JsonSerializable ) {
     1317                        $value = $value->jsonSerialize();
     1318                }
     1319
    13011320                if ( ! is_array( $value ) ) {
    13021321                        return array();
    13031322                }
    function rest_sanitize_value_from_schema( $value, $args ) { 
    13051324                foreach ( $value as $property => $v ) {
    13061325                        if ( isset( $args['properties'][ $property ] ) ) {
    13071326                                $value[ $property ] = rest_sanitize_value_from_schema( $v, $args['properties'][ $property ] );
    1308                         } elseif ( isset( $args['additionalProperties'] ) && false === $args['additionalProperties'] ) {
    1309                                 unset( $value[ $property ] );
     1327                        } elseif ( isset( $args['additionalProperties'] ) ) {
     1328                                if ( false === $args['additionalProperties'] ) {
     1329                                        unset( $value[ $property ] );
     1330                                } elseif ( is_array( $args['additionalProperties'] ) ) {
     1331                                        $value[ $property ] = rest_sanitize_value_from_schema( $v, $args['additionalProperties'] );
     1332                                }
    13101333                        }
    13111334                }
    13121335
  • src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php

    diff --git src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
    index 9cfee2ee71..5b7240ddc6 100644
    abstract class WP_REST_Meta_Fields { 
    143143                         * from the database and then relying on the default value.
    144144                         */
    145145                        if ( is_null( $meta[ $name ] ) ) {
     146                                $args = $this->get_registered_fields()[ $meta_key ];
     147
     148                                if ( $args['single'] ) {
     149                                        $current = get_metadata( $this->get_meta_type(), $object_id, $meta_key, true );
     150
     151                                        if ( is_wp_error( rest_validate_value_from_schema( $current, $args['schema'] ) ) ) {
     152                                                return new WP_Error(
     153                                                        'rest_invalid_stored_value',
     154                                                        /* translators: %s: custom field key */
     155                                                        sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
     156                                                        array( 'status' => 500 )
     157                                                );
     158                                        }
     159                                }
     160
    146161                                $result = $this->delete_meta_value( $object_id, $meta_key, $name );
    147162                                if ( is_wp_error( $result ) ) {
    148163                                        return $result;
    abstract class WP_REST_Meta_Fields { 
    150165                                continue;
    151166                        }
    152167
    153                         $is_valid = rest_validate_value_from_schema( $meta[ $name ], $args['schema'], 'meta.' . $name );
     168                        $value = $meta[ $name ];
     169
     170                        if ( ! $args['single'] && is_array( $value ) && count( array_filter( $value, 'is_null' ) ) ) {
     171                                return new WP_Error(
     172                                        'rest_invalid_stored_value',
     173                                        /* translators: %s: custom field key */
     174                                        sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
     175                                        array( 'status' => 500 )
     176                                );
     177                        }
     178
     179                        $is_valid = rest_validate_value_from_schema( $value, $args['schema'], 'meta.' . $name );
    154180                        if ( is_wp_error( $is_valid ) ) {
    155181                                $is_valid->add_data( array( 'status' => 400 ) );
    156182                                return $is_valid;
    157183                        }
    158184
    159                         $value = rest_sanitize_value_from_schema( $meta[ $name ], $args['schema'] );
     185                        $value = rest_sanitize_value_from_schema( $value, $args['schema'] );
    160186
    161187                        if ( $args['single'] ) {
    162188                                $result = $this->update_meta_value( $object_id, $meta_key, $name, $value );
    abstract class WP_REST_Meta_Fields { 
    260286                        unset( $to_add[ $add_key ] );
    261287                }
    262288
    263                 // `delete_metadata` removes _all_ instances of the value, so only call once.
    264                 $to_remove = array_unique( $to_remove );
     289                // `delete_metadata` removes _all_ instances of the value, so only call once. Otherwise,
     290                // `delete_metadata` will return false for subsequent calls of the same value.
     291                // Use serialization to produce a predictable string that can be used by array_unique.
     292                $to_remove = array_map( 'maybe_unserialize', array_unique( array_map( 'maybe_serialize', $to_remove ) ) );
    265293
    266294                foreach ( $to_remove as $value ) {
    267295                        if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
    abstract class WP_REST_Meta_Fields { 
    393421                        $type = ! empty( $rest_args['type'] ) ? $rest_args['type'] : null;
    394422                        $type = ! empty( $rest_args['schema']['type'] ) ? $rest_args['schema']['type'] : $type;
    395423
    396                         if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number' ) ) ) {
     424                        if ( null === $rest_args['schema']['default'] ) {
     425                                $rest_args['schema']['default'] = $this->get_default_for_type( $type );
     426                        }
     427
     428                        $rest_args['schema'] = $this->default_additional_properties_to_false( $rest_args['schema'] );
     429
     430                        if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number', 'array', 'object' ) ) ) {
    397431                                continue;
    398432                        }
    399433
    400434                        if ( empty( $rest_args['single'] ) ) {
    401                                 $rest_args['schema']['items'] = array(
    402                                         'type' => $rest_args['type'],
     435                                $rest_args['schema'] = array(
     436                                        'type'  => 'array',
     437                                        'items' => $rest_args['schema'],
    403438                                );
    404                                 $rest_args['schema']['type']  = 'array';
    405439                        }
    406440
    407441                        $registered[ $name ] = $rest_args;
    abstract class WP_REST_Meta_Fields { 
    452486         * @return mixed Value prepared for output. If a non-JsonSerializable object, null.
    453487         */
    454488        public static function prepare_value( $value, $request, $args ) {
    455                 $type = $args['schema']['type'];
    456489
    457                 // For multi-value fields, check the item type instead.
    458                 if ( 'array' === $type && ! empty( $args['schema']['items']['type'] ) ) {
    459                         $type = $args['schema']['items']['type'];
     490                if ( $args['single'] ) {
     491                        $schema = $args['schema'];
     492                } else {
     493                        $schema = $args['schema']['items'];
    460494                }
    461495
    462                 switch ( $type ) {
    463                         case 'string':
    464                                 $value = (string) $value;
    465                                 break;
    466                         case 'integer':
    467                                 $value = (int) $value;
    468                                 break;
    469                         case 'number':
    470                                 $value = (float) $value;
    471                                 break;
    472                         case 'boolean':
    473                                 $value = (bool) $value;
    474                                 break;
    475                 }
    476 
    477                 // Don't allow objects to be output.
    478                 if ( is_object( $value ) && ! ( $value instanceof JsonSerializable ) ) {
     496                if ( is_wp_error( rest_validate_value_from_schema( $value, $schema ) ) ) {
    479497                        return null;
    480498                }
    481499
    482                 return $value;
     500                return rest_sanitize_value_from_schema( $value, $schema );
    483501        }
    484502
    485503        /**
    abstract class WP_REST_Meta_Fields { 
    499517
    500518                return $value;
    501519        }
     520
     521        /**
     522         * Recursively add additionalProperties = false to all objects in a schema if no additionalProperties setting
     523         * is specified.
     524         *
     525         * This is needed to restrict properties of objects in meta values to only
     526         * registered items, as the REST API will allow additional properties by
     527         * default.
     528         *
     529         * @since 5.3.0
     530         *
     531         * @param array $schema The schema array.
     532         * @return array
     533         */
     534        protected function default_additional_properties_to_false( $schema ) {
     535                switch ( $schema['type'] ) {
     536                        case 'object':
     537                                foreach ( $schema['properties'] as $key => $child_schema ) {
     538                                        $schema['properties'][ $key ] = $this->default_additional_properties_to_false( $child_schema );
     539                                }
     540
     541                                if ( ! isset( $schema['additionalProperties'] ) ) {
     542                                        $schema['additionalProperties'] = false;
     543                                }
     544                                break;
     545                        case 'array':
     546                                $schema['items'] = $this->default_additional_properties_to_false( $schema['items'] );
     547                                break;
     548                }
     549
     550                return $schema;
     551        }
     552
     553        /**
     554         * Gets the default value for a schema type.
     555         *
     556         * @since 5.3.0
     557         *
     558         * @param string $type
     559         * @return mixed
     560         */
     561        protected function get_default_for_type( $type ) {
     562                switch ( $type ) {
     563                        case 'string':
     564                                return '';
     565                        case 'boolean':
     566                                return false;
     567                        case 'integer':
     568                                return 0;
     569                        case 'number':
     570                                return 0.0;
     571                        case 'array':
     572                                return array();
     573                        case 'object':
     574                                return array();
     575                        default:
     576                                return null;
     577                }
     578        }
    502579}
  • tests/phpunit/includes/class-basic-object.php

    diff --git tests/phpunit/includes/class-basic-object.php tests/phpunit/includes/class-basic-object.php
    index 66ac53703e..6165344bde 100644
     
    77 * @since 4.7.0
    88 */
    99
    10 trigger_error( __FILE__ . ' is deprecated since version 5.0.0 with no alternative available.' );
    11 
    1210/**
    1311 * Class used to test accessing methods and properties
    1412 *
  • new file tests/phpunit/includes/class-jsonserializable-object.php

    diff --git tests/phpunit/includes/class-jsonserializable-object.php tests/phpunit/includes/class-jsonserializable-object.php
    new file mode 100644
    index 0000000000..eb4ae5c3af
    - +  
     1<?php
     2/**
     3 * Unit Tests: JsonSerializable_Object
     4 *
     5 * @package WordPress
     6 * @subpackage UnitTests
     7 * @since 5.3.0
     8 */
     9
     10class JsonSerializable_Object implements JsonSerializable {
     11
     12        private $data;
     13
     14        public function __construct( $data ) {
     15                $this->data = $data;
     16        }
     17
     18        public function jsonSerialize() {
     19                return $this->data;
     20        }
     21}
  • tests/phpunit/includes/functions.php

    diff --git tests/phpunit/includes/functions.php tests/phpunit/includes/functions.php
    index d21aa25235..670d89c44b 100644
     
    11<?php
     2require_once __DIR__ . '/class-basic-object.php';
    23
    34/**
    45 * Retrieves PHPUnit runner version.
  • tests/phpunit/tests/rest-api/rest-post-meta-fields.php

    diff --git tests/phpunit/tests/rest-api/rest-post-meta-fields.php tests/phpunit/tests/rest-api/rest-post-meta-fields.php
    index dc2401b1c3..71bcfdcd87 100644
    class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 
    11761176        }
    11771177
    11781178        /**
    1179          * @ticket 38323
     1179         * @ticket       38323
    11801180         * @dataProvider data_get_subtype_meta_value
    11811181         */
    11821182        public function test_get_subtype_meta_value( $post_type, $meta_key, $single, $in_post_type ) {
    class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 
    12281228        }
    12291229
    12301230        /**
    1231          * @ticket 38323
     1231         * @ticket       38323
    12321232         * @dataProvider data_set_subtype_meta_value
    12331233         */
    12341234        public function test_set_subtype_meta_value( $post_type, $meta_key, $single, $in_post_type, $can_write ) {
    class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 
    12561256                if ( ! $can_write ) {
    12571257                        $this->assertEquals( 403, $response->get_status() );
    12581258                        $this->assertEmpty( get_post_meta( $post_id, $meta_key, $single ) );
     1259
    12591260                        return;
    12601261                }
    12611262
    class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 
    12981299        }
    12991300
    13001301        /**
    1301          * @ticket 42069
     1302         * @ticket       42069
    13021303         * @dataProvider data_update_value_return_success_with_same_value
    13031304         */
    13041305        public function test_update_value_return_success_with_same_value( $meta_key, $meta_value ) {
    class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { 
    13471348                $this->assertEquals( 'Hello', $data['meta']['test\'slashed\'key'] );
    13481349        }
    13491350
     1351        /**
     1352         * @ticket 43392
     1353         */
     1354        public function test_object_single() {
     1355                $this->grant_write_permission();
     1356
     1357                register_post_meta(
     1358                        'post',
     1359                        'object',
     1360                        array(
     1361                                'single'       => true,
     1362                                'type'         => 'object',
     1363                                'show_in_rest' => array(
     1364                                        'schema' => array(
     1365                                                'type'       => 'object',
     1366                                                'properties' => array(
     1367                                                        'project' => array(
     1368                                                                'type' => 'string',
     1369                                                        ),
     1370                                                ),
     1371                                        ),
     1372                                ),
     1373                        )
     1374                );
     1375
     1376                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1377                $request->set_body_params(
     1378                        array(
     1379                                'meta' => array(
     1380                                        'object' => array(
     1381                                                'project' => 'WordPress',
     1382                                        ),
     1383                                ),
     1384                        )
     1385                );
     1386
     1387                $response = rest_get_server()->dispatch( $request );
     1388                $data     = $response->get_data();
     1389
     1390                $this->assertArrayHasKey( 'object', $data['meta'] );
     1391                $this->assertArrayHasKey( 'project', $data['meta']['object'] );
     1392                $this->assertEquals( 'WordPress', $data['meta']['object']['project'] );
     1393
     1394                $meta = get_post_meta( self::$post_id, 'object', true );
     1395                $this->assertArrayHasKey( 'project', $meta );
     1396                $this->assertEquals( 'WordPress', $meta['project'] );
     1397        }
     1398
     1399        /**
     1400         * @ticket 43392
     1401         */
     1402        public function test_object_multiple() {
     1403                $this->grant_write_permission();
     1404
     1405                register_post_meta(
     1406                        'post',
     1407                        'object',
     1408                        array(
     1409                                'single'       => false,
     1410                                'type'         => 'object',
     1411                                'show_in_rest' => array(
     1412                                        'schema' => array(
     1413                                                'type'       => 'object',
     1414                                                'properties' => array(
     1415                                                        'project' => array(
     1416                                                                'type' => 'string',
     1417                                                        ),
     1418                                                ),
     1419                                        ),
     1420                                ),
     1421                        )
     1422                );
     1423
     1424                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1425                $request->set_body_params(
     1426                        array(
     1427                                'meta' => array(
     1428                                        'object' => array(
     1429                                                array(
     1430                                                        'project' => 'WordPress',
     1431                                                ),
     1432                                                array(
     1433                                                        'project' => 'bbPress',
     1434                                                ),
     1435                                        ),
     1436                                ),
     1437                        )
     1438                );
     1439
     1440                $response = rest_get_server()->dispatch( $request );
     1441                $data     = $response->get_data();
     1442
     1443                $this->assertArrayHasKey( 'object', $data['meta'] );
     1444                $this->assertCount( 2, $data['meta']['object'] );
     1445
     1446                $this->assertArrayHasKey( 'project', $data['meta']['object'][0] );
     1447                $this->assertEquals( 'WordPress', $data['meta']['object'][0]['project'] );
     1448
     1449                $this->assertArrayHasKey( 'project', $data['meta']['object'][1] );
     1450                $this->assertEquals( 'bbPress', $data['meta']['object'][1]['project'] );
     1451
     1452                $meta = get_post_meta( self::$post_id, 'object' );
     1453
     1454                $this->assertCount( 2, $meta );
     1455
     1456                $this->assertArrayHasKey( 'project', $meta[0] );
     1457                $this->assertEquals( 'WordPress', $meta[0]['project'] );
     1458
     1459                $this->assertArrayHasKey( 'project', $meta[1] );
     1460                $this->assertEquals( 'bbPress', $meta[1]['project'] );
     1461        }
     1462
     1463        /**
     1464         * @ticket 43392
     1465         */
     1466        public function test_array_single() {
     1467                $this->grant_write_permission();
     1468
     1469                register_post_meta(
     1470                        'post',
     1471                        'list',
     1472                        array(
     1473                                'single'       => true,
     1474                                'type'         => 'array',
     1475                                'show_in_rest' => array(
     1476                                        'schema' => array(
     1477                                                'type'  => 'array',
     1478                                                'items' => array(
     1479                                                        'type' => 'string',
     1480                                                ),
     1481                                        ),
     1482                                ),
     1483                        )
     1484                );
     1485
     1486                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1487                $request->set_body_params(
     1488                        array(
     1489                                'meta' => array(
     1490                                        'list' => array( 'WordPress', 'bbPress' ),
     1491                                ),
     1492                        )
     1493                );
     1494
     1495                $response = rest_get_server()->dispatch( $request );
     1496                $data     = $response->get_data();
     1497
     1498                $this->assertArrayHasKey( 'list', $data['meta'] );
     1499                $this->assertEquals( array( 'WordPress', 'bbPress' ), $data['meta']['list'] );
     1500
     1501                $meta = get_post_meta( self::$post_id, 'list', true );
     1502                $this->assertEquals( array( 'WordPress', 'bbPress' ), $meta );
     1503        }
     1504
     1505        /**
     1506         * @ticket 43392
     1507         */
     1508        public function test_array_of_objects_multiple() {
     1509                $this->grant_write_permission();
     1510
     1511                register_post_meta(
     1512                        'post',
     1513                        'list_of_objects',
     1514                        array(
     1515                                'single'       => false,
     1516                                'type'         => 'array',
     1517                                'show_in_rest' => array(
     1518                                        'schema' => array(
     1519                                                'type'  => 'array',
     1520                                                'items' => array(
     1521                                                        'type'       => 'object',
     1522                                                        'properties' => array(
     1523                                                                'version' => array(
     1524                                                                        'type' => 'string',
     1525                                                                ),
     1526                                                                'artist'  => array(
     1527                                                                        'type' => 'string',
     1528                                                                ),
     1529                                                        ),
     1530                                                ),
     1531                                        ),
     1532                                ),
     1533                        )
     1534                );
     1535
     1536                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1537                $request->set_body_params(
     1538                        array(
     1539                                'meta' => array(
     1540                                        'list_of_objects' => array(
     1541                                                // Meta 1
     1542                                                array(
     1543                                                        array(
     1544                                                                'version' => '5.2',
     1545                                                                'artist'  => 'Jaco',
     1546                                                        ),
     1547                                                        array(
     1548                                                                'version' => '5.1',
     1549                                                                'artist'  => 'Betty',
     1550                                                        ),
     1551                                                ),
     1552                                                // Meta 2
     1553                                                array(
     1554                                                        array(
     1555                                                                'version' => '4.9',
     1556                                                                'artist'  => 'Tipton',
     1557                                                        ),
     1558                                                ),
     1559                                        ),
     1560                                ),
     1561                        )
     1562                );
     1563
     1564                $response = rest_get_server()->dispatch( $request );
     1565                $data     = $response->get_data();
     1566
     1567                $this->assertArrayHasKey( 'list_of_objects', $data['meta'] );
     1568                $this->assertCount( 2, $data['meta']['list_of_objects'] );
     1569
     1570                $this->assertEquals(
     1571                        array(
     1572                                array(
     1573                                        'version' => '5.2',
     1574                                        'artist'  => 'Jaco',
     1575                                ),
     1576                                array(
     1577                                        'version' => '5.1',
     1578                                        'artist'  => 'Betty',
     1579                                ),
     1580                        ),
     1581                        $data['meta']['list_of_objects'][0]
     1582                );
     1583
     1584                $this->assertEquals(
     1585                        array(
     1586                                array(
     1587                                        'version' => '4.9',
     1588                                        'artist'  => 'Tipton',
     1589                                ),
     1590                        ),
     1591                        $data['meta']['list_of_objects'][1]
     1592                );
     1593
     1594                $meta = get_post_meta( self::$post_id, 'list_of_objects' );
     1595
     1596                $this->assertCount( 2, $meta );
     1597
     1598                $this->assertEquals(
     1599                        array(
     1600                                array(
     1601                                        'version' => '5.2',
     1602                                        'artist'  => 'Jaco',
     1603                                ),
     1604                                array(
     1605                                        'version' => '5.1',
     1606                                        'artist'  => 'Betty',
     1607                                ),
     1608                        ),
     1609                        $meta[0]
     1610                );
     1611
     1612                $this->assertEquals(
     1613                        array(
     1614                                array(
     1615                                        'version' => '4.9',
     1616                                        'artist'  => 'Tipton',
     1617                                ),
     1618                        ),
     1619                        $meta[1]
     1620                );
     1621        }
     1622
     1623        /**
     1624         * @ticket 43392
     1625         */
     1626        public function test_php_objects_returned_as_null() {
     1627                register_post_meta(
     1628                        'post',
     1629                        'object',
     1630                        array(
     1631                                'single'       => true,
     1632                                'type'         => 'object',
     1633                                'show_in_rest' => array(
     1634                                        'schema' => array(
     1635                                                'type'       => 'object',
     1636                                                'properties' => array(
     1637                                                        'project' => array(
     1638                                                                'type' => 'string',
     1639                                                        ),
     1640                                                ),
     1641                                        ),
     1642                                ),
     1643                        )
     1644                );
     1645
     1646                $basic          = new Basic_Object();
     1647                $basic->project = 'WordPress';
     1648                update_post_meta( self::$post_id, 'object', $basic );
     1649
     1650                $request  = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1651                $response = rest_get_server()->dispatch( $request );
     1652                $data     = $response->get_data();
     1653
     1654                $this->assertArrayHasKey( 'object', $data['meta'] );
     1655                $this->assertNull( $data['meta']['object'] );
     1656        }
     1657
     1658        /**
     1659         * @ticket 43392
     1660         */
     1661        public function test_php_objects_returned_as_null_multiple() {
     1662                register_post_meta(
     1663                        'post',
     1664                        'object',
     1665                        array(
     1666                                'single'       => false,
     1667                                'type'         => 'object',
     1668                                'show_in_rest' => array(
     1669                                        'schema' => array(
     1670                                                'type'       => 'object',
     1671                                                'properties' => array(
     1672                                                        'project' => array(
     1673                                                                'type' => 'string',
     1674                                                        ),
     1675                                                ),
     1676                                        ),
     1677                                ),
     1678                        )
     1679                );
     1680
     1681                $basic          = new Basic_Object();
     1682                $basic->project = 'WordPress';
     1683                add_post_meta( self::$post_id, 'object', array( 'project' => 'bbPress' ) );
     1684                add_post_meta( self::$post_id, 'object', $basic );
     1685
     1686                $request  = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1687                $response = rest_get_server()->dispatch( $request );
     1688                $data     = $response->get_data();
     1689
     1690                $this->assertArrayHasKey( 'object', $data['meta'] );
     1691                $this->assertCount( 2, $data['meta']['object'] );
     1692                $this->assertEquals( array( 'project' => 'bbPress' ), $data['meta']['object'][0] );
     1693                $this->assertNull( $data['meta']['object'][1] );
     1694        }
     1695
     1696        /**
     1697         * @ticket 43392
     1698         */
     1699        public function test_php_jsonserializable_object_returns_value() {
     1700                require_once __DIR__ . '/../../includes/class-jsonserializable-object.php';
     1701
     1702                register_post_meta(
     1703                        'post',
     1704                        'object',
     1705                        array(
     1706                                'single'       => true,
     1707                                'type'         => 'object',
     1708                                'show_in_rest' => array(
     1709                                        'schema' => array(
     1710                                                'type'       => 'object',
     1711                                                'properties' => array(
     1712                                                        'project' => array(
     1713                                                                'type' => 'string',
     1714                                                        ),
     1715                                                ),
     1716                                        ),
     1717                                ),
     1718                        )
     1719                );
     1720
     1721                update_post_meta( self::$post_id, 'object', new JsonSerializable_Object( array( 'project' => 'WordPress' ) ) );
     1722
     1723                $request  = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1724                $response = rest_get_server()->dispatch( $request );
     1725                $data     = $response->get_data();
     1726
     1727                $this->assertArrayHasKey( 'object', $data['meta'] );
     1728                $this->assertEquals( array( 'project' => 'WordPress' ), $data['meta']['object'] );
     1729        }
     1730
     1731        /**
     1732         * @ticket 43392
     1733         */
     1734        public function test_updating_meta_to_null_for_key_with_existing_php_object_does_not_delete_meta_value() {
     1735                $this->grant_write_permission();
     1736
     1737                register_post_meta(
     1738                        'post',
     1739                        'object',
     1740                        array(
     1741                                'single'       => true,
     1742                                'type'         => 'object',
     1743                                'show_in_rest' => array(
     1744                                        'schema' => array(
     1745                                                'type'       => 'object',
     1746                                                'properties' => array(
     1747                                                        'project' => array(
     1748                                                                'type' => 'string',
     1749                                                        ),
     1750                                                ),
     1751                                        ),
     1752                                ),
     1753                        )
     1754                );
     1755
     1756                $basic          = new Basic_Object();
     1757                $basic->project = 'WordPress';
     1758                update_post_meta( self::$post_id, 'object', $basic );
     1759
     1760                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1761                $request->set_body_params(
     1762                        array(
     1763                                'meta' => array(
     1764                                        'object' => null,
     1765                                ),
     1766                        )
     1767                );
     1768
     1769                $response = rest_get_server()->dispatch( $request );
     1770                $this->assertEquals( 500, $response->get_status() );
     1771        }
     1772
     1773        /**
     1774         * @ticket 43392
     1775         */
     1776        public function test_updating_non_single_meta_to_null_for_key_with_existing_php_object_does_not_set_meta_value_to_null() {
     1777                $this->grant_write_permission();
     1778
     1779                register_post_meta(
     1780                        'post',
     1781                        'object',
     1782                        array(
     1783                                'single'       => false,
     1784                                'type'         => 'object',
     1785                                'show_in_rest' => array(
     1786                                        'schema' => array(
     1787                                                'type'       => 'object',
     1788                                                'properties' => array(
     1789                                                        'project' => array(
     1790                                                                'type' => 'string',
     1791                                                        ),
     1792                                                ),
     1793                                        ),
     1794                                ),
     1795                        )
     1796                );
     1797
     1798                $basic          = new Basic_Object();
     1799                $basic->project = 'WordPress';
     1800                add_post_meta( self::$post_id, 'object', array( 'project' => 'bbPress' ) );
     1801                add_post_meta( self::$post_id, 'object', $basic );
     1802
     1803                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1804                $request->set_body_params(
     1805                        array(
     1806                                'meta' => array(
     1807                                        'object' => array(
     1808                                                array( 'project' => 'BuddyPress' ),
     1809                                                null,
     1810                                        ),
     1811                                ),
     1812                        )
     1813                );
     1814
     1815                $response = rest_get_server()->dispatch( $request );
     1816                $this->assertEquals( 500, $response->get_status() );
     1817        }
     1818
     1819        /**
     1820         * @ticket 43392
     1821         */
     1822        public function test_object_rejects_additional_properties_by_default() {
     1823                $this->grant_write_permission();
     1824
     1825                register_post_meta(
     1826                        'post',
     1827                        'object',
     1828                        array(
     1829                                'single'       => true,
     1830                                'type'         => 'object',
     1831                                'show_in_rest' => array(
     1832                                        'schema' => array(
     1833                                                'type'       => 'object',
     1834                                                'properties' => array(
     1835                                                        'project' => array(
     1836                                                                'type' => 'string',
     1837                                                        ),
     1838                                                ),
     1839                                        ),
     1840                                ),
     1841                        )
     1842                );
     1843
     1844                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1845                $request->set_body_params(
     1846                        array(
     1847                                'meta' => array(
     1848                                        'object' => array(
     1849                                                'project'     => 'BuddyPress',
     1850                                                'awesomeness' => 100,
     1851                                        ),
     1852                                ),
     1853                        )
     1854                );
     1855
     1856                $response = rest_get_server()->dispatch( $request );
     1857                $this->assertEquals( 400, $response->get_status() );
     1858        }
     1859
     1860        /**
     1861         * @ticket 43392
     1862         */
     1863        public function test_object_allows_additional_properties_if_explicitly_set() {
     1864                $this->grant_write_permission();
     1865
     1866                $value = array(
     1867                        'project'     => 'BuddyPress',
     1868                        'awesomeness' => 100,
     1869                );
     1870
     1871                register_post_meta(
     1872                        'post',
     1873                        'object',
     1874                        array(
     1875                                'single'       => true,
     1876                                'type'         => 'object',
     1877                                'show_in_rest' => array(
     1878                                        'schema' => array(
     1879                                                'type'                 => 'object',
     1880                                                'additionalProperties' => true,
     1881                                                'properties'           => array(
     1882                                                        'project' => array(
     1883                                                                'type' => 'string',
     1884                                                        ),
     1885                                                ),
     1886                                        ),
     1887                                ),
     1888                        )
     1889                );
     1890
     1891                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1892                $request->set_body_params(
     1893                        array(
     1894                                'meta' => array(
     1895                                        'object' => $value,
     1896                                ),
     1897                        )
     1898                );
     1899
     1900                $response = rest_get_server()->dispatch( $request );
     1901                $this->assertEquals( 200, $response->get_status() );
     1902                $this->assertEquals( $value, $response->get_data()['meta']['object'] );
     1903
     1904                $this->assertEquals( $value, get_post_meta( self::$post_id, 'object', true ) );
     1905        }
     1906
     1907        /**
     1908         * @ticket 43392
     1909         */
     1910        public function test_object_allows_additional_properties_and_uses_its_schema() {
     1911                $this->grant_write_permission();
     1912
     1913                $value = array(
     1914                        'project'     => 'BuddyPress',
     1915                        'awesomeness' => 'fabulous',
     1916                );
     1917
     1918                register_post_meta(
     1919                        'post',
     1920                        'object',
     1921                        array(
     1922                                'single'       => true,
     1923                                'type'         => 'object',
     1924                                'show_in_rest' => array(
     1925                                        'schema' => array(
     1926                                                'type'                 => 'object',
     1927                                                'additionalProperties' => array(
     1928                                                        'type' => 'number',
     1929                                                ),
     1930                                                'properties'           => array(
     1931                                                        'project' => array(
     1932                                                                'type' => 'string',
     1933                                                        ),
     1934                                                ),
     1935                                        ),
     1936                                ),
     1937                        )
     1938                );
     1939
     1940                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1941                $request->set_body_params(
     1942                        array(
     1943                                'meta' => array(
     1944                                        'object' => $value,
     1945                                ),
     1946                        )
     1947                );
     1948
     1949                $response = rest_get_server()->dispatch( $request );
     1950                $this->assertEquals( 400, $response->get_status() );
     1951        }
     1952
     1953        /**
     1954         * @ticket 43392
     1955         */
     1956        public function test_invalid_meta_value_are_set_to_null_in_response() {
     1957                register_post_meta(
     1958                        'post',
     1959                        'email',
     1960                        array(
     1961                                'single'       => true,
     1962                                'type'         => 'string',
     1963                                'show_in_rest' => array(
     1964                                        'schema' => array(
     1965                                                'type'   => 'string',
     1966                                                'format' => 'email',
     1967                                        ),
     1968                                ),
     1969                        )
     1970                );
     1971
     1972                update_post_meta( self::$post_id, 'email', 'invalid_meta_value' );
     1973
     1974                $request  = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1975                $response = rest_get_server()->dispatch( $request );
     1976
     1977                $this->assertNull( $response->get_data()['meta']['email'] );
     1978        }
     1979
     1980        /**
     1981         * @ticket 43392
     1982         */
     1983        public function test_meta_values_are_not_set_to_null_in_response_if_type_safely_serializable() {
     1984                register_post_meta(
     1985                        'post',
     1986                        'boolean',
     1987                        array(
     1988                                'single'       => true,
     1989                                'show_in_rest' => true,
     1990                                'type'         => 'boolean',
     1991                        )
     1992                );
     1993
     1994                update_post_meta( self::$post_id, 'boolean', 'true' );
     1995
     1996                $request  = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1997                $response = rest_get_server()->dispatch( $request );
     1998
     1999                $this->assertTrue( $response->get_data()['meta']['boolean'] );
     2000        }
     2001
     2002        /**
     2003         * @ticket 43392
     2004         */
     2005        public function test_update_multi_meta_value_object() {
     2006                register_post_meta(
     2007                        'post',
     2008                        'object',
     2009                        array(
     2010                                'single'       => false,
     2011                                'type'         => 'object',
     2012                                'show_in_rest' => array(
     2013                                        'schema' => array(
     2014                                                'type'       => 'object',
     2015                                                'properties' => array(
     2016                                                        'project' => array(
     2017                                                                'type' => 'string',
     2018                                                        ),
     2019                                                ),
     2020                                        ),
     2021                                ),
     2022                        )
     2023                );
     2024
     2025                add_post_meta(
     2026                        self::$post_id,
     2027                        'object',
     2028                        array(
     2029                                'project' => 'WordPress',
     2030                        )
     2031                );
     2032                add_post_meta(
     2033                        self::$post_id,
     2034                        'object',
     2035                        array(
     2036                                'project' => 'bbPress',
     2037                        )
     2038                );
     2039
     2040                $this->grant_write_permission();
     2041
     2042                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     2043                $request->set_body_params(
     2044                        array(
     2045                                'meta' => array(
     2046                                        'object' => array(
     2047                                                array( 'project' => 'WordPress' ),
     2048                                                array( 'project' => 'BuddyPress' ),
     2049                                        ),
     2050                                ),
     2051                        )
     2052                );
     2053
     2054                $response = rest_get_server()->dispatch( $request );
     2055                $this->assertEquals( 200, $response->get_status() );
     2056
     2057                $data = $response->get_data();
     2058                $this->assertArrayHasKey( 'object', $data['meta'] );
     2059
     2060                $this->assertCount( 2, $data['meta']['object'] );
     2061                $this->assertEquals( array( 'project' => 'WordPress' ), $data['meta']['object'][0] );
     2062                $this->assertEquals( array( 'project' => 'BuddyPress' ), $data['meta']['object'][1] );
     2063
     2064                $meta = get_post_meta( self::$post_id, 'object' );
     2065                $this->assertCount( 2, $meta );
     2066                $this->assertEquals( array( 'project' => 'WordPress' ), $meta[0] );
     2067                $this->assertEquals( array( 'project' => 'BuddyPress' ), $meta[1] );
     2068        }
     2069
     2070        /**
     2071         * @ticket 43392
     2072         */
     2073        public function test_update_multi_meta_value_array() {
     2074                register_post_meta(
     2075                        'post',
     2076                        'list',
     2077                        array(
     2078                                'type'         => 'array',
     2079                                'show_in_rest' => array(
     2080                                        'schema' => array(
     2081                                                'type'  => 'array',
     2082                                                'items' => array(
     2083                                                        'type' => 'string',
     2084                                                ),
     2085                                        ),
     2086                                ),
     2087                        )
     2088                );
     2089
     2090                add_post_meta( self::$post_id, 'list', array( 'WordPress', 'bbPress' ) );
     2091                add_post_meta( self::$post_id, 'list', array( 'WordCamp' ) );
     2092
     2093                $this->grant_write_permission();
     2094
     2095                $request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     2096                $request->set_body_params(
     2097                        array(
     2098                                'meta' => array(
     2099                                        'list' => array(
     2100                                                array( 'WordPress', 'bbPress' ),
     2101                                                array( 'BuddyPress' ),
     2102                                        ),
     2103                                ),
     2104                        )
     2105                );
     2106
     2107                $response = rest_get_server()->dispatch( $request );
     2108                $this->assertEquals( 200, $response->get_status() );
     2109
     2110                $data = $response->get_data();
     2111                $this->assertArrayHasKey( 'list', $data['meta'] );
     2112
     2113                $this->assertCount( 2, $data['meta']['list'] );
     2114                $this->assertEquals( array( 'WordPress', 'bbPress' ), $data['meta']['list'][0] );
     2115                $this->assertEquals( array( 'BuddyPress' ), $data['meta']['list'][1] );
     2116
     2117                $meta = get_post_meta( self::$post_id, 'list' );
     2118                $this->assertCount( 2, $meta );
     2119                $this->assertEquals( array( 'WordPress', 'bbPress' ), $meta[0] );
     2120                $this->assertEquals( array( 'BuddyPress' ), $meta[1] );
     2121        }
     2122
    13502123        /**
    13512124         * Internal function used to disable an insert query which
    13522125         * will trigger a wpdb error for testing purposes.