diff --git a/src/classes/jsonld/class-jsonld-endpoint.php b/src/classes/jsonld/class-jsonld-endpoint.php index 8b3e5e0e0..d60e57b06 100644 --- a/src/classes/jsonld/class-jsonld-endpoint.php +++ b/src/classes/jsonld/class-jsonld-endpoint.php @@ -229,7 +229,7 @@ public function jsonld_using_meta( $request ) { $meta_key = $request['meta_key']; $params = $request->get_query_params(); - $meta_value = urldecode( $params['meta_value'] ); + $meta_value = $params['meta_value']; $meta_values = array( $meta_value ); // Merchant Sync stores spaces as plus, so we need to restore them. if ( strpos( $meta_value, ' ' ) > 0 ) { @@ -238,6 +238,16 @@ public function jsonld_using_meta( $request ) { $meta_values[] = str_replace( '+', ' ', $meta_value ); } + $contains_whitespace = strpos( $meta_value, ' ' ) !== false; + $contains_plus = strpos( $meta_value, '+' ) !== false; + + if ( $contains_whitespace ) { + $meta_values[] = str_replace( ' ', '+', $meta_value ); + } + if ( $contains_plus ) { + $meta_values[] = str_replace( '+', ' ', $meta_value ); + } + $sql = " SELECT pm.post_id AS id, %s AS type FROM {$wpdb->postmeta} pm diff --git a/src/composer.json b/src/composer.json index 723d07437..6b16f91ba 100644 --- a/src/composer.json +++ b/src/composer.json @@ -43,5 +43,10 @@ }, "require": { "deliciousbrains/wp-background-processing": "^1.0" + }, + "config": { + "allow-plugins": { + "cweagans/composer-patches": false + } } } diff --git a/src/composer.lock b/src/composer.lock index ffef87d67..dfe270625 100644 --- a/src/composer.lock +++ b/src/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e4128741cec5610310f9aaf6d9de934f", + "content-hash": "edee4ba68851a73a621d5bf67c4d7fb8", "packages": [ { "name": "deliciousbrains/wp-background-processing", @@ -298,6 +298,64 @@ ], "time": "2020-10-18T11:50:25+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.12.15", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "c91d4e8bc056f46cf653656e6f71004b254574d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c91d4e8bc056f46cf653656e6f71004b254574d1", + "reference": "c91d4e8bc056f46cf653656e6f71004b254574d1", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2025-01-05T16:40:22+00:00" + }, { "name": "psr/container", "version": "1.0.0", @@ -1154,10 +1212,10 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.0.0" + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/src/modules/include-exclude-push-config/includes/Include_Exclude_Default_Config_Installer.php b/src/modules/include-exclude-push-config/includes/Include_Exclude_Default_Config_Installer.php index beb61873a..eda756e9e 100644 --- a/src/modules/include-exclude-push-config/includes/Include_Exclude_Default_Config_Installer.php +++ b/src/modules/include-exclude-push-config/includes/Include_Exclude_Default_Config_Installer.php @@ -3,6 +3,7 @@ namespace Wordlift\Modules\Include_Exclude_Push_Config; use Wordlift\Api\Api_Service; +use Wordlift\Api\Response; use Wordlift\Modules\Include_Exclude\Configuration; use Wordlift_Configuration_Service; @@ -37,7 +38,7 @@ public function handle_init() { // Send the default configuration only if it hasn't been sent already. if ( ! get_option( '_wl_include_exclude_default_sent', false ) ) { $response = $this->send(); - if ( $response->is_success() ) { + if ( is_a( $response, Response::class ) && $response->is_success() ) { update_option( '_wl_include_exclude_default_sent', true, true ); } } @@ -49,10 +50,22 @@ public function handle_update_option_wl_exclude_include_urls_settings() { $this->handle_init(); } - public function send() { + /** + * Send the include/exclude default configuration. + * + * @return null|Response + */ + public function send(): ?Response { // I prefer to instantiate the `Wordlift_Configuration_Service` and `Configuration` here // in order to avoid preemptive unused instantiation. - $key = rawurlencode( Wordlift_Configuration_Service::get_instance()->get_key() ); + $key = Wordlift_Configuration_Service::get_instance()->get_key(); + + // That makes no sense for us to send such a request if the key isn't set. + if ( empty( $key ) ) { + return null; + } + + $encoded_key = rawurlencode( $key ); $wp_admin = rawurlencode( untrailingslashit( get_admin_url() ) ); $wp_json = rawurlencode( untrailingslashit( get_rest_url() ) ); $wp_include_exclude_default = rawurlencode( Configuration::get_instance()->get_default() ); @@ -60,7 +73,7 @@ public function send() { return $this->api_service->request( 'PUT', '/accounts/wordpress-configuration?' - . "key=$key" + . "key=$encoded_key" . "&wpAdmin=$wp_admin" . "&wpJson=$wp_json" . "&wp_include_exclude_default=$wp_include_exclude_default" diff --git a/tests/test-jsonld-rest-service.php b/tests/test-jsonld-rest-service.php index 38201f212..80e015590 100644 --- a/tests/test-jsonld-rest-service.php +++ b/tests/test-jsonld-rest-service.php @@ -17,13 +17,21 @@ */ class Wordlift_Jsonld_Endpoint_Test extends Wordlift_Unit_Test_Case { + /** + * @var WP_REST_Server + */ + private $server; + + private const META_KEY = 'META_KEY'; + public function setUp() { parent::setUp(); /** @var WP_REST_Server $wp_rest_server */ global $wp_rest_server; - $wp_rest_server = new Spy_REST_Server; - do_action( 'rest_api_init', $wp_rest_server ); + $wp_rest_server = new WP_REST_Server(); + $this->server = $wp_rest_server; + do_action( 'rest_api_init' ); } public function tearDown() { @@ -32,647 +40,150 @@ public function tearDown() { /** @var WP_REST_Server $wp_rest_server */ global $wp_rest_server; $wp_rest_server = null; + unset( $this->server ); } - public function test() { + /** + * @return Generator>> + */ + private static function provide_encoded_meta_cases() { + yield 'handle url with white spaces' => array( + 'https://www.example.org/with spaces.htm', + array( + 'https://www.example.org/with spaces.htm', + 'https://www.example.org/with+spaces.htm', + ), + ); - /** @var WP_REST_Server $wp_rest_server */ - global $wp_rest_server; -// var_dump( array_keys( $wp_rest_server->get_routes() ) ); + yield 'handle url with encoded spaces' => array( + 'https://www.abc_example.org/with+spaces.htm', + array( + 'https://www.abc_example.org/with+spaces.htm', + 'https://www.abc_example.org/with spaces.htm', + ), + ); + + yield 'handle url with mixed spaces (encoded or not)' => array( + 'https://www.def_example.org/with+spaces+page.htm', + array( + 'https://www.def_example.org/with+spaces page.htm', + 'https://www.def_example.org/with+spaces+page.htm', + 'https://www.def_example.org/with spaces page.htm', + ), + ); + + yield 'handle url with white space as first character' => array( + ' https://www.ghi_example.org/page.htm', + array( + ' https://www.ghi_example.org/page.htm', + '+https://www.ghi_example.org/page.htm', + ), + ); + + yield 'handle url with encoded space as first character' => array( + '+https://www.lmn_example.org/page.htm', + array( + '+https://www.lmn_example.org/page.htm', + ' https://www.lmn_example.org/page.htm', + ), + ); + + yield 'should avoid to decode query params from url' => array( + 'https://www.opq_example.org/with?encoded=%0A123%24', + array( + 'https://www.opq_example.org/with?encoded=%0A123%24', + ), + ); + + yield 'should avoid to decode whitespaces as query params' => array( + 'https://www.rns_example.org/with_space.htm?a=aaa%20bbb', + array( + 'https://www.rns_example.org/with_space.htm?a=aaa%20bbb', + ), + ); + yield 'should avoid to decode encoded url path' => array( + 'https://www.pqr_example.org/with%20space/url.htm', + array( + 'https://www.pqr_example.org/with%20space/url.htm', + ), + ); + + yield 'should not match a different url' => array( + 'https://www.stu_foobar.org/url.htm', + array( + 'https://www.stu_example.org/url.htm', + ), + false, + ); + } + + public static function provide_encoded_meta() { + // permutate a test case for each of provided query strings + foreach ( self::provide_encoded_meta_cases() as $test_title => $args ) { + list($persisted_value, $search_strings, $should_match) = + // fill the array with null values to ensure that the array has at least 3 elements + array_merge( $args, array_fill( count( $args ), 3, null ) ); + if ( isset( $search_strings ) && is_array( $search_strings ) ) { + $cnt = 0; + foreach ( $search_strings as $search_string ) { + ++$cnt; + $tmp_key = sprintf( '%s - case #%d', $test_title, $cnt ); + yield $tmp_key => array( + $persisted_value, + $search_string, + null !== $should_match ? $should_match : true, + ); + } + } + } } + /** @dataProvider provide_encoded_meta */ + public function test_should_handle_encoded_meta( string $stored_url, string $search_string, bool $should_match ) { + $this->load_fixture( + $stored_url, + $meta_key = self::META_KEY + ); + + $request = new WP_REST_Request( + 'GET', + '/' . WL_REST_ROUTE_DEFAULT_NAMESPACE . '/jsonld/meta/' . rawurlencode( $meta_key ) + ); + $request->set_query_params( + array( + 'meta_value' => $search_string, + ) + ); - // -// /** -// * Test that the JSON-LD is an empty array when no URIs have been provided. -// * -// * @since 3.8.0 -// */ -// public function test_jsonld_no_uris() { -// -// // Set up a default request -// $_GET['action'] = 'wl_jsonld'; -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $jsonld = json_decode( $this->_last_response ); -// $this->assertTrue( is_array( $jsonld ) ); -// $this->assertCount( 0, $jsonld ); -// -// } -// -// /** -// * Test that the JSON-LD. -// * -// * @since 3.8.0 -// */ -// public function test_jsonld() { -// -// // Create a location entity post and bind it to the location property. -// $name = rand_str(); -// $local_business_id = $this->factory()->post->create( array( -// 'post_title' => $name, -// 'post_type' => 'entity', -// ) ); -// Wordlift_Entity_Type_Service::get_instance()->set( $local_business_id, 'http://schema.org/LocalBusiness' ); -// $local_business_type = Wordlift_Entity_Type_Service::get_instance()->get( $local_business_id ); -// $this->assertEquals( 'http://schema.org/LocalBusiness', $local_business_type['uri'] ); -// -// $local_business_uri = $this->entity_service->get_uri( $local_business_id ); -// -// // Set the geo coordinates. -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_GEO_LATITUDE, 12.34 ); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_GEO_LONGITUDE, 1.23 ); -// -// $email = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_EMAIL, $email ); -// -// $phone = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_TELEPHONE, $phone ); -// -// // Set a random sameAs. -// $same_as = 'http://example.org/aRandomSameAs'; -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_SAME_AS, $same_as ); -// -// $street_address = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_ADDRESS, $street_address ); -// -// $po_box = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_ADDRESS_PO_BOX, $po_box ); -// -// $postal_code = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_ADDRESS_POSTAL_CODE, $postal_code ); -// -// $locality = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_ADDRESS_LOCALITY, $locality ); -// -// $region = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_ADDRESS_REGION, $region ); -// -// $country = rand_str(); -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_ADDRESS_COUNTRY, $country ); -// -// $person_id = $this->factory()->post->create( array( 'post_type' => 'entity', ) ); -// Wordlift_Entity_Type_Service::get_instance()->set( $person_id, 'http://schema.org/Person' ); -// -// $person_type = Wordlift_Entity_Type_Service::get_instance()->get( $person_id ); -// $this->assertEquals( 'http://schema.org/Person', $person_type['uri'] ); -// -// $person_uri = $this->entity_service->get_uri( $person_id ); -// -// // Bind the person as author of the creative work. -// add_post_meta( $local_business_id, Wordlift_Schema_Service::FIELD_FOUNDER, $person_id ); -// -// // Set up a default request -// $_GET['action'] = 'wl_jsonld'; -// $_GET['id'] = $local_business_id; -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $response = json_decode( $this->_last_response ); -// -// $this->assertTrue( is_array( $response ) ); -// $this->assertCount( 2, $response, "Expected a `LocalBusiness` and a `Person`." ); -// -// $jsonld_1 = get_object_vars( $response[0] ); -// -// $this->assertTrue( is_string( $jsonld_1['url'] ) -// , "URL must be a string, maybe the response is corrupted:\n" -// . var_export( $response[0], true ) ); -// -// $this->assertTrue( is_array( $jsonld_1 ) ); -// $this->assertArrayHasKey( '@context', $jsonld_1 ); -// $this->assertEquals( 'http://schema.org', $jsonld_1['@context'] ); -// -// $this->assertArrayHasKey( '@id', $jsonld_1 ); -// $this->assertEquals( $local_business_uri, $jsonld_1['@id'] ); -// -// $this->assertArrayHasKey( '@type', $jsonld_1 ); -// $this->assertEquals( 'LocalBusiness', $jsonld_1['@type'] ); -// -// $this->assertArrayHasKey( 'name', $jsonld_1 ); -// $this->assertEquals( $name, $jsonld_1['name'] ); -// -// $this->assertArrayHasKey( 'url', $jsonld_1 ); -// $this->assertEquals( get_permalink( $local_business_id ) -// , $jsonld_1['url'] -// , "Expected:\n" -// . var_export( $jsonld_1['url'], true ) -// . "Received:\n" -// . var_export( get_permalink( $local_business_id ), true ) ); -// -// $this->assertArrayHasKey( 'sameAs', $jsonld_1 ); -// $this->assertEquals( $same_as, $jsonld_1['sameAs'] ); -// -// $this->assertArrayHasKey( 'email', $jsonld_1 ); -// $this->assertEquals( $email, $jsonld_1['email'] ); -// -// $this->assertArrayHasKey( 'telephone', $jsonld_1 ); -// $this->assertEquals( $phone, $jsonld_1['telephone'] ); -// -// $this->assertArrayHasKey( 'geo', $jsonld_1 ); -// -// $geo = get_object_vars( $jsonld_1['geo'] ); -// $this->assertArrayHasKey( '@type', $geo ); -// $this->assertEquals( 'GeoCoordinates', $geo['@type'] ); -// -// $this->assertArrayHasKey( 'latitude', $geo ); -// $this->assertEquals( 12.34, $geo['latitude'] ); -// -// $this->assertArrayHasKey( 'longitude', $geo ); -// $this->assertEquals( 1.23, $geo['longitude'] ); -// -// -// $this->assertArrayHasKey( 'address', $jsonld_1 ); -// -// $address = get_object_vars( $jsonld_1['address'] ); -// $this->assertArrayHasKey( '@type', $address ); -// $this->assertEquals( 'PostalAddress', $address['@type'] ); -// -// $this->assertEquals( $street_address, $address['streetAddress'] ); -// $this->assertEquals( $po_box, $address['postOfficeBoxNumber'] ); -// $this->assertEquals( $postal_code, $address['postalCode'] ); -// $this->assertEquals( $locality, $address['addressLocality'] ); -// $this->assertEquals( $region, $address['addressRegion'] ); -// $this->assertEquals( $country, $address['addressCountry'] ); -// -// $this->assertArrayHasKey( 'founder', $jsonld_1 ); -// -// $founder = get_object_vars( $jsonld_1['founder'] ); -// $this->assertArrayHasKey( '@id', $founder ); -// $this->assertEquals( $person_uri, $founder['@id'] ); -// -// -// $jsonld_2 = get_object_vars( $response[1] ); -// -// $this->assertTrue( is_array( $jsonld_2 ) ); -// $this->assertArrayHasKey( '@context', $jsonld_2 ); -// $this->assertEquals( 'http://schema.org', $jsonld_2['@context'] ); -// -// $this->assertArrayHasKey( '@id', $jsonld_2 ); -// $this->assertEquals( $person_uri, $jsonld_2['@id'] ); -// -// $this->assertArrayHasKey( '@type', $jsonld_2 ); -// $this->assertEquals( 'Person', $jsonld_2['@type'] ); -// -// $this->assertArrayHasKey( 'name', $jsonld_2 ); -// -// $this->assertArrayHasKey( 'url', $jsonld_2 ); -// $this->assertEquals( get_permalink( $person_id ), $jsonld_2['url'] ); -// -// } -// -// /** -// * Test JSON-LD WebSite. -// * -// * @since 3.14.0 -// */ -// public function test_jsonld_website() { -// $name = rand_str(); -// $description = rand_str(); -// -// // Set publisher. -// $publisher = $this->entity_factory->create_and_get(); -// Wordlift_Entity_Type_Service::get_instance()->set( $publisher->ID, 'http://schema.org/Person' ); -// $publisher_uri = $this->entity_service->get_uri( $publisher->ID ); -// Wordlift_Configuration_Service::get_instance()->set_publisher_id( $publisher->ID ); -// -// // Create homepage -// $homepage_id = $this->factory->post->create( array( -// 'post_title' => $name, -// 'post_type' => 'page', -// ) ); -// -// // Set our page as homepage & update the site description -// update_option( 'show_on_front', 'page' ); -// update_option( 'page_on_front', $homepage_id ); -// update_option( 'blogdescription', $description ); -// -// // Get site info -// $name = get_bloginfo( 'name' ); -// $alternate_name = get_bloginfo( 'description' ); -// $url = home_url( '/' ); -// $target = $url . '?s={search_term_string}'; -// -// // Set up a default request -// $_GET['action'] = 'wl_jsonld'; -// $_GET['id'] = $homepage_id; -// $_GET['homepage'] = 'true'; -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// // Get response -// $response = json_decode( $this->_last_response, 1 ); -// -// -// $this->assertTrue( is_array( $response ) ); -// -// $this->assertArrayHasKey( '@context', $response ); -// $this->assertEquals( 'http://schema.org', $response['@context'] ); -// -// $this->assertArrayHasKey( '@type', $response ); -// $this->assertEquals( 'WebSite', $response['@type'] ); -// -// $this->assertArrayHasKey( 'alternateName', $response ); -// $this->assertEquals( $alternate_name, $response['alternateName'] ); -// -// $this->assertArrayHasKey( 'name', $response ); -// $this->assertEquals( $name, $response['name'] ); -// -// $this->assertArrayHasKey( 'url', $response ); -// $this->assertEquals( $url, $response['url'] ); -// -// // Get potentital action -// $potential_action = $response['potentialAction']; -// -// $this->assertArrayHasKey( '@type', $potential_action ); -// $this->assertEquals( 'SearchAction', $potential_action['@type'] ); -// -// $this->assertArrayHasKey( 'target', $potential_action ); -// $this->assertEquals( $target, $potential_action['target'] ); -// -// // Check the publisher. -// $this->assertCount( 3, $response['publisher'] ); -// $this->assertEquals( 'Person', $response['publisher']['@type'] ); -// $this->assertEquals( $publisher_uri, $response['publisher']['@id'] ); -// $this->assertEquals( $publisher->post_title, $response['publisher']['name'] ); -// -// } -// -// /** -// * Test that disable website filter is working. -// * -// * @since 3.14.0 -// */ -// public function test_disable_jsonld_website() { -// $name = rand_str(); -// $description = rand_str(); -// -// // Create homepage -// $homepage_id = $this->factory->post->create( array( -// 'post_title' => $name, -// 'post_type' => 'page', -// ) ); -// -// // Get url -// $home_uri = $this->entity_service->get_uri( $homepage_id ); -// -// // Set publisher. -// $publisher = $this->entity_factory->create_and_get(); -// Wordlift_Entity_Type_Service::get_instance()->set( $publisher->ID, 'http://schema.org/Organization' ); -// $publisher_uri = $this->entity_service->get_uri( $publisher->ID ); -// Wordlift_Configuration_Service::get_instance()->set_publisher_id( $publisher->ID ); -// -// // Set our page as homepage & update the site description -// update_option( 'show_on_front', 'page' ); -// update_option( 'page_on_front', $homepage_id ); -// update_option( 'blogdescription', $description ); -// -// // Get site info -// $headline = get_bloginfo( 'name' ); -// $description = get_bloginfo( 'description' ); -// $url = home_url( '/' ); -// $target = $url . '?s={search_term_string}'; -// -// // Set up a default request -// $_GET['action'] = 'wl_jsonld'; -// $_GET['id'] = $homepage_id; -// $_GET['homepage'] = 'true'; -// -// // Diable WebSite schema -// add_filter( 'wordlift_disable_website_json_ld', '__return_true' ); -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $response = json_decode( $this->_last_response ); -// -// $this->assertTrue( is_array( $response ) ); -// -// $this->assertCount( 1, $response ); -// -// $jsonld = get_object_vars( $response[0] ); -// -// $this->assertTrue( is_array( $jsonld ) ); -// -// $this->assertArrayHasKey( '@context', $jsonld ); -// $this->assertEquals( 'http://schema.org', $jsonld['@context'] ); -// -// $this->assertArrayHasKey( '@id', $jsonld ); -// $this->assertEquals( $home_uri, $jsonld['@id'] ); -// -// $this->assertArrayHasKey( '@type', $jsonld ); -// $this->assertNotEquals( 'WebSite', $jsonld['@type'] ); -// -// $this->assertArrayHasKey( 'description', $jsonld ); -// $this->assertNotEquals( $description, $jsonld['description'] ); -// -// $this->assertArrayHasKey( 'headline', $jsonld ); -// $this->assertNotEquals( $headline, $jsonld['headline'] ); -// -// $publisher_2 = get_object_vars( $jsonld['publisher'] ); -// -// // Check the publisher. -// $this->assertCount( 3, $publisher_2 ); -// $this->assertEquals( 'Organization', $publisher_2['@type'] ); -// $this->assertEquals( $publisher_uri, $publisher_2['@id'] ); -// $this->assertEquals( $publisher->post_title, $publisher_2['name'] ); -// } -// -// /** -// * Test that the JSON-LD WebSite works even without homepage. -// * -// * @since 3.14.0 -// */ -// public function test_jsonld_website_without_homepage() { -// $description = rand_str(); -// -// // Set our page as homepage & update the site description -// update_option( 'blogdescription', $description ); -// -// // Set publisher. -// $publisher = $this->entity_factory->create_and_get(); -// Wordlift_Entity_Type_Service::get_instance()->set( $publisher->ID, 'http://schema.org/Organization' ); -// $publisher_uri = $this->entity_service->get_uri( $publisher->ID ); -// Wordlift_Configuration_Service::get_instance()->set_publisher_id( $publisher->ID ); -// -// // Get site info -// $headline = get_bloginfo( 'name' ); -// $description = get_bloginfo( 'description' ); -// $url = home_url( '/' ); -// $target = $url . '?s={search_term_string}'; -// -// $_GET['action'] = 'wl_jsonld'; -// $_GET['homepage'] = 'true'; -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $response = json_decode( $this->_last_response, 1 ); -// -// $this->assertTrue( is_array( $response ) ); -// -// $this->assertArrayHasKey( '@context', $response ); -// $this->assertEquals( 'http://schema.org', $response['@context'] ); -// -// $this->assertArrayHasKey( '@type', $response ); -// $this->assertEquals( 'WebSite', $response['@type'] ); -// -// $this->assertArrayHasKey( 'alternateName', $response ); -// $this->assertEquals( $description, $response['alternateName'] ); -// -// $this->assertArrayHasKey( 'name', $response ); -// $this->assertEquals( $headline, $response['name'] ); -// -// $this->assertArrayHasKey( 'url', $response ); -// $this->assertEquals( $url, $response['url'] ); -// -// $potential_action = $response['potentialAction']; -// -// $this->assertArrayHasKey( '@type', $potential_action ); -// $this->assertEquals( 'SearchAction', $potential_action['@type'] ); -// -// $this->assertArrayHasKey( 'target', $potential_action ); -// $this->assertEquals( $target, $potential_action['target'] ); -// -// $this->assertArrayHasKey( 'target', $potential_action ); -// $this->assertEquals( $target, $potential_action['target'] ); -// -// // Check the publisher. -// $this->assertCount( 3, $response['publisher'] ); -// $this->assertEquals( 'Organization', $response['publisher']['@type'] ); -// $this->assertEquals( $publisher_uri, $response['publisher']['@id'] ); -// $this->assertEquals( $publisher->post_title, $response['publisher']['name'] ); -// } -// -// /** -// * Test that the JSON-LD WebSite search_url filter is working. -// * -// * @since 3.14.0 -// */ -// public function test_change_jsonld_website_search_target() { -// $name = rand_str(); -// $description = rand_str(); -// -// // Create homepage -// $homepage_id = $this->factory->post->create( array( -// 'post_title' => $name, -// 'post_type' => 'page', -// ) ); -// -// // Set publisher. -// $publisher = $this->entity_factory->create_and_get(); -// Wordlift_Entity_Type_Service::get_instance()->set( $publisher->ID, 'http://schema.org/Person' ); -// $publisher_uri = $this->entity_service->get_uri( $publisher->ID ); -// Wordlift_Configuration_Service::get_instance()->set_publisher_id( $publisher->ID ); -// -// // Set our page as homepage & update the site description -// update_option( 'show_on_front', 'page' ); -// update_option( 'page_on_front', $homepage_id ); -// update_option( 'blogdescription', $description ); -// -// // Get site info -// $headline = get_bloginfo( 'name' ); -// $description = get_bloginfo( 'description' ); -// $url = home_url( '/' ); -// $target = $url . '?s={search_term_string}'; -// -// // Change the search target -// $modified_target = str_replace( '{search_term_string}', '', $target ); -// -// $_GET['action'] = 'wl_jsonld'; -// $_GET['id'] = $homepage_id; -// $_GET['homepage'] = true; -// -// add_filter( 'wl_jsonld_search_url', array( -// $this, -// 'change_search_url', -// ) ); -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $response = json_decode( $this->_last_response, 1 ); -// -// $this->assertTrue( is_array( $response ) ); -// -// $this->assertArrayHasKey( '@context', $response ); -// $this->assertEquals( 'http://schema.org', $response['@context'] ); -// -// $this->assertArrayHasKey( '@type', $response ); -// $this->assertEquals( 'WebSite', $response['@type'] ); -// -// $this->assertArrayHasKey( 'alternateName', $response ); -// $this->assertEquals( $description, $response['alternateName'] ); -// -// $this->assertArrayHasKey( 'name', $response ); -// $this->assertEquals( $headline, $response['name'] ); -// -// $this->assertArrayHasKey( 'url', $response ); -// $this->assertEquals( $url, $response['url'] ); -// -// $potential_action = $response['potentialAction']; -// -// $this->assertArrayHasKey( '@type', $potential_action ); -// $this->assertEquals( 'SearchAction', $potential_action['@type'] ); -// -// $this->assertArrayHasKey( 'target', $potential_action ); -// $this->assertNotEquals( $target, $potential_action['target'] ); -// -// $this->assertArrayHasKey( 'target', $potential_action ); -// $this->assertEquals( $modified_target, $potential_action['target'] ); -// -// // Check the publisher. -// $this->assertCount( 3, $response['publisher'] ); -// $this->assertEquals( 'Person', $response['publisher']['@type'] ); -// $this->assertEquals( $publisher_uri, $response['publisher']['@id'] ); -// $this->assertEquals( $publisher->post_title, $response['publisher']['name'] ); -// } -// -// public function test_jsonld_with_html_entities() { -// $name = 'Wordlift\'s blog'; -// $description = 'Sample description" with\'s single\'s quote'; -// -// // Set our page as homepage & update the site description -// update_option( 'blogdescription', $description ); -// update_option( 'blogname', $name ); -// -// // Set up a default request -// $_GET['action'] = 'wl_jsonld'; -// $_GET['homepage'] = 'true'; -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $response = json_decode( $this->_last_response, 1 ); -// -// $this->assertArrayHasKey( 'name', $response ); -// $this->assertEquals( $name, $response['name'] ); -// -// $this->assertArrayHasKey( 'alternateName', $response ); -// $this->assertEquals( $description, $response['alternateName'] ); -// -// } -// -// public function test_jsonld_with_diacritics() { -// $name = 'àüé'; -// $description = 'Sample description" with\'s single\'s quote'; -// -// // Set our page as homepage & update the site description -// update_option( 'blogdescription', $description ); -// update_option( 'blogname', $name ); -// -// // Set up a default request -// $_GET['action'] = 'wl_jsonld'; -// $_GET['homepage'] = 'true'; -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $response = json_decode( $this->_last_response, 1 ); -// -// $this->assertArrayHasKey( 'name', $response ); -// $this->assertEquals( $name, $response['name'] ); -// -// $this->assertArrayHasKey( 'alternateName', $response ); -// $this->assertEquals( $description, $response['alternateName'] ); -// -// } -// -// /** -// * Test the filter `wl_jsonld_search_url`. -// * -// * @param string $url The default URL. -// * -// * @return string A modified URL. -// * @since 3.14.0 -// * -// */ -// public function change_search_url( $url ) { -// return str_replace( '{search_term_string}', '', $url ); -// } -// -// /** -// * Test a recipe mentioned in a post. -// * -// * @since 3.14.1 -// */ -// public function test_post_mentioning_a_recipe() { -// -// $post_id = $this->factory->post->create( array( -// 'type' => 'post', -// 'post_status' => 'publish', -// ) ); -// -// $recipe_post_id = $this->entity_factory->create( array( -// 'post_status' => 'publish', -// ) ); -// Wordlift_Entity_Type_Service::get_instance()->set( $recipe_post_id, 'http://schema.org/Recipe' ); -// -// wl_core_add_relation_instance( $post_id, WL_WHAT_RELATION, $recipe_post_id ); -// -// // Set up a default request -// $_GET['action'] = 'wl_jsonld'; -// $_GET['id'] = $post_id; -// -// // Make the request -// try { -// $this->_handleAjax( 'wl_jsonld' ); -// } catch ( WPAjaxDieContinueException $e ) { -// unset( $e ); -// } -// -// $response = json_decode( $this->_last_response ); -// -// // Check that the recipe is there. -// $instances = array_filter( $response, function ( $item ) { -// return 'Recipe' === $item->{'@type'}; -// } ); -// -// $this->assertCount( 1, $instances ); -// -// } -// -// public function test_register_routes() { -// // TODO: Implement test_register_routes() method. -// } -// + $response = $this->server->dispatch( $request ); + self::assertSame( 200, $response->get_status() ); + $data = $response->get_data(); + self::assertIsArray( $data ); + if ( false === $should_match ) { + self::assertEmpty( $data ); + } else { + self::assertCount( 1, $data, 'Unable to find the expected data in the response' ); + $actual_content = &$data[0]; + self::assertNotNull( $actual_content ); + self::assertArrayHasKey( '@id', $actual_content ); + } + } + + /** + * @param string $url + * @param string $meta_key + * @return void + */ + private function load_fixture( $url, $meta_key ) { + $post_id = $this->factory()->post->create( + array( + 'post_status' => 'publish', + ) + ); + + add_post_meta( $post_id, $meta_key, $url ); + } }