diff --git a/composer.json b/composer.json index 9056b00..b400d1d 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "prefer-stable": true, "minimum-stability": "dev", "require": { - "automattic/jetpack-autoloader": "^2.0.0" + "automattic/jetpack-autoloader": "^2.2.0" }, "require-dev": { "phpunit/phpunit": "6.5.14", diff --git a/src/Controllers/Version2/class-wc-rest-coupons-v2-controller.php b/src/Controllers/Version2/class-wc-rest-coupons-v2-controller.php index e8ab107..7dbcaa1 100644 --- a/src/Controllers/Version2/class-wc-rest-coupons-v2-controller.php +++ b/src/Controllers/Version2/class-wc-rest-coupons-v2-controller.php @@ -511,7 +511,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version2/class-wc-rest-customers-v2-controller.php b/src/Controllers/Version2/class-wc-rest-customers-v2-controller.php index 22fb257..29d4e07 100644 --- a/src/Controllers/Version2/class-wc-rest-customers-v2-controller.php +++ b/src/Controllers/Version2/class-wc-rest-customers-v2-controller.php @@ -350,7 +350,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version2/class-wc-rest-order-refunds-v2-controller.php b/src/Controllers/Version2/class-wc-rest-order-refunds-v2-controller.php index c0b30dc..dff06e2 100644 --- a/src/Controllers/Version2/class-wc-rest-order-refunds-v2-controller.php +++ b/src/Controllers/Version2/class-wc-rest-order-refunds-v2-controller.php @@ -410,7 +410,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -432,13 +432,13 @@ public function get_item_schema() { ), 'name' => array( 'description' => __( 'Product name.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'product_id' => array( 'description' => __( 'Product ID.', 'woocommerce-rest-api' ), - 'type' => array( 'integer', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), @@ -535,7 +535,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), diff --git a/src/Controllers/Version2/class-wc-rest-orders-v2-controller.php b/src/Controllers/Version2/class-wc-rest-orders-v2-controller.php index 2744e42..a9422ae 100644 --- a/src/Controllers/Version2/class-wc-rest-orders-v2-controller.php +++ b/src/Controllers/Version2/class-wc-rest-orders-v2-controller.php @@ -1170,7 +1170,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1191,12 +1191,12 @@ public function get_item_schema() { ), 'name' => array( 'description' => __( 'Product name.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'product_id' => array( 'description' => __( 'Product ID.', 'woocommerce-rest-api' ), - 'type' => array( 'integer' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'variation_id' => array( @@ -1282,7 +1282,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1373,7 +1373,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1397,12 +1397,12 @@ public function get_item_schema() { ), 'method_title' => array( 'description' => __( 'Shipping method name.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'method_id' => array( 'description' => __( 'Shipping method ID.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'instance_id' => array( @@ -1464,7 +1464,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1488,7 +1488,7 @@ public function get_item_schema() { ), 'name' => array( 'description' => __( 'Fee name.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'tax_class' => array( @@ -1562,7 +1562,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1586,7 +1586,7 @@ public function get_item_schema() { ), 'code' => array( 'description' => __( 'Coupon code.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'discount' => array( @@ -1620,7 +1620,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version2/class-wc-rest-product-variations-v2-controller.php b/src/Controllers/Version2/class-wc-rest-product-variations-v2-controller.php index 4941870..392098a 100644 --- a/src/Controllers/Version2/class-wc-rest-product-variations-v2-controller.php +++ b/src/Controllers/Version2/class-wc-rest-product-variations-v2-controller.php @@ -799,7 +799,7 @@ public function get_item_schema() { ), 'manage_stock' => array( 'description' => __( 'Stock management at variation level.', 'woocommerce-rest-api' ), - 'type' => array( 'boolean', 'null' ), + 'type' => 'mixed', 'default' => false, 'context' => array( 'view', 'edit' ), ), @@ -982,7 +982,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version2/class-wc-rest-products-v2-controller.php b/src/Controllers/Version2/class-wc-rest-products-v2-controller.php index 8155463..f38ecb7 100644 --- a/src/Controllers/Version2/class-wc-rest-products-v2-controller.php +++ b/src/Controllers/Version2/class-wc-rest-products-v2-controller.php @@ -2084,7 +2084,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php b/src/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php index e23aa3a..7c8a72a 100644 --- a/src/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php +++ b/src/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php @@ -530,18 +530,12 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Setting value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'array', 'null' ), - 'items' => array( - 'type' => array( 'string', 'null' ), - ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'default' => array( 'description' => __( 'Default value for the setting.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'array', 'null' ), - 'items' => array( - 'type' => array( 'string', 'null' ), - ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), diff --git a/src/Controllers/Version3/class-wc-rest-controller.php b/src/Controllers/Version3/class-wc-rest-controller.php index d851be5..7f16389 100644 --- a/src/Controllers/Version3/class-wc-rest-controller.php +++ b/src/Controllers/Version3/class-wc-rest-controller.php @@ -93,16 +93,57 @@ public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CRE return $endpoint_args; } + $endpoint_args = $this->adjust_wp_5_5_datatype_compatibility( $endpoint_args ); + + return $endpoint_args; + } + + /** + * Change datatypes `date-time` to string, and `mixed` to composite of all built in types. This is required for maintaining forward compatibility with WP 5.5 since custom post types are not supported anymore. + * + * See @link https://core.trac.wordpress.org/changeset/48306 + * + * We still use the 'mixed' type, since if we convert to composite type everywhere, it won't work in 5.4 anymore because they require to define the full schema. + * + * @param array $endpoint_args Schema with datatypes to convert. + + * @return mixed Schema with converted datatype. + */ + protected function adjust_wp_5_5_datatype_compatibility( $endpoint_args ) { + if ( version_compare( get_bloginfo( 'version' ), '5.5', '<' ) ) { + return $endpoint_args; + } + foreach ( $endpoint_args as $field_id => $params ) { + + if ( ! isset( $params['type'] ) ) { + continue; + } + /** - * Custom types are not supported as of WP 5.5, this translates type => 'date-time' to type => 'string' with format date-time. + * Custom types are not supported as of WP 5.5, this translates type => 'date-time' to type => 'string'. */ if ( 'date-time' === $params['type'] ) { - $endpoint_args[ $field_id ]['type'] = 'string'; - $endpoint_args[ $field_id ]['format'] = 'date-time'; + $params['type'] = array( 'null', 'string' ); + } + + /** + * WARNING: Order of fields here is important, types of fields are ordered from most specific to least specific as perceived by core's built-in type validation methods. + */ + if ( 'mixed' === $params['type'] ) { + $params['type'] = array( 'null', 'object', 'string', 'number', 'boolean', 'integer', 'array' ); + } + + if ( isset( $params['properties'] ) ) { + $params['properties'] = $this->adjust_wp_5_5_datatype_compatibility( $params['properties'] ); } - } + if ( isset( $params['items'] ) && isset( $params['items']['properties'] ) ) { + $params['items']['properties'] = $this->adjust_wp_5_5_datatype_compatibility( $params['items']['properties'] ); + } + + $endpoint_args[ $field_id ] = $params; + } return $endpoint_args; } diff --git a/src/Controllers/Version3/class-wc-rest-crud-controller.php b/src/Controllers/Version3/class-wc-rest-crud-controller.php index 7aaa3af..c12186e 100644 --- a/src/Controllers/Version3/class-wc-rest-crud-controller.php +++ b/src/Controllers/Version3/class-wc-rest-crud-controller.php @@ -91,8 +91,6 @@ public function delete_item_permissions_check( $request ) { return true; } - - /** * Get object permalink. * diff --git a/src/Controllers/Version3/class-wc-rest-customers-controller.php b/src/Controllers/Version3/class-wc-rest-customers-controller.php index 072fb08..65ce592 100644 --- a/src/Controllers/Version3/class-wc-rest-customers-controller.php +++ b/src/Controllers/Version3/class-wc-rest-customers-controller.php @@ -293,7 +293,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version3/class-wc-rest-product-variations-controller.php b/src/Controllers/Version3/class-wc-rest-product-variations-controller.php index 6c71016..0477e81 100644 --- a/src/Controllers/Version3/class-wc-rest-product-variations-controller.php +++ b/src/Controllers/Version3/class-wc-rest-product-variations-controller.php @@ -736,7 +736,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version3/class-wc-rest-products-controller.php b/src/Controllers/Version3/class-wc-rest-products-controller.php index 6f3d3a0..a6401bf 100644 --- a/src/Controllers/Version3/class-wc-rest-products-controller.php +++ b/src/Controllers/Version3/class-wc-rest-products-controller.php @@ -1288,7 +1288,7 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'null' ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/src/Controllers/Version3/class-wc-rest-setting-options-controller.php b/src/Controllers/Version3/class-wc-rest-setting-options-controller.php index 59d3828..b725569 100644 --- a/src/Controllers/Version3/class-wc-rest-setting-options-controller.php +++ b/src/Controllers/Version3/class-wc-rest-setting-options-controller.php @@ -199,18 +199,12 @@ public function get_item_schema() { ), 'value' => array( 'description' => __( 'Setting value.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'array', 'null' ), - 'items' => array( - 'type' => array( 'string', 'null' ), - ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'default' => array( 'description' => __( 'Default value for the setting.', 'woocommerce-rest-api' ), - 'type' => array( 'string', 'array', 'null' ), - 'items' => array( - 'type' => array( 'string', 'null' ), - ), + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), diff --git a/unit-tests/Bootstrap.php b/unit-tests/Bootstrap.php index b10c7f8..a21c4cc 100755 --- a/unit-tests/Bootstrap.php +++ b/unit-tests/Bootstrap.php @@ -128,6 +128,9 @@ protected function load_framework() { require_once $this->tests_dir . '/Helpers/SettingsHelper.php'; require_once $this->tests_dir . '/Helpers/QueueHelper.php'; require_once $this->tests_dir . '/AbstractRestApiTest.php'; + + // Traits. + require_once $this->tests_dir . '/traits/trait-wc-rest-api-complex-meta.php'; } } diff --git a/unit-tests/Tests/Version2/product-variations.php b/unit-tests/Tests/Version2/product-variations.php index 22a53d4..560e886 100644 --- a/unit-tests/Tests/Version2/product-variations.php +++ b/unit-tests/Tests/Version2/product-variations.php @@ -7,6 +7,7 @@ */ class Product_Variations_API_V2 extends WC_REST_Unit_Test_Case { + use WC_REST_API_Complex_Meta; /** * Setup our test server, endpoints, and user info. @@ -299,6 +300,19 @@ public function test_create_variation() { $this->assertEquals( 3, count( $variations ) ); } + /** + * Test updating complex meta object. + */ + public function test_update_complex_meta_27282() { + wp_set_current_user( $this->user ); + $product = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper::create_variation_product(); + $product->save(); + $variations = $product->get_available_variations( 'objects' ); + $first_variation_id = $variations[0]->get_id(); + $url = '/wc/v2/products/' . $product->get_id() . '/variations/' . $first_variation_id; + $this->assert_update_complex_meta( $url ); + } + /** * Test creating a single variation without permission. * diff --git a/unit-tests/Tests/Version3/orders.php b/unit-tests/Tests/Version3/orders.php index 6ebb747..ea5768c 100644 --- a/unit-tests/Tests/Version3/orders.php +++ b/unit-tests/Tests/Version3/orders.php @@ -10,6 +10,7 @@ * Class WC_Tests_API_Orders */ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case { + use WC_REST_API_Complex_Meta; /** * Array of order to track @@ -76,12 +77,22 @@ public function test_get_items_ordered_by_modified() { $order2->save(); $request = new WP_REST_Request( 'GET', '/wc/v3/orders' ); - $request->set_query_params( array( 'orderby' => 'modified', 'order' => 'asc' ) ); + $request->set_query_params( + array( + 'orderby' => 'modified', + 'order' => 'asc', + ) + ); $response = $this->server->dispatch( $request ); $orders = $response->get_data(); $this->assertEquals( $order1->get_id(), $orders[0]['id'] ); - $request->set_query_params( array( 'orderby' => 'modified', 'order' => 'desc' ) ); + $request->set_query_params( + array( + 'orderby' => 'modified', + 'order' => 'desc', + ) + ); $response = $this->server->dispatch( $request ); $orders = $response->get_data(); $this->assertEquals( $order2->get_id(), $orders[0]['id'] ); @@ -208,6 +219,20 @@ public function test_create_order() { 'method_title' => 'Flat rate', 'total' => '10.00', 'instance_id' => '1', + 'meta_data' => array( + array( + 'key' => 'string', + 'value' => 'string_val', + ), + array( + 'key' => 'integer', + 'value' => 1, + ), + array( + 'key' => 'array', + 'value' => array( 1, 2 ), + ), + ), ), ), ) diff --git a/unit-tests/Tests/Version3/products.php b/unit-tests/Tests/Version3/products.php index 2235189..fa00aa6 100644 --- a/unit-tests/Tests/Version3/products.php +++ b/unit-tests/Tests/Version3/products.php @@ -10,6 +10,7 @@ * WC_Tests_API_Product class. */ class WC_Tests_API_Product extends WC_REST_Unit_Test_Case { + use WC_REST_API_Complex_Meta; /** * Setup our test server, endpoints, and user info. @@ -218,7 +219,7 @@ public function test_update_product() { $product = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper::create_simple_product(); $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() ) ); $data = $response->get_data(); - $date_created = date( 'Y-m-d\TH:i:s', current_time( 'timestamp' ) ); + $date_created = gmdate( 'Y-m-d\TH:i:s', current_time( 'timestamp' ) ); $this->assertEquals( 'DUMMY SKU', $data['sku'] ); $this->assertEquals( 10, $data['regular_price'] ); @@ -455,6 +456,55 @@ public function test_create_product() { $this->assertEquals( 3, count( $products ) ); } + /** + * Test to update complex metadata. + */ + public function test_update_complex_meta_27282() { + wp_set_current_user( $this->user ); + $product = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper::create_simple_product(); + $product->save(); + $url = '/wc/v3/products/' . $product->get_id(); + $this->assert_update_complex_meta( $url ); + } + + /** + * Test to update datetime property. + */ + public function test_update_date_time() { + wp_set_current_user( $this->user ); + $product = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper::create_simple_product(); + $product->save(); + $date_from_sale = '2020-01-01T01:01:01'; + + $request = new WP_REST_Request( 'PUT', '/wc/v3/products/' . $product->get_id() ); + + $request->set_body_params( array( 'date_on_sale_from' => $date_from_sale ) ); + $response = $this->server->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertEquals( $date_from_sale, $data['date_on_sale_from'] ); + + // Empty string should delete. + $request->set_body_params( array( 'date_on_sale_from' => '' ) ); + $response = $this->server->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertEquals( null, $data['date_on_sale_from'] ); + + $request->set_body_params( array( 'date_on_sale_from' => $date_from_sale ) ); + $response = $this->server->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertEquals( $date_from_sale, $data['date_on_sale_from'] ); + + // Null does not delete. + $request->set_body_params( array( 'date_on_sale_from' => null ) ); + $response = $this->server->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $this->assertEquals( $date_from_sale, $data['date_on_sale_from'] ); + } + /** * Test creating a single product without permission. * diff --git a/unit-tests/bin/install.sh b/unit-tests/bin/install.sh index 8ab83ff..5ad1c12 100755 --- a/unit-tests/bin/install.sh +++ b/unit-tests/bin/install.sh @@ -174,6 +174,7 @@ install_deps() { curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar php wp-cli.phar core config --dbname=$DB_NAME --dbuser=$DB_USER --dbpass=$DB_PASS --dbhost=$DB_HOST --dbprefix=wptests_ + php wp-cli.phar config set JETPACK_AUTOLOAD_DEV true --raw php wp-cli.phar core install --url="$WP_SITE_URL" --title="Example" --admin_user=admin --admin_password=password --admin_email=info@example.com --path=$WP_CORE_DIR --skip-email # Install WooCommerce and WooCommerce Admin diff --git a/unit-tests/traits/trait-wc-rest-api-complex-meta.php b/unit-tests/traits/trait-wc-rest-api-complex-meta.php new file mode 100644 index 0000000..1b51c8b --- /dev/null +++ b/unit-tests/traits/trait-wc-rest-api-complex-meta.php @@ -0,0 +1,83 @@ + 'string_meta', + 'value' => 'string_value', + ), + array( + 'key' => 'int_meta', + 'value' => 1, + ), + array( + 'key' => 'bool_meta', + 'value' => true, + ), + array( + 'key' => 'array_meta', + 'value' => array( 1, 2, 'string' ), + ), + array( + 'key' => 'null_meta', + 'value' => 'null', + ), + array( + 'key' => 'object_meta', + 'value' => array( + 'nested_key1' => 'nested_value1', + 'nested_key2' => 0, + 'nested_key3' => true, + 'nested_key4' => array( 2, 3, 4 ), + 'nested_key5' => array( 2, 3, array( 'deep' => 'nesting' ) ), + ), + ), + ); + + /** + * Test to update `meta_data` field with a complex data type. + * + * @param string $url URL to send request against. + * @param array $options Options for customizations. + */ + public function assert_update_complex_meta( $url, $options = array() ) { + $meta = $options['meta'] ?? self::$sample_meta; + $request = new WP_REST_Request( 'PUT', $url ); + $request->set_body_params( array( 'meta_data' => $meta ) ); + + $response = $this->server->dispatch( $request ); + + $data = $response->get_data(); + + $this->assertEquals( 200, $response->get_status() ); + + $response_meta = $data['meta_data']; + + foreach ( $meta as $meta_object ) { + $found = false; + foreach ( $response_meta as $response_meta_object ) { + if ( $response_meta_object->key === $meta_object['key'] ) { + $response_value = $response_meta_object->value; + $this->assertEquals( $meta_object['value'], $response_value ); + $found = true; + break; + } + } + $this->assertEquals( true, $found, sprintf( 'Meta key %s was not found in response.', $meta_object['key'] ) ); + } + } +}