From e3d26fc949ff5e1bb12cb64c756b166d41690868 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 20 Oct 2025 14:08:02 +0200 Subject: [PATCH 001/319] Adds initial route and cli command and returns the schema of the first 100 indexables. --- .../aggregate-site-schema-command-handler.php | 60 ++++++++ .../aggregate-site-schema-command.php | 38 +++++ .../domain/page-controls.php | 52 +++++++ .../infrastructure/config.php | 41 +++++ .../site-schema-json-conditional.php | 37 +++++ .../site-schema-aggregator-cli-command.php | 104 +++++++++++++ .../site-schema-aggregator-route.php | 145 ++++++++++++++++++ src/repositories/indexable-repository.php | 21 +++ 8 files changed, 498 insertions(+) create mode 100644 src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php create mode 100644 src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php create mode 100644 src/nlweb/schema-aggregator/domain/page-controls.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/config.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/site-schema-json-conditional.php create mode 100644 src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php create mode 100644 src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php new file mode 100644 index 00000000000..ae536e5b248 --- /dev/null +++ b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -0,0 +1,60 @@ +indexable_repository = $indexable_repository; + $this->meta_tags_context_memoizer = $meta_tags_context_memoizer; + } + + /** + * Handles the Aggregate_Site_Schema_Command. + * + * @param Aggregate_Site_Schema_Command $command The command. + * + * @return array The aggregated schema. + */ + public function handle( Aggregate_Site_Schema_Command $command ): array { + + $indexables = $this->indexable_repository->find_all_public_paginated( + $command->get_page_controls()->get_page(), + $command->get_page_controls()->get_page_size() + ); + + // This part should be replaced by the rest of the system. + $schema = []; + foreach ( $indexables as $indexable ) { + $schema[] = $this->meta_tags_context_memoizer->get( $indexable, $indexable->object_sub_type )->presentation->schema; + } + return $schema; + } +} diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php new file mode 100644 index 00000000000..42411ba5cf4 --- /dev/null +++ b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php @@ -0,0 +1,38 @@ +page_controls = new Page_Controls( $page, $per_page ); + } + + /** + * Gets the page controls. + * + * @return Page_Controls + */ + public function get_page_controls(): Page_Controls { + return $this->page_controls; + } +} diff --git a/src/nlweb/schema-aggregator/domain/page-controls.php b/src/nlweb/schema-aggregator/domain/page-controls.php new file mode 100644 index 00000000000..c3eaafcede2 --- /dev/null +++ b/src/nlweb/schema-aggregator/domain/page-controls.php @@ -0,0 +1,52 @@ +page = $page; + $this->page_size = $page_size; + } + + /** + * Gets the current page. + * + * @return int + */ + public function get_page(): int { + return $this->page; + } + + /** + * Gets the page size. + * + * @return int + */ + public function get_page_size(): int { + return $this->page_size; + } +} diff --git a/src/nlweb/schema-aggregator/infrastructure/config.php b/src/nlweb/schema-aggregator/infrastructure/config.php new file mode 100644 index 00000000000..3a881a94eea --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/config.php @@ -0,0 +1,41 @@ +options = $options; + } + + /** + * Returns whether the 'Site schema route' setting has been enabled. + * + * @return bool `true` when the 'Site schema route' setting has been enabled. + */ + public function is_met() { + return true; + } +} diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php new file mode 100644 index 00000000000..ca780436075 --- /dev/null +++ b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php @@ -0,0 +1,104 @@ +config = $config; + $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; + } + + /** + * Returns the namespace of this command. + * + * @return string + */ + public static function get_namespace() { + return Main::WP_CLI_NAMESPACE; + } + + /** + * Aggregates the schema for a certain site. + * + * ## OPTIONS + * + * [--page=] + * : The current page to process. + * --- + * default: 1 + * --- + * + * [--per_page=] + * : How many items to process per page. + * --- + * default: 100 + + * ## EXAMPLES + * + * wp yoast aggregate_site_schema + * + * @when after_wp_load + * + * @param array|null $args The arguments. + * @param array|null $assoc_args The associative arguments. + * + * @return void + * + * @throws ExitException When the input args are invalid. + */ + public function aggregate_site_schema( $args = null, $assoc_args = null ) { + if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] < 1 ) { + WP_CLI::error( \__( 'The value for \'page\' must be a positive integer higher than equal to 1.', 'wordpress-seo' ) ); + } + if ( isset( $assoc_args['per_page'] ) && (int) $assoc_args['per_page'] < 1 ) { + WP_CLI::error( \__( 'The value for \'per_page\' must be a positive integer higher than equal to 1.', 'wordpress-seo' ) ); + } + $page = (int) $assoc_args['page']; + $per_page = (int) $assoc_args['per_page']; + try { + $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); + } catch ( Exception $exception ) { + WP_CLI::error( \__( 'An error occurred while aggregating the site schema.', 'wordpress-seo' ) ); + } + $output = WPSEO_Utils::format_json_encode( $result ); + $output = \str_replace( "\n", \PHP_EOL . "\t", $output ); + WP_CLI::log( + $output + ); + } +} diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php new file mode 100644 index 00000000000..1dc5208c248 --- /dev/null +++ b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -0,0 +1,145 @@ + The conditionals that must be met to load this. + */ + public static function get_conditionals() { + return [ Site_Schema_Json_Conditional::class ]; + } + + /** + * Site_Schema_Aggregator_Route constructor. + * + * @param Config $config The config object. + * @param Capability_Helper $capability_helper The capability helper. + * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler. + */ + public function __construct( Config $config, Capability_Helper $capability_helper, Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler ) { + $this->config = $config; + $this->capability_helper = $capability_helper; + $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; + } + + /** + * Registers routes with WordPress. + * + * @return void + */ + public function register_routes() { + $schema_aggregator_route = [ + 'methods' => 'GET', + 'callback' => [ $this, 'aggregate_site_schema' ], + 'permission_callback' => [ $this, 'get_permission_callback' ], + 'args' => [ + 'page' => [ + 'default' => 1, + 'validate_callback' => static function ( $param ) { + return \is_numeric( $param ) && $param > 0; + }, + 'sanitize_callback' => 'absint', + ], + 'per_page' => [ + 'default' => $this->config->get_per_page(), + 'validate_callback' => function ( $param ) { + return \is_numeric( $param ) && $param > 0 && $param <= $this->config->get_per_page_max(); + }, + 'sanitize_callback' => 'absint', + ], + ], + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE, $schema_aggregator_route ); + } + + /** + * Permission callback for the route. + * + * @return bool True if the user has permission, false otherwise. + */ + public function get_permission_callback(): bool { + return true; + } + + /** + * Returns a JSON representation of a site. + * + * @param WP_REST_Request $request The request object. + * + * @return WP_REST_Response|WP_Error The success or failure response. + */ + public function aggregate_site_schema( WP_REST_Request $request ) { + $page = $request->get_param( 'page' ); + $per_page = $request->get_param( 'per_page' ); + + try { + $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); + } catch ( Exception $exception ) { + return new WP_Error( + 'wpseo_aggregate_site_schema_error', + $exception->getMessage(), + (object) [] + ); + } + $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); + return new WP_REST_Response( + $output, + ( $result ) ? 200 : 400 + ); + } +} diff --git a/src/repositories/indexable-repository.php b/src/repositories/indexable-repository.php index cedab5852f1..9ccc1d8b877 100644 --- a/src/repositories/indexable-repository.php +++ b/src/repositories/indexable-repository.php @@ -216,6 +216,27 @@ public function find_all_with_type_and_sub_type( $object_type, $object_sub_type return \array_map( [ $this, 'upgrade_indexable' ], $indexables ); } + /** + * Retrieves a paginated set of indexable instances of public indexables. + * + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * @param array $post_type_exclude_list Post types to ignore (can be empty). + * + * @return Indexable[] The array with the paginated indexable instances which are public. + */ + public function find_all_public_paginated( $page, $page_size, $post_type_exclude_list = [] ): array { + $offset = ( ( $page - 1 ) * $page_size ); + + $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + if ( $post_type_exclude_list ) { + $query->where_not_in( 'object_sub_type', $post_type_exclude_list ); + } + $indexables = $query->order_by_asc( 'id' )->limit( $page_size )->offset( $offset )->find_many(); + + return \array_map( [ $this, 'upgrade_indexable' ], $indexables ); + } + /** * Retrieves the homepage indexable. * From fc838f51470116624a3a2ab99a19196d9c6dfeb1 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 20 Oct 2025 14:48:28 +0200 Subject: [PATCH 002/319] Add additional class to abstract the place to get the collector --- .../aggregate-site-schema-command-handler.php | 19 ++++---- .../to-aggregate-indexable-collector.php | 44 +++++++++++++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php index ae536e5b248..a171a45f09e 100644 --- a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application; use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; +use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\To_Aggregate_Indexable_Collector; use Yoast\WP\SEO\Repositories\Indexable_Repository; /** @@ -12,11 +13,11 @@ class Aggregate_Site_Schema_Command_Handler { /** - * Represents the indexable repository. + * The To_Aggregate_Indexable_Collector instance. * - * @var Indexable_Repository + * @var To_Aggregate_Indexable_Collector */ - private $indexable_repository; + private $to_aggregate_indexable_collector; /** * Represents the meta tags memoizer. @@ -28,12 +29,12 @@ class Aggregate_Site_Schema_Command_Handler { /** * Aggregate_Site_Schema_Command_Handler constructor. * - * @param Indexable_Repository $indexable_repository The indexable repository. - * @param Meta_Tags_Context_Memoizer $meta_tags_context_memoizer The meta tags context memoizer. + * @param To_Aggregate_Indexable_Collector $to_aggregate_indexable_collector The collector of indexables that need to be aggregated. + * @param Meta_Tags_Context_Memoizer $meta_tags_context_memoizer The meta tags context memoizer. */ - public function __construct( Indexable_Repository $indexable_repository, Meta_Tags_Context_Memoizer $meta_tags_context_memoizer ) { - $this->indexable_repository = $indexable_repository; - $this->meta_tags_context_memoizer = $meta_tags_context_memoizer; + public function __construct( To_Aggregate_Indexable_Collector $to_aggregate_indexable_collector, Meta_Tags_Context_Memoizer $meta_tags_context_memoizer ) { + $this->to_aggregate_indexable_collector = $to_aggregate_indexable_collector; + $this->meta_tags_context_memoizer = $meta_tags_context_memoizer; } /** @@ -45,7 +46,7 @@ public function __construct( Indexable_Repository $indexable_repository, Meta_Ta */ public function handle( Aggregate_Site_Schema_Command $command ): array { - $indexables = $this->indexable_repository->find_all_public_paginated( + $indexables = $this->to_aggregate_indexable_collector->get( $command->get_page_controls()->get_page(), $command->get_page_controls()->get_page_size() ); diff --git a/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php b/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php new file mode 100644 index 00000000000..fecad592e0e --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php @@ -0,0 +1,44 @@ +indexable_repository = $indexable_repository; + } + + /** + * Handles the Aggregate_Site_Schema_Command. + * + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * + * @return array The aggregated schema. + */ + public function get( $page, $page_size ): array { + + return $this->indexable_repository->find_all_public_paginated( + $page, + $page_size, + ); + } +} From cb8afd25ad111dd84d4d62c5df77b4b3bc5a3473 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 21 Oct 2025 09:47:57 +0200 Subject: [PATCH 003/319] Start of very basic caching --- .../application/cache/manager.php | 280 ++++++++++++++++++ .../site-schema-aggregator-route.php | 1 + 2 files changed, 281 insertions(+) create mode 100644 src/nlweb/schema-aggregator/application/cache/manager.php diff --git a/src/nlweb/schema-aggregator/application/cache/manager.php b/src/nlweb/schema-aggregator/application/cache/manager.php new file mode 100644 index 00000000000..1d82e268d75 --- /dev/null +++ b/src/nlweb/schema-aggregator/application/cache/manager.php @@ -0,0 +1,280 @@ +config = $config; + } + + /** + * Get cached data for a page + * + * @param int $page Page number. + * @param int $per_page Items per page. + * + * @return array|null Cached data or null. + */ + public function get( int $page, int $per_page ): ?array { + try { + // Validate input + if ( $page < 1 ) { + error_log( "Yoast NLWeb Cache: Invalid page number: {$page}" ); + + return null; + } + + if ( $per_page < 1 ) { + error_log( "Yoast NLWeb Cache: Invalid per_page number: {$per_page}" ); + + return null; + } + + $key = $this->get_cache_key( $page, $per_page ); + + // get_transient can fail in various ways + $data = get_transient( $key ); + + if ( $data === false ) { + return null; + } + + // Validate cached data structure + if ( ! is_array( $data ) ) { + error_log( "Yoast NLWeb Cache: Cached data for page {$page} is not an array, invalidating" ); + delete_transient( $key ); + + return null; + } + + return $data; + + } catch ( \Exception $e ) { + error_log( "Yoast NLWeb Cache: Error getting cache for page {$page}: " . $e->getMessage() ); + + return null; + } + } + + /** + * Set cache data for a page + * + * @param int $page Page number. + * @param int $per_page Items per page. + * @param array $data Data to cache. + * + * @return bool Success. + */ + public function set( int $page, int $per_page, array $data ): bool { + try { + // Validate inputs + if ( $page < 1 || $per_page < 1 || ! is_array( $data ) ) { + return false; + } + + $key = $this->get_cache_key( $page, $per_page ); + $expiration = $this->get_expiration( $data ); + + $result = set_transient( $key, $data, $expiration ); + + if ( ! $result ) { + error_log( "Yoast NLWeb Cache: Failed to set transient for page {$page}" ); + } + + return $result; + + } catch ( \Exception $e ) { + error_log( "Yoast NLWeb Cache: Error setting cache for page {$page}: " . $e->getMessage() ); + + return false; + } + } + + /** + * Invalidate cache for specific page/per_page combination or all pages + * + * Note: When invalidating a specific page without per_page, this clears + * ALL per_page variations for that page using a wildcard pattern. + * + * @param int|null $page Page number or null for all. + * @param int|null $per_page Items per page or null to clear all per_page variations. + * + * @return bool Success. + */ + public function invalidate( ?int $page = null, ?int $per_page = null ): bool { + if ( $page !== null && $per_page !== null ) { + // Clear specific page/per_page combination + return delete_transient( $this->get_cache_key( $page, $per_page ) ); + } + + if ( $page !== null && $per_page === null ) { + // Clear all per_page variations for this page + global $wpdb; + + if ( ! isset( $wpdb ) || ! is_object( $wpdb ) ) { + error_log( 'Yoast NLWeb Cache: $wpdb is not available for invalidate' ); + + return false; + } + + $pattern = '_transient_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; + $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; + + $deleted = $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + $pattern, + $timeout_pattern + ) + ); + + return $deleted !== false; + } + + // Clear everything + return $this->invalidate_all(); + } + + /** + * Invalidate all cache pages + * + * TODO: Implement incremental cache updates (v2 feature) instead of full regeneration + * + * @return bool Success. + */ + public function invalidate_all(): bool { + try { + global $wpdb; + + // Validate wpdb is available + if ( ! isset( $wpdb ) || ! is_object( $wpdb ) ) { + error_log( 'Yoast NLWeb Cache: $wpdb is not available for invalidate_all' ); + + return false; + } + + // Delete all transients matching our pattern + // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version} + $pattern = '_transient_' . self::CACHE_PREFIX . '_page_%'; + $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_%'; + + $deleted = $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + $pattern, + $timeout_pattern + ) + ); + + if ( $deleted === false ) { + error_log( 'Yoast NLWeb Cache: Database query failed in invalidate_all' ); + if ( ! empty( $wpdb->last_error ) ) { + error_log( 'Yoast NLWeb Cache: Database error: ' . $wpdb->last_error ); + } + + return false; + } + + return true; + + } catch ( \Exception $e ) { + error_log( 'Yoast NLWeb Cache: Error in invalidate_all: ' . $e->getMessage() ); + + return false; + } + } + + /** + * Generate cache key for page + * + * @param int $page Page number. + * @param int $per_page Items per page. + * + * @return string Cache key. + */ + private function get_cache_key( int $page, int $per_page ): string { + return sprintf( + '%s_page_%d_per_%d_v%d', + self::CACHE_PREFIX, + $page, + $per_page, + self::CACHE_VERSION + ); + } + + /** + * Get expiration time based on data size + * + * @param array $data Data to cache. + * + * @return int Expiration in seconds. + */ + private function get_expiration( array $data ): int { + try { + // Attempt to serialize to calculate size + // This can fail with circular references or exceed memory + $serialized = serialize( $data ); + + if ( $serialized === false ) { + error_log( 'Yoast NLWeb Cache: Failed to serialize data for expiration calculation' ); + + return HOUR_IN_SECONDS; // Default + } + + $size = strlen( $serialized ); + + // Large payloads: cache longer + if ( $size > 1048576 ) { // > 1MB + return 6 * HOUR_IN_SECONDS; + } + + // Small payloads: cache shorter + if ( $size < 102400 ) { // < 100KB + return 30 * MINUTE_IN_SECONDS; + } + + // Default: 1 hour + return HOUR_IN_SECONDS; + + } catch ( \Exception $e ) { + error_log( 'Yoast NLWeb Cache: Error calculating expiration: ' . $e->getMessage() ); + + return HOUR_IN_SECONDS; // Safe default + } + } +} diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php index 1dc5208c248..112c5c72980 100644 --- a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -137,6 +137,7 @@ public function aggregate_site_schema( WP_REST_Request $request ) { ); } $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); + return new WP_REST_Response( $output, ( $result ) ? 200 : 400 From 08320c568cf55388e4dde45e467d6a65c003e0de Mon Sep 17 00:00:00 2001 From: Thijs van der Heijden Date: Tue, 21 Oct 2025 09:51:22 +0200 Subject: [PATCH 004/319] Apply suggestions from code review Co-authored-by: Paolo L. Scala <68744851+pls78@users.noreply.github.com> --- .../application/aggregate-site-schema-command-handler.php | 3 +-- .../infrastructure/to-aggregate-indexable-collector.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php index a171a45f09e..bb053b84a7c 100644 --- a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -5,7 +5,6 @@ use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\To_Aggregate_Indexable_Collector; -use Yoast\WP\SEO\Repositories\Indexable_Repository; /** * Class that handles the Aggregate_Site_Schema_Command. @@ -22,7 +21,7 @@ class Aggregate_Site_Schema_Command_Handler { /** * Represents the meta tags memoizer. * - * @var Indexable_Repository + * @var Meta_Tags_Context_Memoizer */ protected $meta_tags_context_memoizer; diff --git a/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php b/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php index fecad592e0e..6d166aafedb 100644 --- a/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php +++ b/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php @@ -27,7 +27,7 @@ public function __construct( Indexable_Repository $indexable_repository ) { } /** - * Handles the Aggregate_Site_Schema_Command. + * Gets the indexables to be aggregated. * * @param int $page The page number (1-based). * @param int $page_size The number of items per page. From a9621d899bae49cfaf20568107e98c31c56e5b8a Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 21 Oct 2025 09:52:21 +0200 Subject: [PATCH 005/319] update name. --- .../user-interface/site-schema-aggregator-route.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php index 1dc5208c248..f945146fa1d 100644 --- a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -97,7 +97,7 @@ public function register_routes() { 'per_page' => [ 'default' => $this->config->get_per_page(), 'validate_callback' => function ( $param ) { - return \is_numeric( $param ) && $param > 0 && $param <= $this->config->get_per_page_max(); + return \is_numeric( $param ) && $param > 0 && $param <= $this->config->get_max_per_page(); }, 'sanitize_callback' => 'absint', ], From ac7eb50908cf1b727c1ad543b043cf437348ea3f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 21 Oct 2025 15:54:45 +0200 Subject: [PATCH 006/319] Fix method name --- src/nlweb/schema-aggregator/infrastructure/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nlweb/schema-aggregator/infrastructure/config.php b/src/nlweb/schema-aggregator/infrastructure/config.php index 3a881a94eea..8de05df689f 100644 --- a/src/nlweb/schema-aggregator/infrastructure/config.php +++ b/src/nlweb/schema-aggregator/infrastructure/config.php @@ -35,7 +35,7 @@ public function get_per_page(): int { * * @return int */ - public function get_per_page_max(): int { + public function get_max_per_page(): int { return self::MAX_PER_PAGE; } } From 23940c9b243de28f1332ce9aa86d3ac91cfca8d1 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 20 Oct 2025 15:20:10 +0200 Subject: [PATCH 007/319] Initial commit --- .../application/aggregator.php | 29 ++++++ .../schema-piece-repository-interface.php | 20 ++++ .../schema-aggregator/domain/schema-piece.php | 98 +++++++++++++++++++ .../meta-tags-context-memoizer-adapter.php | 51 ++++++++++ .../schema-piece-repository.php | 84 ++++++++++++++++ 5 files changed, 282 insertions(+) create mode 100644 src/nlweb/schema-aggregator/application/aggregator.php create mode 100644 src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php create mode 100644 src/nlweb/schema-aggregator/domain/schema-piece.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php diff --git a/src/nlweb/schema-aggregator/application/aggregator.php b/src/nlweb/schema-aggregator/application/aggregator.php new file mode 100644 index 00000000000..af90c190bb0 --- /dev/null +++ b/src/nlweb/schema-aggregator/application/aggregator.php @@ -0,0 +1,29 @@ +schema_data_repository = $schema_data_repository; + } +} diff --git a/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php b/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php new file mode 100644 index 00000000000..1b2db475897 --- /dev/null +++ b/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php @@ -0,0 +1,20 @@ + $indexable_ids The indexable IDs. + * + * @return array The schema pieces. + */ + public function get_by_indexable_ids( array $indexable_ids ): array; +} diff --git a/src/nlweb/schema-aggregator/domain/schema-piece.php b/src/nlweb/schema-aggregator/domain/schema-piece.php new file mode 100644 index 00000000000..a6162f1b321 --- /dev/null +++ b/src/nlweb/schema-aggregator/domain/schema-piece.php @@ -0,0 +1,98 @@ + + */ + protected $data; + + /** + * Class constructor. + * + * @param array $data The data of the schema piece. + * @param string $type The type of the schema piece. + */ + public function __construct( array $data, string $type ) { + $this->data = $data; + $this->type = $type; + } + + /** + * Gets the type of the schema piece. + * + * @return string The type of the schema piece. + */ + public function get_type(): string { + return $this->type; + } + + /** + * Gets the data of the schema piece. + * + * @return array The data of the schema piece. + */ + public function get_data(): array { + return $this->data; + } + + /** + * Converts the schema piece to a schema.org array. + * + * @return array The schema.org array representation. + */ + public function to_schema_array(): array { + return [ + '@type' => $this->type, + ...$this->data, + ]; + } + + /** + * Encodes the schema piece in JSON-LD format. + * + * @return string The JSON-LD representation. + */ + public function to_json_ld(): string { + $schema_array = $this->to_schema_array(); + return WPSEO_Utils::format_json_encode( $schema_array ); + } + + /** + * Converts multiple schema pieces to a JSON-LD-encoded graph. + * + * @param Schema_Piece[] $schema_pieces Array of schema pieces. + * @return string The JSON-LD graph representation. + */ + public static function to_json_ld_graph( array $schema_pieces ): string { + $graph = []; + foreach ( $schema_pieces as $piece ) { + if ( $piece instanceof self ) { + $graph[] = $piece->to_schema_array(); + } + } + + $schema_graph = [ + '@context' => 'https://schema.org', + '@graph' => $graph, + ]; + + return WPSEO_Utils::format_json_encode( $schema_graph ); + } +} diff --git a/src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..8af24e381e7 --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php @@ -0,0 +1,51 @@ + The meta tags context as an array. + */ + public function meta_tags_context_to_array( Meta_Tags_Context $context ): array { + return [ + 'canonical' => $context->canonical, + 'permalink' => $context->permalink, + 'title' => $context->title, + 'description' => $context->description, + 'id' => $context->id, + 'site_name' => $context->site_name, + 'alternate_site_name' => $context->alternate_site_name, + 'wordpress_site_name' => $context->wordpress_site_name, + 'site_url' => $context->site_url, + 'company_name' => $context->company_name, + 'company_alternate_name' => $context->company_alternate_name, + 'company_logo_id' => $context->company_logo_id, + 'company_logo_meta' => $context->company_logo_meta, + 'person_logo_id' => $context->person_logo_id, + 'person_logo_meta' => $context->person_logo_meta, + 'site_user_id' => $context->site_user_id, + 'site_represents' => $context->site_represents, + 'site_represents_reference' => $context->site_represents_reference, + 'schema_page_type' => $context->schema_page_type, + 'schema_article_type' => $context->schema_article_type, + 'main_schema_id' => $context->main_schema_id, + 'main_entity_of_page' => $context->main_entity_of_page, + 'open_graph_enabled' => $context->open_graph_enabled, + 'open_graph_publisher' => $context->open_graph_publisher, + 'twitter_card' => $context->twitter_card, + 'page_type' => $context->page_type, + 'has_article' => $context->has_article, + 'has_image' => $context->has_image, + 'main_image_id' => $context->main_image_id, + 'main_image_url' => $context->main_image_url, + ]; + } +} diff --git a/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php new file mode 100644 index 00000000000..a31d970bce1 --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php @@ -0,0 +1,84 @@ +memoizer = $memoizer; + $this->indexable_helper = $indexable_helper; + $this->indexable_repository = $indexable_repository; + $this->context_converter = $context_adapter; + } + + /** + * Gets schema pieces for the given indexable IDs. + * + * @param array $indexable_ids The indexable IDs. + * @return array The schema pieces. + */ + public function get_by_indexable_ids( array $indexable_ids ): array { + $indexables = $this->indexable_repository->find_by_ids( $indexable_ids ); + + $schema_pieces = []; + + foreach ( $indexables as $indexable ) { + $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); + $context = $this->memoizer->get( $indexable, $page_type ); + $context_array = $this->context_converter->meta_tags_context_to_array( $context ); + $schema_pieces[] = new Schema_Piece( $context_array, $page_type ); + } + + return $schema_pieces; + } +} From 364785ce45fc575d3889e138f4e7f1bfc2a204eb Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 22 Oct 2025 14:46:58 +0200 Subject: [PATCH 008/319] Add caching functionality to the schema aggregator --- .../application/cache/manager.php | 121 +++--------------- .../infrastructure/config.php | 49 +++++++ ...te-schema-aggregator-cache-cli-command.php | 87 +++++++++++++ .../site-schema-aggregator-cli-command.php | 2 +- .../site-schema-aggregator-route.php | 49 +++++-- 5 files changed, 192 insertions(+), 116 deletions(-) create mode 100644 src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php diff --git a/src/nlweb/schema-aggregator/application/cache/manager.php b/src/nlweb/schema-aggregator/application/cache/manager.php index 1d82e268d75..eea3a7552bc 100644 --- a/src/nlweb/schema-aggregator/application/cache/manager.php +++ b/src/nlweb/schema-aggregator/application/cache/manager.php @@ -1,9 +1,9 @@ |null Cached data or null. */ public function get( int $page, int $per_page ): ?array { try { - // Validate input - if ( $page < 1 ) { - error_log( "Yoast NLWeb Cache: Invalid page number: {$page}" ); - - return null; - } - - if ( $per_page < 1 ) { - error_log( "Yoast NLWeb Cache: Invalid per_page number: {$per_page}" ); - + if ( $page < 1 || $per_page < 1 ) { return null; } $key = $this->get_cache_key( $page, $per_page ); - // get_transient can fail in various ways - $data = get_transient( $key ); + $data = \get_transient( $key ); if ( $data === false ) { return null; } - - // Validate cached data structure - if ( ! is_array( $data ) ) { - error_log( "Yoast NLWeb Cache: Cached data for page {$page} is not an array, invalidating" ); - delete_transient( $key ); + if ( ! \is_array( $data ) ) { + \delete_transient( $key ); return null; } @@ -85,8 +72,6 @@ public function get( int $page, int $per_page ): ?array { return $data; } catch ( \Exception $e ) { - error_log( "Yoast NLWeb Cache: Error getting cache for page {$page}: " . $e->getMessage() ); - return null; } } @@ -94,33 +79,24 @@ public function get( int $page, int $per_page ): ?array { /** * Set cache data for a page * - * @param int $page Page number. - * @param int $per_page Items per page. - * @param array $data Data to cache. + * @param int $page Page number. + * @param int $per_page Items per page. + * @param array $data Data to cache. * * @return bool Success. */ public function set( int $page, int $per_page, array $data ): bool { try { - // Validate inputs - if ( $page < 1 || $per_page < 1 || ! is_array( $data ) ) { + if ( $page < 1 || $per_page < 1 || ! \is_array( $data ) ) { return false; } $key = $this->get_cache_key( $page, $per_page ); - $expiration = $this->get_expiration( $data ); - - $result = set_transient( $key, $data, $expiration ); - - if ( ! $result ) { - error_log( "Yoast NLWeb Cache: Failed to set transient for page {$page}" ); - } + $expiration = $this->config->get_expiration( $data ); - return $result; + return \set_transient( $key, $data, $expiration ); } catch ( \Exception $e ) { - error_log( "Yoast NLWeb Cache: Error setting cache for page {$page}: " . $e->getMessage() ); - return false; } } @@ -138,17 +114,15 @@ public function set( int $page, int $per_page, array $data ): bool { */ public function invalidate( ?int $page = null, ?int $per_page = null ): bool { if ( $page !== null && $per_page !== null ) { - // Clear specific page/per_page combination - return delete_transient( $this->get_cache_key( $page, $per_page ) ); + // Clear specific page/per_page combination. + return \delete_transient( $this->get_cache_key( $page, $per_page ) ); } if ( $page !== null && $per_page === null ) { - // Clear all per_page variations for this page + // Clear all per_page variations for this page. global $wpdb; - if ( ! isset( $wpdb ) || ! is_object( $wpdb ) ) { - error_log( 'Yoast NLWeb Cache: $wpdb is not available for invalidate' ); - + if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) { return false; } @@ -165,31 +139,23 @@ public function invalidate( ?int $page = null, ?int $per_page = null ): bool { return $deleted !== false; } - - // Clear everything return $this->invalidate_all(); } /** * Invalidate all cache pages * - * TODO: Implement incremental cache updates (v2 feature) instead of full regeneration - * * @return bool Success. */ public function invalidate_all(): bool { try { global $wpdb; - // Validate wpdb is available - if ( ! isset( $wpdb ) || ! is_object( $wpdb ) ) { - error_log( 'Yoast NLWeb Cache: $wpdb is not available for invalidate_all' ); - + if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) { return false; } - // Delete all transients matching our pattern - // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version} + // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version}. $pattern = '_transient_' . self::CACHE_PREFIX . '_page_%'; $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_%'; @@ -202,25 +168,19 @@ public function invalidate_all(): bool { ); if ( $deleted === false ) { - error_log( 'Yoast NLWeb Cache: Database query failed in invalidate_all' ); - if ( ! empty( $wpdb->last_error ) ) { - error_log( 'Yoast NLWeb Cache: Database error: ' . $wpdb->last_error ); - } - return false; } return true; } catch ( \Exception $e ) { - error_log( 'Yoast NLWeb Cache: Error in invalidate_all: ' . $e->getMessage() ); return false; } } /** - * Generate cache key for page + * Generate cache key for page. * * @param int $page Page number. * @param int $per_page Items per page. @@ -228,7 +188,7 @@ public function invalidate_all(): bool { * @return string Cache key. */ private function get_cache_key( int $page, int $per_page ): string { - return sprintf( + return \sprintf( '%s_page_%d_per_%d_v%d', self::CACHE_PREFIX, $page, @@ -236,45 +196,4 @@ private function get_cache_key( int $page, int $per_page ): string { self::CACHE_VERSION ); } - - /** - * Get expiration time based on data size - * - * @param array $data Data to cache. - * - * @return int Expiration in seconds. - */ - private function get_expiration( array $data ): int { - try { - // Attempt to serialize to calculate size - // This can fail with circular references or exceed memory - $serialized = serialize( $data ); - - if ( $serialized === false ) { - error_log( 'Yoast NLWeb Cache: Failed to serialize data for expiration calculation' ); - - return HOUR_IN_SECONDS; // Default - } - - $size = strlen( $serialized ); - - // Large payloads: cache longer - if ( $size > 1048576 ) { // > 1MB - return 6 * HOUR_IN_SECONDS; - } - - // Small payloads: cache shorter - if ( $size < 102400 ) { // < 100KB - return 30 * MINUTE_IN_SECONDS; - } - - // Default: 1 hour - return HOUR_IN_SECONDS; - - } catch ( \Exception $e ) { - error_log( 'Yoast NLWeb Cache: Error calculating expiration: ' . $e->getMessage() ); - - return HOUR_IN_SECONDS; // Safe default - } - } } diff --git a/src/nlweb/schema-aggregator/infrastructure/config.php b/src/nlweb/schema-aggregator/infrastructure/config.php index 3a881a94eea..ab7ebe3a1e2 100644 --- a/src/nlweb/schema-aggregator/infrastructure/config.php +++ b/src/nlweb/schema-aggregator/infrastructure/config.php @@ -2,6 +2,8 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure; +use Exception; + /** * Configuration for the Schema Aggregator. */ @@ -20,6 +22,12 @@ class Config { * @var int */ private const MAX_PER_PAGE = 100; + /** + * Default cache TTL in seconds + * + * @var int + */ + private const DEFAULT_CACHE_TTL = \HOUR_IN_SECONDS; /** * Get default items per page @@ -38,4 +46,45 @@ public function get_per_page(): int { public function get_per_page_max(): int { return self::MAX_PER_PAGE; } + + /** + * Get expiration time based on data size. + * + * @param array $data Data to cache. + * + * @return int Expiration in seconds. + */ + public function get_expiration( array $data ): int { + $cache_ttl = self::DEFAULT_CACHE_TTL; + try { + $serialized = \serialize( $data ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.serialize_unserialize -- Needed for size calculation. + + if ( $serialized === false ) { + return self::DEFAULT_CACHE_TTL; + } + + $size = \strlen( $serialized ); + + // Large payloads: cache longer. + if ( $size > 1048576 ) { + $cache_ttl = ( 6 * \HOUR_IN_SECONDS ); + } + + // Small payloads: cache shorter. + if ( $size < 102400 ) { + $cache_ttl = ( 30 * \MINUTE_IN_SECONDS ); + } + + $cache_ttl = \apply_filters( 'yoast_nlweb_cache_ttl', $cache_ttl ); + + if ( ! \is_int( $cache_ttl ) || $cache_ttl <= 0 ) { + return self::DEFAULT_CACHE_TTL; + } + + return $cache_ttl; + + } catch ( Exception $e ) { + return self::DEFAULT_CACHE_TTL; + } + } } diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php new file mode 100644 index 00000000000..9f43d59c87f --- /dev/null +++ b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php @@ -0,0 +1,87 @@ +config = $config; + $this->cache_manager = $cache_manager; + } + + /** + * Returns the namespace of this command. + * + * @return string + */ + public static function get_namespace() { + return Main::WP_CLI_NAMESPACE; + } + + /** + * Aggregates the schema for a certain site. + * + * ## OPTIONS + * + * [--page=] + * : The current page to process. + * --- + * ## EXAMPLES + * + * wp yoast aggregate_site_schema_clear_cache + * + * @when after_wp_load + * + * @param array|null $args The arguments. + * @param array|null $assoc_args The associative arguments. + * + * @throws ExitException When the input args are invalid. + * @return void + */ + public function aggregate_site_schema_clear_cache( $args = null, $assoc_args = null ) { + if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] >= 1 ) { + $this->cache_manager->invalidate( $assoc_args['page'] ); + WP_CLI::log( + \__( 'The site schema cache has been cleared successfully.', 'wordpress-seo' ) + ); + return; + } + $this->cache_manager->invalidate_all(); + + WP_CLI::log( + \__( 'All site schema cache has been cleared successfully.', 'wordpress-seo' ) + ); + } +} diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php index ca780436075..e249565f8bf 100644 --- a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php +++ b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php @@ -33,7 +33,7 @@ class Site_Schema_Aggregator_Cli_Command implements Command_Interface { private $aggregate_site_schema_command_handler; /** - * Site_Schema_Aggregator_Route constructor. + * Site_Schema_Aggregator_Cli_Command constructor. * * @param Config $config The config object. * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler. diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php index 112c5c72980..74b6d61373c 100644 --- a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -2,6 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Nlweb\Schema_Aggregator\User_Interface; +use Exception; use WP_Error; use WP_REST_Request; use WP_REST_Response; @@ -9,6 +10,7 @@ use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; +use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application\Cache\Manager; use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; use Yoast\WP\SEO\Routes\Route_Interface; @@ -54,6 +56,13 @@ class Site_Schema_Aggregator_Route implements Route_Interface { */ private $aggregate_site_schema_command_handler; + /** + * The cache manager instance. + * + * @var Manager + */ + private $cache_manager; + /** * Returns the conditional for this route. * @@ -69,11 +78,18 @@ public static function get_conditionals() { * @param Config $config The config object. * @param Capability_Helper $capability_helper The capability helper. * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler. + * @param Manager $cache_manager The cache manager. */ - public function __construct( Config $config, Capability_Helper $capability_helper, Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler ) { + public function __construct( + Config $config, + Capability_Helper $capability_helper, + Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler, + Manager $cache_manager + ) { $this->config = $config; $this->capability_helper = $capability_helper; $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; + $this->cache_manager = $cache_manager; } /** @@ -127,20 +143,25 @@ public function aggregate_site_schema( WP_REST_Request $request ) { $page = $request->get_param( 'page' ); $per_page = $request->get_param( 'per_page' ); - try { - $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); - } catch ( Exception $exception ) { - return new WP_Error( - 'wpseo_aggregate_site_schema_error', - $exception->getMessage(), - (object) [] - ); + $output = $this->cache_manager->get( $page, $per_page ); + if ( $output === null ) { + try { + $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); + $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); + $this->cache_manager->set( $page, $per_page, $result ); + + } catch ( Exception $exception ) { + return new WP_Error( + 'wpseo_aggregate_site_schema_error', + $exception->getMessage(), + (object) [] + ); + } } - $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); + $response = \rest_ensure_response( $output ); + + $response->header( 'Cache-Control', 'public, max-age=300' ); - return new WP_REST_Response( - $output, - ( $result ) ? 200 : 400 - ); + return $response; } } From c8cbc0d0efc26584b5542dedc7a9e01fea296665 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 13:36:05 +0200 Subject: [PATCH 009/319] Refactor the memoizer adapter to a factory --- ...act-meta-tags-context-memoizer-adapter.php | 52 +++++++++++++++++++ ...ive-meta-tags-context-memoizer-adapter.php | 24 +++++++++ ...ive-meta-tags-context-memoizer-adapter.php | 27 ++++++++++ ...lt-meta-tags-context-memoizer-adapter.php} | 39 +++++++------- ...age-meta-tags-context-memoizer-adapter.php | 23 ++++++++ ...age-meta-tags-context-memoizer-adapter.php | 35 +++++++++++++ ...-tags-context-memoizer-adapter-factory.php | 36 +++++++++++++ ...ags-context-memoizer-adapter-interface.php | 18 +++++++ ...ype-meta-tags-context-memoizer-adapter.php | 38 ++++++++++++++ ...ult-meta-tags-context-memoizer-adapter.php | 23 ++++++++ 10 files changed, 295 insertions(+), 20 deletions(-) create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php rename src/nlweb/schema-aggregator/infrastructure/{meta-tags-context-memoizer-adapter.php => adapters/default-meta-tags-context-memoizer-adapter.php} (54%) create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-interface.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/post-type-meta-tags-context-memoizer-adapter.php create mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..9e762af2939 --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php @@ -0,0 +1,52 @@ + The meta tags context as an array. + */ + public function meta_tags_context_to_array( Meta_Tags_Context $context ): array { + return \array_merge( + $this->get_base_fields( $context ), + $this->get_specific_fields( $context ) + ); + } + + /** + * Gets the base fields that are relevant for all page types. + * + * @param Meta_Tags_Context $context The meta tags context. + * @return array The base fields. + */ + protected function get_base_fields( Meta_Tags_Context $context ): array { + return [ + 'canonical' => $context->canonical, + 'permalink' => $context->permalink, + 'title' => $context->title, + 'description' => $context->description, + 'id' => $context->id, + 'site_name' => $context->site_name, + 'site_url' => $context->site_url, + 'schema_page_type' => $context->schema_page_type, + 'main_schema_id' => $context->main_schema_id, + 'page_type' => $context->page_type, + ]; + } + + /** + * Gets the page-type specific fields. + * + * @param Meta_Tags_Context $context The meta tags context. + * @return array The page-type specific fields. + */ + abstract protected function get_specific_fields( Meta_Tags_Context $context ): array; +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..5cca64e80fb --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php @@ -0,0 +1,24 @@ + The archive specific fields. + */ + protected function get_specific_fields( Meta_Tags_Context $context ): array { + return [ + 'open_graph_enabled' => $context->open_graph_enabled, + 'open_graph_publisher' => $context->open_graph_publisher, + 'twitter_card' => $context->twitter_card, + ]; + } +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..9320a219bb8 --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php @@ -0,0 +1,27 @@ + The author archive specific fields. + */ + protected function get_specific_fields( Meta_Tags_Context $context ): array { + return [ + 'person_logo_id' => $context->person_logo_id, + 'person_logo_meta' => $context->person_logo_meta, + 'site_user_id' => $context->site_user_id, + 'open_graph_enabled' => $context->open_graph_enabled, + 'open_graph_publisher' => $context->open_graph_publisher, + 'twitter_card' => $context->twitter_card, + ]; + } +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/default-meta-tags-context-memoizer-adapter.php similarity index 54% rename from src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php rename to src/nlweb/schema-aggregator/infrastructure/adapters/default-meta-tags-context-memoizer-adapter.php index 8af24e381e7..d532e05b272 100644 --- a/src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/default-meta-tags-context-memoizer-adapter.php @@ -1,30 +1,24 @@ The meta tags context as an array. + * @return array All optional fields. */ - public function meta_tags_context_to_array( Meta_Tags_Context $context ): array { - return [ - 'canonical' => $context->canonical, - 'permalink' => $context->permalink, - 'title' => $context->title, - 'description' => $context->description, - 'id' => $context->id, - 'site_name' => $context->site_name, + protected function get_specific_fields( Meta_Tags_Context $context ): array { + $fields = [ 'alternate_site_name' => $context->alternate_site_name, 'wordpress_site_name' => $context->wordpress_site_name, - 'site_url' => $context->site_url, 'company_name' => $context->company_name, 'company_alternate_name' => $context->company_alternate_name, 'company_logo_id' => $context->company_logo_id, @@ -34,18 +28,23 @@ public function meta_tags_context_to_array( Meta_Tags_Context $context ): array 'site_user_id' => $context->site_user_id, 'site_represents' => $context->site_represents, 'site_represents_reference' => $context->site_represents_reference, - 'schema_page_type' => $context->schema_page_type, 'schema_article_type' => $context->schema_article_type, - 'main_schema_id' => $context->main_schema_id, - 'main_entity_of_page' => $context->main_entity_of_page, 'open_graph_enabled' => $context->open_graph_enabled, 'open_graph_publisher' => $context->open_graph_publisher, 'twitter_card' => $context->twitter_card, - 'page_type' => $context->page_type, - 'has_article' => $context->has_article, 'has_image' => $context->has_image, 'main_image_id' => $context->main_image_id, 'main_image_url' => $context->main_image_url, ]; + + // Access public property directly (not through __get magic method) + $fields['has_article'] = $context->has_article; + + // Access dynamic property if it exists + if ( isset( $context->main_entity_of_page ) ) { + $fields['main_entity_of_page'] = $context->main_entity_of_page; + } + + return $fields; } -} +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..2e7929a0c7f --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php @@ -0,0 +1,23 @@ + The error page specific fields. + */ + protected function get_specific_fields( Meta_Tags_Context $context ): array { + return [ + 'open_graph_enabled' => $context->open_graph_enabled, + 'twitter_card' => $context->twitter_card, + ]; + } +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..e4fdfd5db8a --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php @@ -0,0 +1,35 @@ + The home page specific fields. + */ + protected function get_specific_fields( Meta_Tags_Context $context ): array { + return [ + 'alternate_site_name' => $context->alternate_site_name, + 'wordpress_site_name' => $context->wordpress_site_name, + 'company_name' => $context->company_name, + 'company_alternate_name' => $context->company_alternate_name, + 'company_logo_id' => $context->company_logo_id, + 'company_logo_meta' => $context->company_logo_meta, + 'person_logo_id' => $context->person_logo_id, + 'person_logo_meta' => $context->person_logo_meta, + 'site_user_id' => $context->site_user_id, + 'site_represents' => $context->site_represents, + 'site_represents_reference' => $context->site_represents_reference, + 'open_graph_enabled' => $context->open_graph_enabled, + 'open_graph_publisher' => $context->open_graph_publisher, + 'twitter_card' => $context->twitter_card, + ]; + } +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php b/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php new file mode 100644 index 00000000000..b1d09061126 --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php @@ -0,0 +1,36 @@ + The meta tags context as an array. + */ + public function meta_tags_context_to_array( Meta_Tags_Context $context ): array; +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/post-type-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/post-type-meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..2e1d5289d90 --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/post-type-meta-tags-context-memoizer-adapter.php @@ -0,0 +1,38 @@ + The post type specific fields. + */ + protected function get_specific_fields( Meta_Tags_Context $context ): array { + $fields = [ + 'schema_article_type' => $context->schema_article_type, + 'has_image' => $context->has_image, + 'main_image_id' => $context->main_image_id, + 'main_image_url' => $context->main_image_url, + 'open_graph_enabled' => $context->open_graph_enabled, + 'open_graph_publisher' => $context->open_graph_publisher, + 'twitter_card' => $context->twitter_card, + ]; + + // Access public property directly (not through __get magic method) + $fields['has_article'] = $context->has_article; + + // Access dynamic property if it exists + if ( isset( $context->main_entity_of_page ) ) { + $fields['main_entity_of_page'] = $context->main_entity_of_page; + } + + return $fields; + } +} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php new file mode 100644 index 00000000000..3c927710901 --- /dev/null +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php @@ -0,0 +1,23 @@ + The search specific fields. + */ + protected function get_specific_fields( Meta_Tags_Context $context ): array { + return [ + 'open_graph_enabled' => $context->open_graph_enabled, + 'twitter_card' => $context->twitter_card, + ]; + } +} \ No newline at end of file From a4c3d0cd4e2cf62bda230468550fe0988a56796d Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 13:36:38 +0200 Subject: [PATCH 010/319] use the Schema_Piece_Repository class to get Schema_Piece objects --- .../schema-piece-repository.php | 43 ++++++++++-------- .../to-aggregate-indexable-collector.php | 44 ------------------- 2 files changed, 25 insertions(+), 62 deletions(-) delete mode 100644 src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php diff --git a/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php index a31d970bce1..4ab4eacbc05 100644 --- a/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php @@ -4,8 +4,10 @@ use Yoast\WP\SEO\Helpers\Indexable_Helper; use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; +use Yoast\WP\SEO\Models\Indexable; use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; +use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Infrastructure\Adapters\Meta_Tags_Context_Memoizer_Adapter_Factory; use Yoast\WP\SEO\Repositories\Indexable_Repository; /** @@ -35,47 +37,52 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { private $indexable_helper; /** - * The meta tags context converter. + * The meta tags context adapter factory. * - * @var Meta_Tags_Context_Memoizer_Adapter + * @var Meta_Tags_Context_Memoizer_Adapter_Factory */ - private $context_converter; + private $adapter_factory; /** * Constructor. * - * @param Meta_Tags_Context_Memoizer $memoizer The meta tags context memoizer. - * @param Indexable_Helper $indexable_helper The indexable helper. - * @param Indexable_Repository $indexable_repository The indexable repository. - * @param Meta_Tags_Context_Memoizer_Adapter $context_adapter The context adapter. + * @param Meta_Tags_Context_Memoizer $memoizer The meta tags context memoizer. + * @param Indexable_Helper $indexable_helper The indexable helper. + * @param Indexable_Repository $indexable_repository The indexable repository. + * @param Meta_Tags_Context_Memoizer_Adapter_Factory $adapter_factory The adapter factory. */ public function __construct( Meta_Tags_Context_Memoizer $memoizer, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository, - Meta_Tags_Context_Memoizer_Adapter $context_adapter + Meta_Tags_Context_Memoizer_Adapter_Factory $adapter_factory ) { $this->memoizer = $memoizer; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; - $this->context_converter = $context_adapter; + $this->adapter_factory = $adapter_factory; } /** - * Gets schema pieces for the given indexable IDs. + * Gets the indexables to be aggregated. * - * @param array $indexable_ids The indexable IDs. - * @return array The schema pieces. + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * + * @return array The aggregated schema. */ - public function get_by_indexable_ids( array $indexable_ids ): array { - $indexables = $this->indexable_repository->find_by_ids( $indexable_ids ); - - $schema_pieces = []; + public function get( $page, $page_size ): array { + $public_indexables = $this->indexable_repository->find_all_public_paginated( + $page, + $page_size, + ); + $schema_pieces = []; - foreach ( $indexables as $indexable ) { + foreach ( $public_indexables as $indexable ) { $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); $context = $this->memoizer->get( $indexable, $page_type ); - $context_array = $this->context_converter->meta_tags_context_to_array( $context ); + $adapter = $this->adapter_factory->create( $page_type ); + $context_array = $adapter->meta_tags_context_to_array( $context ); $schema_pieces[] = new Schema_Piece( $context_array, $page_type ); } diff --git a/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php b/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php deleted file mode 100644 index 6d166aafedb..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php +++ /dev/null @@ -1,44 +0,0 @@ -indexable_repository = $indexable_repository; - } - - /** - * Gets the indexables to be aggregated. - * - * @param int $page The page number (1-based). - * @param int $page_size The number of items per page. - * - * @return array The aggregated schema. - */ - public function get( $page, $page_size ): array { - - return $this->indexable_repository->find_all_public_paginated( - $page, - $page_size, - ); - } -} From aa82859e44be81093ed7f5eb9e6d5965862da4cd Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 13:36:47 +0200 Subject: [PATCH 011/319] Refactor interface --- .../domain/schema-piece-repository-interface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php b/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php index 1b2db475897..2c7b28dc42f 100644 --- a/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php +++ b/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php @@ -16,5 +16,5 @@ interface Schema_Piece_Repository_Interface { * * @return array The schema pieces. */ - public function get_by_indexable_ids( array $indexable_ids ): array; + public function get( $page, $page_size ): array; } From 54db777cb4c4c5c17e17a84d6e50464d43300c1f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 13:36:57 +0200 Subject: [PATCH 012/319] Refactor the command handler --- .../aggregate-site-schema-command-handler.php | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php index bb053b84a7c..802f23ded07 100644 --- a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application; use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; +use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Infrastructure\Schema_Piece_Repository; use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\To_Aggregate_Indexable_Collector; /** @@ -12,28 +13,19 @@ class Aggregate_Site_Schema_Command_Handler { /** - * The To_Aggregate_Indexable_Collector instance. + * The Schema_Piece_Repository instance. * - * @var To_Aggregate_Indexable_Collector + * @var Schema_Piece_Repository */ - private $to_aggregate_indexable_collector; - - /** - * Represents the meta tags memoizer. - * - * @var Meta_Tags_Context_Memoizer - */ - protected $meta_tags_context_memoizer; + private $schema_piece_repository; /** * Aggregate_Site_Schema_Command_Handler constructor. * - * @param To_Aggregate_Indexable_Collector $to_aggregate_indexable_collector The collector of indexables that need to be aggregated. - * @param Meta_Tags_Context_Memoizer $meta_tags_context_memoizer The meta tags context memoizer. + * @param Schema_Piece_Repository $schema_piece_repository The collector of indexables that need to be aggregated. */ - public function __construct( To_Aggregate_Indexable_Collector $to_aggregate_indexable_collector, Meta_Tags_Context_Memoizer $meta_tags_context_memoizer ) { - $this->to_aggregate_indexable_collector = $to_aggregate_indexable_collector; - $this->meta_tags_context_memoizer = $meta_tags_context_memoizer; + public function __construct( Schema_Piece_Repository $schema_piece_repository ) { + $this->schema_piece_repository = $schema_piece_repository; } /** @@ -45,15 +37,15 @@ public function __construct( To_Aggregate_Indexable_Collector $to_aggregate_inde */ public function handle( Aggregate_Site_Schema_Command $command ): array { - $indexables = $this->to_aggregate_indexable_collector->get( + $schema_pieces = $this->schema_piece_repository->get( $command->get_page_controls()->get_page(), $command->get_page_controls()->get_page_size() ); // This part should be replaced by the rest of the system. $schema = []; - foreach ( $indexables as $indexable ) { - $schema[] = $this->meta_tags_context_memoizer->get( $indexable, $indexable->object_sub_type )->presentation->schema; + foreach ( $schema_pieces as $schema_piece ) { + $schema[] = $schema_piece->to_schema_array(); } return $schema; } From 6cf857e0ef40f1fc517ba11995f74576f8785b05 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 14:15:58 +0200 Subject: [PATCH 013/319] Remove the adapter factory nonsense --- ...act-meta-tags-context-memoizer-adapter.php | 52 ------------------- ...ive-meta-tags-context-memoizer-adapter.php | 24 --------- ...ive-meta-tags-context-memoizer-adapter.php | 27 ---------- ...ult-meta-tags-context-memoizer-adapter.php | 50 ------------------ ...age-meta-tags-context-memoizer-adapter.php | 23 -------- ...age-meta-tags-context-memoizer-adapter.php | 35 ------------- ...-tags-context-memoizer-adapter-factory.php | 36 ------------- ...ype-meta-tags-context-memoizer-adapter.php | 38 -------------- ...ult-meta-tags-context-memoizer-adapter.php | 23 -------- 9 files changed, 308 deletions(-) delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/default-meta-tags-context-memoizer-adapter.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/post-type-meta-tags-context-memoizer-adapter.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php deleted file mode 100644 index 9e762af2939..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/abstract-meta-tags-context-memoizer-adapter.php +++ /dev/null @@ -1,52 +0,0 @@ - The meta tags context as an array. - */ - public function meta_tags_context_to_array( Meta_Tags_Context $context ): array { - return \array_merge( - $this->get_base_fields( $context ), - $this->get_specific_fields( $context ) - ); - } - - /** - * Gets the base fields that are relevant for all page types. - * - * @param Meta_Tags_Context $context The meta tags context. - * @return array The base fields. - */ - protected function get_base_fields( Meta_Tags_Context $context ): array { - return [ - 'canonical' => $context->canonical, - 'permalink' => $context->permalink, - 'title' => $context->title, - 'description' => $context->description, - 'id' => $context->id, - 'site_name' => $context->site_name, - 'site_url' => $context->site_url, - 'schema_page_type' => $context->schema_page_type, - 'main_schema_id' => $context->main_schema_id, - 'page_type' => $context->page_type, - ]; - } - - /** - * Gets the page-type specific fields. - * - * @param Meta_Tags_Context $context The meta tags context. - * @return array The page-type specific fields. - */ - abstract protected function get_specific_fields( Meta_Tags_Context $context ): array; -} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php deleted file mode 100644 index 5cca64e80fb..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/archive-meta-tags-context-memoizer-adapter.php +++ /dev/null @@ -1,24 +0,0 @@ - The archive specific fields. - */ - protected function get_specific_fields( Meta_Tags_Context $context ): array { - return [ - 'open_graph_enabled' => $context->open_graph_enabled, - 'open_graph_publisher' => $context->open_graph_publisher, - 'twitter_card' => $context->twitter_card, - ]; - } -} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php deleted file mode 100644 index 9320a219bb8..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/author-archive-meta-tags-context-memoizer-adapter.php +++ /dev/null @@ -1,27 +0,0 @@ - The author archive specific fields. - */ - protected function get_specific_fields( Meta_Tags_Context $context ): array { - return [ - 'person_logo_id' => $context->person_logo_id, - 'person_logo_meta' => $context->person_logo_meta, - 'site_user_id' => $context->site_user_id, - 'open_graph_enabled' => $context->open_graph_enabled, - 'open_graph_publisher' => $context->open_graph_publisher, - 'twitter_card' => $context->twitter_card, - ]; - } -} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/default-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/default-meta-tags-context-memoizer-adapter.php deleted file mode 100644 index d532e05b272..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/default-meta-tags-context-memoizer-adapter.php +++ /dev/null @@ -1,50 +0,0 @@ - All optional fields. - */ - protected function get_specific_fields( Meta_Tags_Context $context ): array { - $fields = [ - 'alternate_site_name' => $context->alternate_site_name, - 'wordpress_site_name' => $context->wordpress_site_name, - 'company_name' => $context->company_name, - 'company_alternate_name' => $context->company_alternate_name, - 'company_logo_id' => $context->company_logo_id, - 'company_logo_meta' => $context->company_logo_meta, - 'person_logo_id' => $context->person_logo_id, - 'person_logo_meta' => $context->person_logo_meta, - 'site_user_id' => $context->site_user_id, - 'site_represents' => $context->site_represents, - 'site_represents_reference' => $context->site_represents_reference, - 'schema_article_type' => $context->schema_article_type, - 'open_graph_enabled' => $context->open_graph_enabled, - 'open_graph_publisher' => $context->open_graph_publisher, - 'twitter_card' => $context->twitter_card, - 'has_image' => $context->has_image, - 'main_image_id' => $context->main_image_id, - 'main_image_url' => $context->main_image_url, - ]; - - // Access public property directly (not through __get magic method) - $fields['has_article'] = $context->has_article; - - // Access dynamic property if it exists - if ( isset( $context->main_entity_of_page ) ) { - $fields['main_entity_of_page'] = $context->main_entity_of_page; - } - - return $fields; - } -} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php deleted file mode 100644 index 2e7929a0c7f..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/error-page-meta-tags-context-memoizer-adapter.php +++ /dev/null @@ -1,23 +0,0 @@ - The error page specific fields. - */ - protected function get_specific_fields( Meta_Tags_Context $context ): array { - return [ - 'open_graph_enabled' => $context->open_graph_enabled, - 'twitter_card' => $context->twitter_card, - ]; - } -} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php deleted file mode 100644 index e4fdfd5db8a..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/home-page-meta-tags-context-memoizer-adapter.php +++ /dev/null @@ -1,35 +0,0 @@ - The home page specific fields. - */ - protected function get_specific_fields( Meta_Tags_Context $context ): array { - return [ - 'alternate_site_name' => $context->alternate_site_name, - 'wordpress_site_name' => $context->wordpress_site_name, - 'company_name' => $context->company_name, - 'company_alternate_name' => $context->company_alternate_name, - 'company_logo_id' => $context->company_logo_id, - 'company_logo_meta' => $context->company_logo_meta, - 'person_logo_id' => $context->person_logo_id, - 'person_logo_meta' => $context->person_logo_meta, - 'site_user_id' => $context->site_user_id, - 'site_represents' => $context->site_represents, - 'site_represents_reference' => $context->site_represents_reference, - 'open_graph_enabled' => $context->open_graph_enabled, - 'open_graph_publisher' => $context->open_graph_publisher, - 'twitter_card' => $context->twitter_card, - ]; - } -} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php b/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php deleted file mode 100644 index b1d09061126..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-factory.php +++ /dev/null @@ -1,36 +0,0 @@ - The post type specific fields. - */ - protected function get_specific_fields( Meta_Tags_Context $context ): array { - $fields = [ - 'schema_article_type' => $context->schema_article_type, - 'has_image' => $context->has_image, - 'main_image_id' => $context->main_image_id, - 'main_image_url' => $context->main_image_url, - 'open_graph_enabled' => $context->open_graph_enabled, - 'open_graph_publisher' => $context->open_graph_publisher, - 'twitter_card' => $context->twitter_card, - ]; - - // Access public property directly (not through __get magic method) - $fields['has_article'] = $context->has_article; - - // Access dynamic property if it exists - if ( isset( $context->main_entity_of_page ) ) { - $fields['main_entity_of_page'] = $context->main_entity_of_page; - } - - return $fields; - } -} \ No newline at end of file diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php deleted file mode 100644 index 3c927710901..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/search-result-meta-tags-context-memoizer-adapter.php +++ /dev/null @@ -1,23 +0,0 @@ - The search specific fields. - */ - protected function get_specific_fields( Meta_Tags_Context $context ): array { - return [ - 'open_graph_enabled' => $context->open_graph_enabled, - 'twitter_card' => $context->twitter_card, - ]; - } -} \ No newline at end of file From c392c3f329eda9b243d96fb8a7b7877f0e126240 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 14:16:40 +0200 Subject: [PATCH 014/319] Use a single adapter --- ...face.php => meta-tags-context-memoizer-adapter.php} | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) rename src/nlweb/schema-aggregator/infrastructure/adapters/{meta-tags-context-memoizer-adapter-interface.php => meta-tags-context-memoizer-adapter.php} (70%) diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-interface.php b/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter.php similarity index 70% rename from src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-interface.php rename to src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter.php index fa81686a5b6..5e47fe29e9d 100644 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter-interface.php +++ b/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter.php @@ -4,9 +4,9 @@ use Yoast\WP\SEO\Context\Meta_Tags_Context; /** - * Interface for converting Meta_Tags_Context objects to arrays. + * Class for converting Meta_Tags_Context objects to arrays. */ -interface Meta_Tags_Context_Memoizer_Adapter_Interface { +class Meta_Tags_Context_Memoizer_Adapter { /** * Converts a Meta_Tags_Context object to an array. @@ -14,5 +14,7 @@ interface Meta_Tags_Context_Memoizer_Adapter_Interface { * @param Meta_Tags_Context $context The meta tags context. * @return array The meta tags context as an array. */ - public function meta_tags_context_to_array( Meta_Tags_Context $context ): array; -} \ No newline at end of file + public function meta_tags_context_to_array( Meta_Tags_Context $context ): array { + return $context->presentation->schema; + } +} From 035233439288e004be9cb43ede42315bce19b261 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 14:18:19 +0200 Subject: [PATCH 015/319] Use the adapter --- .../infrastructure/schema-piece-repository.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php index 4ab4eacbc05..26a94cffa22 100644 --- a/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php @@ -7,7 +7,7 @@ use Yoast\WP\SEO\Models\Indexable; use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; -use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Infrastructure\Adapters\Meta_Tags_Context_Memoizer_Adapter_Factory; +use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Infrastructure\Adapters\Meta_Tags_Context_Memoizer_Adapter; use Yoast\WP\SEO\Repositories\Indexable_Repository; /** @@ -39,9 +39,9 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { /** * The meta tags context adapter factory. * - * @var Meta_Tags_Context_Memoizer_Adapter_Factory + * @var Meta_Tags_Context_Memoizer_Adapter */ - private $adapter_factory; + private $adapter; /** * Constructor. @@ -49,18 +49,18 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { * @param Meta_Tags_Context_Memoizer $memoizer The meta tags context memoizer. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. - * @param Meta_Tags_Context_Memoizer_Adapter_Factory $adapter_factory The adapter factory. + * @param Meta_Tags_Context_Memoizer_Adapter $adapter The adapter factory. */ public function __construct( Meta_Tags_Context_Memoizer $memoizer, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository, - Meta_Tags_Context_Memoizer_Adapter_Factory $adapter_factory + Meta_Tags_Context_Memoizer_Adapter $adapter ) { $this->memoizer = $memoizer; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; - $this->adapter_factory = $adapter_factory; + $this->adapter = $adapter; } /** @@ -81,8 +81,7 @@ public function get( $page, $page_size ): array { foreach ( $public_indexables as $indexable ) { $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); $context = $this->memoizer->get( $indexable, $page_type ); - $adapter = $this->adapter_factory->create( $page_type ); - $context_array = $adapter->meta_tags_context_to_array( $context ); + $context_array = $this->adapter->meta_tags_context_to_array( $context ); $schema_pieces[] = new Schema_Piece( $context_array, $page_type ); } From cfdde82c72a7f5e57fb1e798727f2af09621faba Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 15:17:39 +0200 Subject: [PATCH 016/319] Fix cs --- .../aggregate-site-schema-command-handler.php | 8 +++----- .../schema-piece-repository-interface.php | 8 ++++---- .../schema-aggregator/domain/schema-piece.php | 18 +++--------------- .../meta-tags-context-memoizer-adapter.php | 4 +++- .../infrastructure/schema-piece-repository.php | 17 ++++++++--------- 5 files changed, 21 insertions(+), 34 deletions(-) rename src/nlweb/schema-aggregator/infrastructure/{adapters => }/meta-tags-context-memoizer-adapter.php (75%) diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php index 802f23ded07..9eb7371d7eb 100644 --- a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -3,9 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application; -use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; use Yoast\WP\SEO\NLWeb\Schema_Aggregator\Infrastructure\Schema_Piece_Repository; -use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\To_Aggregate_Indexable_Collector; /** * Class that handles the Aggregate_Site_Schema_Command. @@ -22,10 +20,10 @@ class Aggregate_Site_Schema_Command_Handler { /** * Aggregate_Site_Schema_Command_Handler constructor. * - * @param Schema_Piece_Repository $schema_piece_repository The collector of indexables that need to be aggregated. + * @param Schema_Piece_Repository $schema_piece_repository The collector of indexables that need to be aggregated. */ public function __construct( Schema_Piece_Repository $schema_piece_repository ) { - $this->schema_piece_repository = $schema_piece_repository; + $this->schema_piece_repository = $schema_piece_repository; } /** @@ -45,7 +43,7 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { // This part should be replaced by the rest of the system. $schema = []; foreach ( $schema_pieces as $schema_piece ) { - $schema[] = $schema_piece->to_schema_array(); + $schema[] = $schema_piece->get_data(); } return $schema; } diff --git a/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php b/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php index 2c7b28dc42f..9b711a66c6c 100644 --- a/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php +++ b/src/nlweb/schema-aggregator/domain/schema-piece-repository-interface.php @@ -1,9 +1,8 @@ $indexable_ids The indexable IDs. + * @param int $page The page number. + * @param int $page_size The number of items per page. * * @return array The schema pieces. */ - public function get( $page, $page_size ): array; + public function get( int $page, int $page_size ): array; } diff --git a/src/nlweb/schema-aggregator/domain/schema-piece.php b/src/nlweb/schema-aggregator/domain/schema-piece.php index a6162f1b321..82d4d639cf7 100644 --- a/src/nlweb/schema-aggregator/domain/schema-piece.php +++ b/src/nlweb/schema-aggregator/domain/schema-piece.php @@ -1,5 +1,6 @@ data; } - /** - * Converts the schema piece to a schema.org array. - * - * @return array The schema.org array representation. - */ - public function to_schema_array(): array { - return [ - '@type' => $this->type, - ...$this->data, - ]; - } - /** * Encodes the schema piece in JSON-LD format. * * @return string The JSON-LD representation. */ public function to_json_ld(): string { - $schema_array = $this->to_schema_array(); - return WPSEO_Utils::format_json_encode( $schema_array ); + return WPSEO_Utils::format_json_encode( $this->data ); } /** @@ -84,7 +72,7 @@ public static function to_json_ld_graph( array $schema_pieces ): string { $graph = []; foreach ( $schema_pieces as $piece ) { if ( $piece instanceof self ) { - $graph[] = $piece->to_schema_array(); + $graph[] = $piece->data; } } diff --git a/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter.php b/src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php similarity index 75% rename from src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter.php rename to src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php index 5e47fe29e9d..0da7b4537cd 100644 --- a/src/nlweb/schema-aggregator/infrastructure/adapters/meta-tags-context-memoizer-adapter.php +++ b/src/nlweb/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php @@ -1,5 +1,7 @@ memoizer = $memoizer; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; - $this->adapter = $adapter; + $this->adapter = $adapter; } /** @@ -71,7 +70,7 @@ public function __construct( * * @return array The aggregated schema. */ - public function get( $page, $page_size ): array { + public function get( int $page, int $page_size ): array { $public_indexables = $this->indexable_repository->find_all_public_paginated( $page, $page_size, @@ -81,7 +80,7 @@ public function get( $page, $page_size ): array { foreach ( $public_indexables as $indexable ) { $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); $context = $this->memoizer->get( $indexable, $page_type ); - $context_array = $this->adapter->meta_tags_context_to_array( $context ); + $context_array = $this->adapter->meta_tags_context_to_array( $context ); $schema_pieces[] = new Schema_Piece( $context_array, $page_type ); } From 647154bf815106f32608afeae85388a2cd083879 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 23 Oct 2025 15:23:05 +0200 Subject: [PATCH 017/319] Fix cs --- .../application/aggregator.php | 29 ------------------- .../schema-piece-repository.php | 2 +- 2 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 src/nlweb/schema-aggregator/application/aggregator.php diff --git a/src/nlweb/schema-aggregator/application/aggregator.php b/src/nlweb/schema-aggregator/application/aggregator.php deleted file mode 100644 index af90c190bb0..00000000000 --- a/src/nlweb/schema-aggregator/application/aggregator.php +++ /dev/null @@ -1,29 +0,0 @@ -schema_data_repository = $schema_data_repository; - } -} diff --git a/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php index 46137ab4b1c..3f92a0b799a 100644 --- a/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/nlweb/schema-aggregator/infrastructure/schema-piece-repository.php @@ -1,12 +1,12 @@ Date: Mon, 27 Oct 2025 11:16:14 +0100 Subject: [PATCH 018/319] Add cache invalidation --- .../application/cache/manager.php | 14 ++- .../infrastructure/config.php | 22 +++- ...indexables-update-listener-integration.php | 115 ++++++++++++++++++ 3 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php diff --git a/src/nlweb/schema-aggregator/application/cache/manager.php b/src/nlweb/schema-aggregator/application/cache/manager.php index eea3a7552bc..1e1c6ca1a2b 100644 --- a/src/nlweb/schema-aggregator/application/cache/manager.php +++ b/src/nlweb/schema-aggregator/application/cache/manager.php @@ -4,6 +4,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application\Cache; +use Exception; use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\Config; /** @@ -52,6 +53,9 @@ public function __construct( Config $config ) { */ public function get( int $page, int $per_page ): ?array { try { + if ( ! $this->config->cache_enabled() ) { + return null; + } if ( $page < 1 || $per_page < 1 ) { return null; } @@ -71,7 +75,7 @@ public function get( int $page, int $per_page ): ?array { return $data; - } catch ( \Exception $e ) { + } catch ( Exception $e ) { return null; } } @@ -96,7 +100,7 @@ public function set( int $page, int $per_page, array $data ): bool { return \set_transient( $key, $data, $expiration ); - } catch ( \Exception $e ) { + } catch ( Exception $e ) { return false; } } @@ -128,7 +132,7 @@ public function invalidate( ?int $page = null, ?int $per_page = null ): bool { $pattern = '_transient_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; - + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery $deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", @@ -158,7 +162,7 @@ public function invalidate_all(): bool { // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version}. $pattern = '_transient_' . self::CACHE_PREFIX . '_page_%'; $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_%'; - + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery $deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", @@ -173,7 +177,7 @@ public function invalidate_all(): bool { return true; - } catch ( \Exception $e ) { + } catch ( Exception $e ) { return false; } diff --git a/src/nlweb/schema-aggregator/infrastructure/config.php b/src/nlweb/schema-aggregator/infrastructure/config.php index ab7ebe3a1e2..749f00dd6ea 100644 --- a/src/nlweb/schema-aggregator/infrastructure/config.php +++ b/src/nlweb/schema-aggregator/infrastructure/config.php @@ -14,7 +14,7 @@ class Config { * * @var int */ - private const DEFAULT_PER_PAGE = 100; + private const DEFAULT_PER_PAGE = 10; /** * Maximum items per page @@ -27,7 +27,7 @@ class Config { * * @var int */ - private const DEFAULT_CACHE_TTL = \HOUR_IN_SECONDS; + private const DEFAULT_CACHE_TTL = ( 60 * 60 ); /** * Get default items per page @@ -57,7 +57,7 @@ public function get_per_page_max(): int { public function get_expiration( array $data ): int { $cache_ttl = self::DEFAULT_CACHE_TTL; try { - $serialized = \serialize( $data ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.serialize_unserialize -- Needed for size calculation. + $serialized = \serialize( $data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- Needed for size calculation. if ( $serialized === false ) { return self::DEFAULT_CACHE_TTL; @@ -87,4 +87,20 @@ public function get_expiration( array $data ): int { return self::DEFAULT_CACHE_TTL; } } + + /** + * Check if caching is enabled. + * + * @return bool True if caching is enabled, false otherwise. + */ + public function cache_enabled(): bool { + $enabled = \apply_filters( 'yoast_nlweb_cache_enabled', true ); + + if ( \is_bool( $enabled ) ) { + return $enabled; + } + else { + return true; + } + } } diff --git a/src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php new file mode 100644 index 00000000000..edae909dae1 --- /dev/null +++ b/src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -0,0 +1,115 @@ +indexable_repository = $indexable_repository; + $this->config = $config; + $this->manager = $manager; + } + + /** + * Registers the hooks with WordPress. + * + * @return void + */ + public function register_hooks() { + \add_action( 'wpseo_save_indexable', [ $this, 'reset_cache' ], \PHP_INT_MAX, 2 ); + } + + /** + * Returns the needed conditionals. + * + * @return array + */ + public static function get_conditionals() { + return [ Site_Schema_Json_Conditional::class ]; + } + + /** + * This method resets the cache for the cached page where the changed indexable is located. + * + * @param Indexable $indexable The updated indexable. + * @param Indexable $indexable_before The state of the indexable before the update. + * + * @return bool + */ + public function reset_cache( $indexable, $indexable_before ) { + if ( $indexable_before->permalink === null ) { + $this->manager->invalidate_all(); + return false; + } + $page = $this->get_page_number( $indexable ); + $this->manager->invalidate( $page ); + + return true; + } + + /** + * Calculates which page an indexable appears on in a filtered, paginated list. + * + * This method accounts for deletions by counting the actual position in the result set, + * not just using the ID directly. + * + * @param Indexable $indexable The indexable to find the page for. + * @param array $post_type_exclude_list The list of excluded post types. + * + * @return int The page number (1-indexed) where this indexable appears. + */ + public function get_page_number( $indexable, $post_type_exclude_list = [] ) { + $query = $this->indexable_repository->query(); + + $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + if ( $post_type_exclude_list ) { + $query->where_not_in( 'object_sub_type', $post_type_exclude_list ); + } + + // Count how many records come before this indexable (have a smaller ID). + $count_before = $query + ->where_lt( 'id', $indexable->id ) + ->count(); + + return ( (int) \floor( $count_before / $this->config->get_per_page() ) + 1 ); + } +} From e3d12e34a9cf8f6d14cc8afccd02bb475c69aecb Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 28 Oct 2025 10:27:20 +0100 Subject: [PATCH 019/319] Rename --- .../aggregate-site-schema-command-handler.php | 61 ------ .../aggregate-site-schema-command.php | 38 ---- .../application/cache/manager.php | 203 ------------------ .../domain/page-controls.php | 52 ----- .../infrastructure/config.php | 106 --------- .../site-schema-json-conditional.php | 37 ---- .../to-aggregate-indexable-collector.php | 44 ---- ...indexables-update-listener-integration.php | 115 ---------- ...te-schema-aggregator-cache-cli-command.php | 87 -------- .../site-schema-aggregator-cli-command.php | 104 --------- .../site-schema-aggregator-route.php | 167 -------------- 11 files changed, 1014 deletions(-) delete mode 100644 src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php delete mode 100644 src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php delete mode 100644 src/nlweb/schema-aggregator/application/cache/manager.php delete mode 100644 src/nlweb/schema-aggregator/domain/page-controls.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/config.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/site-schema-json-conditional.php delete mode 100644 src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php delete mode 100644 src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php delete mode 100644 src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php delete mode 100644 src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php delete mode 100644 src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php deleted file mode 100644 index a171a45f09e..00000000000 --- a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ /dev/null @@ -1,61 +0,0 @@ -to_aggregate_indexable_collector = $to_aggregate_indexable_collector; - $this->meta_tags_context_memoizer = $meta_tags_context_memoizer; - } - - /** - * Handles the Aggregate_Site_Schema_Command. - * - * @param Aggregate_Site_Schema_Command $command The command. - * - * @return array The aggregated schema. - */ - public function handle( Aggregate_Site_Schema_Command $command ): array { - - $indexables = $this->to_aggregate_indexable_collector->get( - $command->get_page_controls()->get_page(), - $command->get_page_controls()->get_page_size() - ); - - // This part should be replaced by the rest of the system. - $schema = []; - foreach ( $indexables as $indexable ) { - $schema[] = $this->meta_tags_context_memoizer->get( $indexable, $indexable->object_sub_type )->presentation->schema; - } - return $schema; - } -} diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php b/src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php deleted file mode 100644 index 42411ba5cf4..00000000000 --- a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command.php +++ /dev/null @@ -1,38 +0,0 @@ -page_controls = new Page_Controls( $page, $per_page ); - } - - /** - * Gets the page controls. - * - * @return Page_Controls - */ - public function get_page_controls(): Page_Controls { - return $this->page_controls; - } -} diff --git a/src/nlweb/schema-aggregator/application/cache/manager.php b/src/nlweb/schema-aggregator/application/cache/manager.php deleted file mode 100644 index 1e1c6ca1a2b..00000000000 --- a/src/nlweb/schema-aggregator/application/cache/manager.php +++ /dev/null @@ -1,203 +0,0 @@ -config = $config; - } - - /** - * Get cached data for a page - * - * @param int $page Page number. - * @param int $per_page Items per page. - * - * @return array|null Cached data or null. - */ - public function get( int $page, int $per_page ): ?array { - try { - if ( ! $this->config->cache_enabled() ) { - return null; - } - if ( $page < 1 || $per_page < 1 ) { - return null; - } - - $key = $this->get_cache_key( $page, $per_page ); - - $data = \get_transient( $key ); - - if ( $data === false ) { - return null; - } - if ( ! \is_array( $data ) ) { - \delete_transient( $key ); - - return null; - } - - return $data; - - } catch ( Exception $e ) { - return null; - } - } - - /** - * Set cache data for a page - * - * @param int $page Page number. - * @param int $per_page Items per page. - * @param array $data Data to cache. - * - * @return bool Success. - */ - public function set( int $page, int $per_page, array $data ): bool { - try { - if ( $page < 1 || $per_page < 1 || ! \is_array( $data ) ) { - return false; - } - - $key = $this->get_cache_key( $page, $per_page ); - $expiration = $this->config->get_expiration( $data ); - - return \set_transient( $key, $data, $expiration ); - - } catch ( Exception $e ) { - return false; - } - } - - /** - * Invalidate cache for specific page/per_page combination or all pages - * - * Note: When invalidating a specific page without per_page, this clears - * ALL per_page variations for that page using a wildcard pattern. - * - * @param int|null $page Page number or null for all. - * @param int|null $per_page Items per page or null to clear all per_page variations. - * - * @return bool Success. - */ - public function invalidate( ?int $page = null, ?int $per_page = null ): bool { - if ( $page !== null && $per_page !== null ) { - // Clear specific page/per_page combination. - return \delete_transient( $this->get_cache_key( $page, $per_page ) ); - } - - if ( $page !== null && $per_page === null ) { - // Clear all per_page variations for this page. - global $wpdb; - - if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) { - return false; - } - - $pattern = '_transient_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; - $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery - $deleted = $wpdb->query( - $wpdb->prepare( - "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", - $pattern, - $timeout_pattern - ) - ); - - return $deleted !== false; - } - return $this->invalidate_all(); - } - - /** - * Invalidate all cache pages - * - * @return bool Success. - */ - public function invalidate_all(): bool { - try { - global $wpdb; - - if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) { - return false; - } - - // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version}. - $pattern = '_transient_' . self::CACHE_PREFIX . '_page_%'; - $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_%'; - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery - $deleted = $wpdb->query( - $wpdb->prepare( - "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", - $pattern, - $timeout_pattern - ) - ); - - if ( $deleted === false ) { - return false; - } - - return true; - - } catch ( Exception $e ) { - - return false; - } - } - - /** - * Generate cache key for page. - * - * @param int $page Page number. - * @param int $per_page Items per page. - * - * @return string Cache key. - */ - private function get_cache_key( int $page, int $per_page ): string { - return \sprintf( - '%s_page_%d_per_%d_v%d', - self::CACHE_PREFIX, - $page, - $per_page, - self::CACHE_VERSION - ); - } -} diff --git a/src/nlweb/schema-aggregator/domain/page-controls.php b/src/nlweb/schema-aggregator/domain/page-controls.php deleted file mode 100644 index c3eaafcede2..00000000000 --- a/src/nlweb/schema-aggregator/domain/page-controls.php +++ /dev/null @@ -1,52 +0,0 @@ -page = $page; - $this->page_size = $page_size; - } - - /** - * Gets the current page. - * - * @return int - */ - public function get_page(): int { - return $this->page; - } - - /** - * Gets the page size. - * - * @return int - */ - public function get_page_size(): int { - return $this->page_size; - } -} diff --git a/src/nlweb/schema-aggregator/infrastructure/config.php b/src/nlweb/schema-aggregator/infrastructure/config.php deleted file mode 100644 index 749f00dd6ea..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/config.php +++ /dev/null @@ -1,106 +0,0 @@ - $data Data to cache. - * - * @return int Expiration in seconds. - */ - public function get_expiration( array $data ): int { - $cache_ttl = self::DEFAULT_CACHE_TTL; - try { - $serialized = \serialize( $data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- Needed for size calculation. - - if ( $serialized === false ) { - return self::DEFAULT_CACHE_TTL; - } - - $size = \strlen( $serialized ); - - // Large payloads: cache longer. - if ( $size > 1048576 ) { - $cache_ttl = ( 6 * \HOUR_IN_SECONDS ); - } - - // Small payloads: cache shorter. - if ( $size < 102400 ) { - $cache_ttl = ( 30 * \MINUTE_IN_SECONDS ); - } - - $cache_ttl = \apply_filters( 'yoast_nlweb_cache_ttl', $cache_ttl ); - - if ( ! \is_int( $cache_ttl ) || $cache_ttl <= 0 ) { - return self::DEFAULT_CACHE_TTL; - } - - return $cache_ttl; - - } catch ( Exception $e ) { - return self::DEFAULT_CACHE_TTL; - } - } - - /** - * Check if caching is enabled. - * - * @return bool True if caching is enabled, false otherwise. - */ - public function cache_enabled(): bool { - $enabled = \apply_filters( 'yoast_nlweb_cache_enabled', true ); - - if ( \is_bool( $enabled ) ) { - return $enabled; - } - else { - return true; - } - } -} diff --git a/src/nlweb/schema-aggregator/infrastructure/site-schema-json-conditional.php b/src/nlweb/schema-aggregator/infrastructure/site-schema-json-conditional.php deleted file mode 100644 index fe0bf9a3f71..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/site-schema-json-conditional.php +++ /dev/null @@ -1,37 +0,0 @@ -options = $options; - } - - /** - * Returns whether the 'Site schema route' setting has been enabled. - * - * @return bool `true` when the 'Site schema route' setting has been enabled. - */ - public function is_met() { - return true; - } -} diff --git a/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php b/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php deleted file mode 100644 index fecad592e0e..00000000000 --- a/src/nlweb/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php +++ /dev/null @@ -1,44 +0,0 @@ -indexable_repository = $indexable_repository; - } - - /** - * Handles the Aggregate_Site_Schema_Command. - * - * @param int $page The page number (1-based). - * @param int $page_size The number of items per page. - * - * @return array The aggregated schema. - */ - public function get( $page, $page_size ): array { - - return $this->indexable_repository->find_all_public_paginated( - $page, - $page_size, - ); - } -} diff --git a/src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php deleted file mode 100644 index edae909dae1..00000000000 --- a/src/nlweb/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php +++ /dev/null @@ -1,115 +0,0 @@ -indexable_repository = $indexable_repository; - $this->config = $config; - $this->manager = $manager; - } - - /** - * Registers the hooks with WordPress. - * - * @return void - */ - public function register_hooks() { - \add_action( 'wpseo_save_indexable', [ $this, 'reset_cache' ], \PHP_INT_MAX, 2 ); - } - - /** - * Returns the needed conditionals. - * - * @return array - */ - public static function get_conditionals() { - return [ Site_Schema_Json_Conditional::class ]; - } - - /** - * This method resets the cache for the cached page where the changed indexable is located. - * - * @param Indexable $indexable The updated indexable. - * @param Indexable $indexable_before The state of the indexable before the update. - * - * @return bool - */ - public function reset_cache( $indexable, $indexable_before ) { - if ( $indexable_before->permalink === null ) { - $this->manager->invalidate_all(); - return false; - } - $page = $this->get_page_number( $indexable ); - $this->manager->invalidate( $page ); - - return true; - } - - /** - * Calculates which page an indexable appears on in a filtered, paginated list. - * - * This method accounts for deletions by counting the actual position in the result set, - * not just using the ID directly. - * - * @param Indexable $indexable The indexable to find the page for. - * @param array $post_type_exclude_list The list of excluded post types. - * - * @return int The page number (1-indexed) where this indexable appears. - */ - public function get_page_number( $indexable, $post_type_exclude_list = [] ) { - $query = $this->indexable_repository->query(); - - $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); - if ( $post_type_exclude_list ) { - $query->where_not_in( 'object_sub_type', $post_type_exclude_list ); - } - - // Count how many records come before this indexable (have a smaller ID). - $count_before = $query - ->where_lt( 'id', $indexable->id ) - ->count(); - - return ( (int) \floor( $count_before / $this->config->get_per_page() ) + 1 ); - } -} diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php deleted file mode 100644 index 9f43d59c87f..00000000000 --- a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php +++ /dev/null @@ -1,87 +0,0 @@ -config = $config; - $this->cache_manager = $cache_manager; - } - - /** - * Returns the namespace of this command. - * - * @return string - */ - public static function get_namespace() { - return Main::WP_CLI_NAMESPACE; - } - - /** - * Aggregates the schema for a certain site. - * - * ## OPTIONS - * - * [--page=] - * : The current page to process. - * --- - * ## EXAMPLES - * - * wp yoast aggregate_site_schema_clear_cache - * - * @when after_wp_load - * - * @param array|null $args The arguments. - * @param array|null $assoc_args The associative arguments. - * - * @throws ExitException When the input args are invalid. - * @return void - */ - public function aggregate_site_schema_clear_cache( $args = null, $assoc_args = null ) { - if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] >= 1 ) { - $this->cache_manager->invalidate( $assoc_args['page'] ); - WP_CLI::log( - \__( 'The site schema cache has been cleared successfully.', 'wordpress-seo' ) - ); - return; - } - $this->cache_manager->invalidate_all(); - - WP_CLI::log( - \__( 'All site schema cache has been cleared successfully.', 'wordpress-seo' ) - ); - } -} diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php deleted file mode 100644 index e249565f8bf..00000000000 --- a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php +++ /dev/null @@ -1,104 +0,0 @@ -config = $config; - $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; - } - - /** - * Returns the namespace of this command. - * - * @return string - */ - public static function get_namespace() { - return Main::WP_CLI_NAMESPACE; - } - - /** - * Aggregates the schema for a certain site. - * - * ## OPTIONS - * - * [--page=] - * : The current page to process. - * --- - * default: 1 - * --- - * - * [--per_page=] - * : How many items to process per page. - * --- - * default: 100 - - * ## EXAMPLES - * - * wp yoast aggregate_site_schema - * - * @when after_wp_load - * - * @param array|null $args The arguments. - * @param array|null $assoc_args The associative arguments. - * - * @return void - * - * @throws ExitException When the input args are invalid. - */ - public function aggregate_site_schema( $args = null, $assoc_args = null ) { - if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] < 1 ) { - WP_CLI::error( \__( 'The value for \'page\' must be a positive integer higher than equal to 1.', 'wordpress-seo' ) ); - } - if ( isset( $assoc_args['per_page'] ) && (int) $assoc_args['per_page'] < 1 ) { - WP_CLI::error( \__( 'The value for \'per_page\' must be a positive integer higher than equal to 1.', 'wordpress-seo' ) ); - } - $page = (int) $assoc_args['page']; - $per_page = (int) $assoc_args['per_page']; - try { - $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); - } catch ( Exception $exception ) { - WP_CLI::error( \__( 'An error occurred while aggregating the site schema.', 'wordpress-seo' ) ); - } - $output = WPSEO_Utils::format_json_encode( $result ); - $output = \str_replace( "\n", \PHP_EOL . "\t", $output ); - WP_CLI::log( - $output - ); - } -} diff --git a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php deleted file mode 100644 index 74b6d61373c..00000000000 --- a/src/nlweb/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ /dev/null @@ -1,167 +0,0 @@ - The conditionals that must be met to load this. - */ - public static function get_conditionals() { - return [ Site_Schema_Json_Conditional::class ]; - } - - /** - * Site_Schema_Aggregator_Route constructor. - * - * @param Config $config The config object. - * @param Capability_Helper $capability_helper The capability helper. - * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler. - * @param Manager $cache_manager The cache manager. - */ - public function __construct( - Config $config, - Capability_Helper $capability_helper, - Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler, - Manager $cache_manager - ) { - $this->config = $config; - $this->capability_helper = $capability_helper; - $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; - $this->cache_manager = $cache_manager; - } - - /** - * Registers routes with WordPress. - * - * @return void - */ - public function register_routes() { - $schema_aggregator_route = [ - 'methods' => 'GET', - 'callback' => [ $this, 'aggregate_site_schema' ], - 'permission_callback' => [ $this, 'get_permission_callback' ], - 'args' => [ - 'page' => [ - 'default' => 1, - 'validate_callback' => static function ( $param ) { - return \is_numeric( $param ) && $param > 0; - }, - 'sanitize_callback' => 'absint', - ], - 'per_page' => [ - 'default' => $this->config->get_per_page(), - 'validate_callback' => function ( $param ) { - return \is_numeric( $param ) && $param > 0 && $param <= $this->config->get_per_page_max(); - }, - 'sanitize_callback' => 'absint', - ], - ], - ]; - - \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE, $schema_aggregator_route ); - } - - /** - * Permission callback for the route. - * - * @return bool True if the user has permission, false otherwise. - */ - public function get_permission_callback(): bool { - return true; - } - - /** - * Returns a JSON representation of a site. - * - * @param WP_REST_Request $request The request object. - * - * @return WP_REST_Response|WP_Error The success or failure response. - */ - public function aggregate_site_schema( WP_REST_Request $request ) { - $page = $request->get_param( 'page' ); - $per_page = $request->get_param( 'per_page' ); - - $output = $this->cache_manager->get( $page, $per_page ); - if ( $output === null ) { - try { - $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); - $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); - $this->cache_manager->set( $page, $per_page, $result ); - - } catch ( Exception $exception ) { - return new WP_Error( - 'wpseo_aggregate_site_schema_error', - $exception->getMessage(), - (object) [] - ); - } - } - $response = \rest_ensure_response( $output ); - - $response->header( 'Cache-Control', 'public, max-age=300' ); - - return $response; - } -} From 7f832130dcf59df5a250fca56adaa2ce1656a2fa Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 28 Oct 2025 10:30:20 +0100 Subject: [PATCH 020/319] Rename --- .../aggregate-site-schema-command-handler.php | 61 ++++++ .../aggregate-site-schema-command.php | 38 ++++ .../application/cache/manager.php | 203 ++++++++++++++++++ .../domain/page-controls.php | 52 +++++ .../infrastructure/config.php | 106 +++++++++ .../site-schema-json-conditional.php | 37 ++++ .../to-aggregate-indexable-collector.php | 44 ++++ ...indexables-update-listener-integration.php | 115 ++++++++++ ...te-schema-aggregator-cache-cli-command.php | 87 ++++++++ .../site-schema-aggregator-cli-command.php | 104 +++++++++ .../site-schema-aggregator-route.php | 167 ++++++++++++++ 11 files changed, 1014 insertions(+) create mode 100644 src/schema-aggregator/application/aggregate-site-schema-command-handler.php create mode 100644 src/schema-aggregator/application/aggregate-site-schema-command.php create mode 100644 src/schema-aggregator/application/cache/manager.php create mode 100644 src/schema-aggregator/domain/page-controls.php create mode 100644 src/schema-aggregator/infrastructure/config.php create mode 100644 src/schema-aggregator/infrastructure/site-schema-json-conditional.php create mode 100644 src/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php create mode 100644 src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php create mode 100644 src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php create mode 100644 src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php create mode 100644 src/schema-aggregator/user-interface/site-schema-aggregator-route.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php new file mode 100644 index 00000000000..63e94e062be --- /dev/null +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -0,0 +1,61 @@ +to_aggregate_indexable_collector = $to_aggregate_indexable_collector; + $this->meta_tags_context_memoizer = $meta_tags_context_memoizer; + } + + /** + * Handles the Aggregate_Site_Schema_Command. + * + * @param Aggregate_Site_Schema_Command $command The command. + * + * @return array The aggregated schema. + */ + public function handle( Aggregate_Site_Schema_Command $command ): array { + + $indexables = $this->to_aggregate_indexable_collector->get( + $command->get_page_controls()->get_page(), + $command->get_page_controls()->get_page_size() + ); + + // This part should be replaced by the rest of the system. + $schema = []; + foreach ( $indexables as $indexable ) { + $schema[] = $this->meta_tags_context_memoizer->get( $indexable, $indexable->object_sub_type )->presentation->schema; + } + return $schema; + } +} diff --git a/src/schema-aggregator/application/aggregate-site-schema-command.php b/src/schema-aggregator/application/aggregate-site-schema-command.php new file mode 100644 index 00000000000..7353b7ad84c --- /dev/null +++ b/src/schema-aggregator/application/aggregate-site-schema-command.php @@ -0,0 +1,38 @@ +page_controls = new Page_Controls( $page, $per_page ); + } + + /** + * Gets the page controls. + * + * @return Page_Controls + */ + public function get_page_controls(): Page_Controls { + return $this->page_controls; + } +} diff --git a/src/schema-aggregator/application/cache/manager.php b/src/schema-aggregator/application/cache/manager.php new file mode 100644 index 00000000000..f6ef3d61c83 --- /dev/null +++ b/src/schema-aggregator/application/cache/manager.php @@ -0,0 +1,203 @@ +config = $config; + } + + /** + * Get cached data for a page + * + * @param int $page Page number. + * @param int $per_page Items per page. + * + * @return array|null Cached data or null. + */ + public function get( int $page, int $per_page ): ?array { + try { + if ( ! $this->config->cache_enabled() ) { + return null; + } + if ( $page < 1 || $per_page < 1 ) { + return null; + } + + $key = $this->get_cache_key( $page, $per_page ); + + $data = \get_transient( $key ); + + if ( $data === false ) { + return null; + } + if ( ! \is_array( $data ) ) { + \delete_transient( $key ); + + return null; + } + + return $data; + + } catch ( Exception $e ) { + return null; + } + } + + /** + * Set cache data for a page + * + * @param int $page Page number. + * @param int $per_page Items per page. + * @param array $data Data to cache. + * + * @return bool Success. + */ + public function set( int $page, int $per_page, array $data ): bool { + try { + if ( $page < 1 || $per_page < 1 || ! \is_array( $data ) ) { + return false; + } + + $key = $this->get_cache_key( $page, $per_page ); + $expiration = $this->config->get_expiration( $data ); + + return \set_transient( $key, $data, $expiration ); + + } catch ( Exception $e ) { + return false; + } + } + + /** + * Invalidate cache for specific page/per_page combination or all pages + * + * Note: When invalidating a specific page without per_page, this clears + * ALL per_page variations for that page using a wildcard pattern. + * + * @param int|null $page Page number or null for all. + * @param int|null $per_page Items per page or null to clear all per_page variations. + * + * @return bool Success. + */ + public function invalidate( ?int $page = null, ?int $per_page = null ): bool { + if ( $page !== null && $per_page !== null ) { + // Clear specific page/per_page combination. + return \delete_transient( $this->get_cache_key( $page, $per_page ) ); + } + + if ( $page !== null && $per_page === null ) { + // Clear all per_page variations for this page. + global $wpdb; + + if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) { + return false; + } + + $pattern = '_transient_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; + $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%'; + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery + $deleted = $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + $pattern, + $timeout_pattern + ) + ); + + return $deleted !== false; + } + return $this->invalidate_all(); + } + + /** + * Invalidate all cache pages + * + * @return bool Success. + */ + public function invalidate_all(): bool { + try { + global $wpdb; + + if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) { + return false; + } + + // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version}. + $pattern = '_transient_' . self::CACHE_PREFIX . '_page_%'; + $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_%'; + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery + $deleted = $wpdb->query( + $wpdb->prepare( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + $pattern, + $timeout_pattern + ) + ); + + if ( $deleted === false ) { + return false; + } + + return true; + + } catch ( Exception $e ) { + + return false; + } + } + + /** + * Generate cache key for page. + * + * @param int $page Page number. + * @param int $per_page Items per page. + * + * @return string Cache key. + */ + private function get_cache_key( int $page, int $per_page ): string { + return \sprintf( + '%s_page_%d_per_%d_v%d', + self::CACHE_PREFIX, + $page, + $per_page, + self::CACHE_VERSION + ); + } +} diff --git a/src/schema-aggregator/domain/page-controls.php b/src/schema-aggregator/domain/page-controls.php new file mode 100644 index 00000000000..3923390f306 --- /dev/null +++ b/src/schema-aggregator/domain/page-controls.php @@ -0,0 +1,52 @@ +page = $page; + $this->page_size = $page_size; + } + + /** + * Gets the current page. + * + * @return int + */ + public function get_page(): int { + return $this->page; + } + + /** + * Gets the page size. + * + * @return int + */ + public function get_page_size(): int { + return $this->page_size; + } +} diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php new file mode 100644 index 00000000000..8760fad5050 --- /dev/null +++ b/src/schema-aggregator/infrastructure/config.php @@ -0,0 +1,106 @@ + $data Data to cache. + * + * @return int Expiration in seconds. + */ + public function get_expiration( array $data ): int { + $cache_ttl = self::DEFAULT_CACHE_TTL; + try { + $serialized = \serialize( $data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- Needed for size calculation. + + if ( $serialized === false ) { + return self::DEFAULT_CACHE_TTL; + } + + $size = \strlen( $serialized ); + + // Large payloads: cache longer. + if ( $size > 1048576 ) { + $cache_ttl = ( 6 * \HOUR_IN_SECONDS ); + } + + // Small payloads: cache shorter. + if ( $size < 102400 ) { + $cache_ttl = ( 30 * \MINUTE_IN_SECONDS ); + } + + $cache_ttl = \apply_filters( 'yoast_schema_aggregator_cache_ttl', $cache_ttl ); + + if ( ! \is_int( $cache_ttl ) || $cache_ttl <= 0 ) { + return self::DEFAULT_CACHE_TTL; + } + + return $cache_ttl; + + } catch ( Exception $e ) { + return self::DEFAULT_CACHE_TTL; + } + } + + /** + * Check if caching is enabled. + * + * @return bool True if caching is enabled, false otherwise. + */ + public function cache_enabled(): bool { + $enabled = \apply_filters( 'yoast_schema_aggregator_cache_enabled', true ); + + if ( \is_bool( $enabled ) ) { + return $enabled; + } + else { + return true; + } + } +} diff --git a/src/schema-aggregator/infrastructure/site-schema-json-conditional.php b/src/schema-aggregator/infrastructure/site-schema-json-conditional.php new file mode 100644 index 00000000000..7e9fd72deff --- /dev/null +++ b/src/schema-aggregator/infrastructure/site-schema-json-conditional.php @@ -0,0 +1,37 @@ +options = $options; + } + + /** + * Returns whether the 'Site schema route' setting has been enabled. + * + * @return bool `true` when the 'Site schema route' setting has been enabled. + */ + public function is_met() { + return true; + } +} diff --git a/src/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php b/src/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php new file mode 100644 index 00000000000..087b88362b1 --- /dev/null +++ b/src/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php @@ -0,0 +1,44 @@ +indexable_repository = $indexable_repository; + } + + /** + * Handles the Aggregate_Site_Schema_Command. + * + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * + * @return array The aggregated schema. + */ + public function get( $page, $page_size ): array { + + return $this->indexable_repository->find_all_public_paginated( + $page, + $page_size, + ); + } +} diff --git a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php new file mode 100644 index 00000000000..5c3ba60d79f --- /dev/null +++ b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -0,0 +1,115 @@ +indexable_repository = $indexable_repository; + $this->config = $config; + $this->manager = $manager; + } + + /** + * Registers the hooks with WordPress. + * + * @return void + */ + public function register_hooks() { + \add_action( 'wpseo_save_indexable', [ $this, 'reset_cache' ], \PHP_INT_MAX, 2 ); + } + + /** + * Returns the needed conditionals. + * + * @return array + */ + public static function get_conditionals() { + return [ Site_Schema_Json_Conditional::class ]; + } + + /** + * This method resets the cache for the cached page where the changed indexable is located. + * + * @param Indexable $indexable The updated indexable. + * @param Indexable $indexable_before The state of the indexable before the update. + * + * @return bool + */ + public function reset_cache( $indexable, $indexable_before ) { + if ( $indexable_before->permalink === null ) { + $this->manager->invalidate_all(); + return false; + } + $page = $this->get_page_number( $indexable ); + $this->manager->invalidate( $page ); + + return true; + } + + /** + * Calculates which page an indexable appears on in a filtered, paginated list. + * + * This method accounts for deletions by counting the actual position in the result set, + * not just using the ID directly. + * + * @param Indexable $indexable The indexable to find the page for. + * @param array $post_type_exclude_list The list of excluded post types. + * + * @return int The page number (1-indexed) where this indexable appears. + */ + public function get_page_number( $indexable, $post_type_exclude_list = [] ) { + $query = $this->indexable_repository->query(); + + $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + if ( $post_type_exclude_list ) { + $query->where_not_in( 'object_sub_type', $post_type_exclude_list ); + } + + // Count how many records come before this indexable (have a smaller ID). + $count_before = $query + ->where_lt( 'id', $indexable->id ) + ->count(); + + return ( (int) \floor( $count_before / $this->config->get_per_page() ) + 1 ); + } +} diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php new file mode 100644 index 00000000000..a150588cbf6 --- /dev/null +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php @@ -0,0 +1,87 @@ +config = $config; + $this->cache_manager = $cache_manager; + } + + /** + * Returns the namespace of this command. + * + * @return string + */ + public static function get_namespace() { + return Main::WP_CLI_NAMESPACE; + } + + /** + * Aggregates the schema for a certain site. + * + * ## OPTIONS + * + * [--page=] + * : The current page to process. + * --- + * ## EXAMPLES + * + * wp yoast aggregate_site_schema_clear_cache + * + * @when after_wp_load + * + * @param array|null $args The arguments. + * @param array|null $assoc_args The associative arguments. + * + * @throws ExitException When the input args are invalid. + * @return void + */ + public function aggregate_site_schema_clear_cache( $args = null, $assoc_args = null ) { + if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] >= 1 ) { + $this->cache_manager->invalidate( $assoc_args['page'] ); + WP_CLI::log( + \__( 'The site schema cache has been cleared successfully.', 'wordpress-seo' ) + ); + return; + } + $this->cache_manager->invalidate_all(); + + WP_CLI::log( + \__( 'All site schema cache has been cleared successfully.', 'wordpress-seo' ) + ); + } +} diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php new file mode 100644 index 00000000000..68c7c8980e7 --- /dev/null +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php @@ -0,0 +1,104 @@ +config = $config; + $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; + } + + /** + * Returns the namespace of this command. + * + * @return string + */ + public static function get_namespace() { + return Main::WP_CLI_NAMESPACE; + } + + /** + * Aggregates the schema for a certain site. + * + * ## OPTIONS + * + * [--page=] + * : The current page to process. + * --- + * default: 1 + * --- + * + * [--per_page=] + * : How many items to process per page. + * --- + * default: 100 + + * ## EXAMPLES + * + * wp yoast aggregate_site_schema + * + * @when after_wp_load + * + * @param array|null $args The arguments. + * @param array|null $assoc_args The associative arguments. + * + * @return void + * + * @throws ExitException When the input args are invalid. + */ + public function aggregate_site_schema( $args = null, $assoc_args = null ) { + if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] < 1 ) { + WP_CLI::error( \__( 'The value for \'page\' must be a positive integer higher than equal to 1.', 'wordpress-seo' ) ); + } + if ( isset( $assoc_args['per_page'] ) && (int) $assoc_args['per_page'] < 1 ) { + WP_CLI::error( \__( 'The value for \'per_page\' must be a positive integer higher than equal to 1.', 'wordpress-seo' ) ); + } + $page = (int) $assoc_args['page']; + $per_page = (int) $assoc_args['per_page']; + try { + $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); + } catch ( Exception $exception ) { + WP_CLI::error( \__( 'An error occurred while aggregating the site schema.', 'wordpress-seo' ) ); + } + $output = WPSEO_Utils::format_json_encode( $result ); + $output = \str_replace( "\n", \PHP_EOL . "\t", $output ); + WP_CLI::log( + $output + ); + } +} diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php new file mode 100644 index 00000000000..a31e8cfc1a8 --- /dev/null +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -0,0 +1,167 @@ + The conditionals that must be met to load this. + */ + public static function get_conditionals() { + return [ Site_Schema_Json_Conditional::class ]; + } + + /** + * Site_Schema_Aggregator_Route constructor. + * + * @param Config $config The config object. + * @param Capability_Helper $capability_helper The capability helper. + * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler. + * @param Manager $cache_manager The cache manager. + */ + public function __construct( + Config $config, + Capability_Helper $capability_helper, + Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler, + Manager $cache_manager + ) { + $this->config = $config; + $this->capability_helper = $capability_helper; + $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; + $this->cache_manager = $cache_manager; + } + + /** + * Registers routes with WordPress. + * + * @return void + */ + public function register_routes() { + $schema_aggregator_route = [ + 'methods' => 'GET', + 'callback' => [ $this, 'aggregate_site_schema' ], + 'permission_callback' => [ $this, 'get_permission_callback' ], + 'args' => [ + 'page' => [ + 'default' => 1, + 'validate_callback' => static function ( $param ) { + return \is_numeric( $param ) && $param > 0; + }, + 'sanitize_callback' => 'absint', + ], + 'per_page' => [ + 'default' => $this->config->get_per_page(), + 'validate_callback' => function ( $param ) { + return \is_numeric( $param ) && $param > 0 && $param <= $this->config->get_per_page_max(); + }, + 'sanitize_callback' => 'absint', + ], + ], + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE, $schema_aggregator_route ); + } + + /** + * Permission callback for the route. + * + * @return bool True if the user has permission, false otherwise. + */ + public function get_permission_callback(): bool { + return true; + } + + /** + * Returns a JSON representation of a site. + * + * @param WP_REST_Request $request The request object. + * + * @return WP_REST_Response|WP_Error The success or failure response. + */ + public function aggregate_site_schema( WP_REST_Request $request ) { + $page = $request->get_param( 'page' ); + $per_page = $request->get_param( 'per_page' ); + + $output = $this->cache_manager->get( $page, $per_page ); + if ( $output === null ) { + try { + $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); + $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); + $this->cache_manager->set( $page, $per_page, $result ); + + } catch ( Exception $exception ) { + return new WP_Error( + 'wpseo_aggregate_site_schema_error', + $exception->getMessage(), + (object) [] + ); + } + } + $response = \rest_ensure_response( $output ); + + $response->header( 'Cache-Control', 'public, max-age=300' ); + + return $response; + } +} From ad2fbb385b7d7dd077f76f180bbc634613a6c148 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 28 Oct 2025 10:34:20 +0100 Subject: [PATCH 021/319] Rename. --- .../aggregate-site-schema-command-handler.php | 4 ++-- .../application/aggregate-site-schema-command.php | 4 ++-- .../domain/page-controls.php | 2 +- .../domain/schema-piece-repository-interface.php | 2 +- .../domain/schema-piece.php | 2 +- .../infrastructure/config.php | 4 ++-- .../meta-tags-context-memoizer-adapter.php | 2 +- .../infrastructure/schema-piece-repository.php | 6 +++--- .../infrastructure/site-schema-json-conditional.php | 2 +- .../site-schema-aggregator-cli-command.php | 8 ++++---- .../user-interface/site-schema-aggregator-route.php | 12 ++++++------ 11 files changed, 24 insertions(+), 24 deletions(-) rename src/{nlweb/schema-aggregator => schema_generator}/application/aggregate-site-schema-command-handler.php (90%) rename src/{nlweb/schema-aggregator => schema_generator}/application/aggregate-site-schema-command.php (85%) rename src/{nlweb/schema-aggregator => schema_generator}/domain/page-controls.php (93%) rename src/{nlweb/schema-aggregator => schema_generator}/domain/schema-piece-repository-interface.php (89%) rename src/{nlweb/schema-aggregator => schema_generator}/domain/schema-piece.php (97%) rename src/{nlweb/schema-aggregator => schema_generator}/infrastructure/config.php (78%) rename src/{nlweb/schema-aggregator => schema_generator}/infrastructure/meta-tags-context-memoizer-adapter.php (90%) rename src/{nlweb/schema-aggregator => schema_generator}/infrastructure/schema-piece-repository.php (92%) rename src/{nlweb/schema-aggregator => schema_generator}/infrastructure/site-schema-json-conditional.php (93%) rename src/{nlweb/schema-aggregator => schema_generator}/user-interface/site-schema-aggregator-cli-command.php (90%) rename src/{nlweb/schema-aggregator => schema_generator}/user-interface/site-schema-aggregator-route.php (90%) diff --git a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema_generator/application/aggregate-site-schema-command-handler.php similarity index 90% rename from src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php rename to src/schema_generator/application/aggregate-site-schema-command-handler.php index 9eb7371d7eb..1f60b075350 100644 --- a/src/nlweb/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema_generator/application/aggregate-site-schema-command-handler.php @@ -1,9 +1,9 @@ Date: Wed, 29 Oct 2025 09:30:50 +0100 Subject: [PATCH 022/319] Start implementation --- .../enhancement/article-schema-enhancer.php | 20 +++++++++++++ .../enhancement/person-schema-enhancer.php | 20 +++++++++++++ .../schema-enhancement-factory.php | 28 +++++++++++++++++++ .../schema-enhancement-interface.php | 17 +++++++++++ 4 files changed, 85 insertions(+) create mode 100644 src/schema_generator/application/enhancement/article-schema-enhancer.php create mode 100644 src/schema_generator/application/enhancement/person-schema-enhancer.php create mode 100644 src/schema_generator/application/enhancement/schema-enhancement-factory.php create mode 100644 src/schema_generator/domain/enhancement/schema-enhancement-interface.php diff --git a/src/schema_generator/application/enhancement/article-schema-enhancer.php b/src/schema_generator/application/enhancement/article-schema-enhancer.php new file mode 100644 index 00000000000..9b14ce55202 --- /dev/null +++ b/src/schema_generator/application/enhancement/article-schema-enhancer.php @@ -0,0 +1,20 @@ + Date: Mon, 27 Oct 2025 15:18:24 +0100 Subject: [PATCH 023/319] Store in data only the inner graph properties --- src/schema_generator/infrastructure/schema-piece-repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema_generator/infrastructure/schema-piece-repository.php b/src/schema_generator/infrastructure/schema-piece-repository.php index 8144b005933..b8970e72fa1 100644 --- a/src/schema_generator/infrastructure/schema-piece-repository.php +++ b/src/schema_generator/infrastructure/schema-piece-repository.php @@ -81,7 +81,7 @@ public function get( int $page, int $page_size ): array { $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); $context = $this->memoizer->get( $indexable, $page_type ); $context_array = $this->adapter->meta_tags_context_to_array( $context ); - $schema_pieces[] = new Schema_Piece( $context_array, $page_type ); + $schema_pieces[] = new Schema_Piece( $context_array['@graph'][0], $page_type ); } return $schema_pieces; From a24aee73402249ca2a4700e6294545f9f061a97e Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 27 Oct 2025 15:19:11 +0100 Subject: [PATCH 024/319] Remove unused methods, add the get_id one and adapt the to_json_ld_graph one --- src/schema_generator/domain/schema-piece.php | 26 +++++++------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/schema_generator/domain/schema-piece.php b/src/schema_generator/domain/schema-piece.php index 57cd8ee3cbb..275f8fa1baa 100644 --- a/src/schema_generator/domain/schema-piece.php +++ b/src/schema_generator/domain/schema-piece.php @@ -54,33 +54,25 @@ public function get_data(): array { } /** - * Encodes the schema piece in JSON-LD format. + * Gets the ID of the schema piece. * - * @return string The JSON-LD representation. + * @return string|null The ID of the schema piece, or null if not set. */ - public function to_json_ld(): string { - return WPSEO_Utils::format_json_encode( $this->data ); + public function get_id(): ?string { + return $this->data['@id'] ?? null; } /** * Converts multiple schema pieces to a JSON-LD-encoded graph. * * @param Schema_Piece[] $schema_pieces Array of schema pieces. - * @return string The JSON-LD graph representation. + * + * @return array The JSON-LD graph representation. */ - public static function to_json_ld_graph( array $schema_pieces ): string { - $graph = []; - foreach ( $schema_pieces as $piece ) { - if ( $piece instanceof self ) { - $graph[] = $piece->data; - } - } - - $schema_graph = [ + public function to_json_ld_graph(): array { + return [ '@context' => 'https://schema.org', - '@graph' => $graph, + '@graph' => $this->data, ]; - - return WPSEO_Utils::format_json_encode( $schema_graph ); } } From e5636fcb0df671e499400284d252c9e260b14d48 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 27 Oct 2025 15:20:55 +0100 Subject: [PATCH 025/319] Introduce the schema piece aggregator --- .../application/schema-pieces-aggregator.php | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 src/schema_generator/application/schema-pieces-aggregator.php diff --git a/src/schema_generator/application/schema-pieces-aggregator.php b/src/schema_generator/application/schema-pieces-aggregator.php new file mode 100644 index 00000000000..fa5c0da6daf --- /dev/null +++ b/src/schema_generator/application/schema-pieces-aggregator.php @@ -0,0 +1,188 @@ + $schema_pieces The schema pieces to aggregate. + */ + public function aggregate( array $schema_pieces ): array { + $aggregated_schema = []; + + foreach ( $schema_pieces as $piece ) { + $data = $piece->get_data(); + $type = $piece->get_type(); + $id = $piece->get_id(); + if ( \is_null( $id ) ) { + continue; + } + + if ( isset( $aggregated_schema[ $id ] ) ) { + // Merge properties if the piece already exists. + $aggregated_schema[ $id ] = new Schema_Piece( $this->merge_properties( $aggregated_schema[ $id ]->get_data(), $data ), $type ); + + } + else { + // Add new piece. + $aggregated_schema[ $id ] = new Schema_Piece( $data, $type ); + } + } + + // Return only the values to get rid of the keys (which are @id). + return \array_values( $aggregated_schema ); + } + + /** + * Merge properties from two schema entities with the same @id + * + * Strategy (FR-012): + * - @type: Special handling - merge types into unified array + * - @id: Skip (always the same) + * - Arrays: Combine unique values + * - Scalars: Prefer non-empty over empty + * - Objects: Deep merge recursively + * - Null vs value: Prefer non-null + * + * @param array $entity1 First entity. + * @param array $entity2 Second entity. + * @return array Merged entity. + */ + private function merge_properties( array $entity1, array $entity2 ): array { + $merged = $entity1; + + foreach ( $entity2 as $key => $value ) { + // Skip @id - these should always be the same + if ( $key === '@id' ) { + continue; + } + + // Special handling for @type - merge types (JSON-LD allows multiple types) + if ( $key === '@type' ) { + $merged['@type'] = $this->merge_types( + $merged['@type'] ?? null, + $value + ); + continue; + } + + if ( ! isset( $merged[ $key ] ) || $merged[ $key ] === '' ) { + // Property doesn't exist in entity1 or is empty - use entity2's value + $merged[ $key ] = $value; + } + elseif ( \is_array( $merged[ $key ] ) && \is_array( $value ) ) { + // Both are arrays - check if associative (object) or indexed (list) + if ( $this->is_associative_array( $merged[ $key ] ) || $this->is_associative_array( $value ) ) { + // Deep merge objects + $merged[ $key ] = $this->merge_properties( $merged[ $key ], $value ); + } + else { + // Combine arrays and get unique values + $merged[ $key ] = \array_values( \array_unique( \array_merge( $merged[ $key ], $value ), \SORT_REGULAR ) ); + } + } + // Else: entity1's value is non-empty scalar, keep it (prefer first occurrence) + } + + return $merged; + } + + /** + * Merge @type values from two entities + * + * JSON-LD allows @type to be either a string or an array of strings. + * This method combines types from both entities, deduplicates them, + * and normalizes the result (string if 1 type, array if multiple). + * + * Examples: + * - merge_types("Person", "Person") → "Person" + * - merge_types("Person", "Author") → ["Person", "Author"] + * - merge_types("Person", ["Author", "Employee"]) → ["Person", "Author", "Employee"] + * - merge_types(["Person"], "Person") → "Person" + * - merge_types(["Person", "Author"], ["Author", "Employee"]) → ["Person", "Author", "Employee"] + * + * @param string|array|null $type1 First @type value. + * @param string|array|null $type2 Second @type value. + * @return string|array Merged and normalized @type value. + */ + private function merge_types( $type1, $type2 ) { + // Normalize both to arrays + $types1 = $this->normalize_type_to_array( $type1 ); + $types2 = $this->normalize_type_to_array( $type2 ); + + // Combine and deduplicate + $merged = \array_unique( \array_merge( $types1, $types2 ), \SORT_REGULAR ); + + // Normalize result: string if 1 type, array if multiple + return $this->normalize_type_from_array( $merged ); + } + + /** + * Normalize @type value to array format + * + * @param string|array|null $type Type value to normalize. + * @return array Array of type strings. + */ + private function normalize_type_to_array( $type ): array { + if ( $type === null ) { + return []; + } + + if ( \is_string( $type ) ) { + return [ $type ]; + } + + if ( \is_array( $type ) ) { + // Filter out non-strings for safety + return \array_values( \array_filter( $type, 'is_string' ) ); + } + + // Invalid type format + \error_log( 'Yoast NLWeb Aggregator: Invalid @type format: ' . \gettype( $type ) ); + return []; + } + + /** + * Normalize array of types back to string or array + * + * Returns string if single type, array if multiple types. + * This keeps the output compact while supporting multi-type entities. + * + * @param array $types Array of type strings. + * @return string|array Normalized type value. + */ + private function normalize_type_from_array( array $types ) { + // Remove duplicates and re-index + $types = \array_values( \array_unique( $types ) ); + + if ( empty( $types ) ) { + // Fallback - should not happen in normal flow + return 'Thing'; // schema.org root type + } + + if ( \count( $types ) === 1 ) { + return $types[0]; // Return as string for single type + } + + return $types; // Return as array for multiple types + } + + /** + * Check if array is associative (object-like) vs indexed (list-like) + * + * @param array $array Array to check. + * @return bool True if associative. + */ + private function is_associative_array( array $array ): bool { + if ( empty( $array ) ) { + return false; + } + return \array_keys( $array ) !== \range( 0, ( \count( $array ) - 1 ) ); + } +} From 1904ecb2c82b57d9b32f9d610d366cbd88b8fd70 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 27 Oct 2025 15:21:12 +0100 Subject: [PATCH 026/319] update the command handler to use the aggregator --- .../aggregate-site-schema-command-handler.php | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/schema_generator/application/aggregate-site-schema-command-handler.php b/src/schema_generator/application/aggregate-site-schema-command-handler.php index 1f60b075350..b95750e211b 100644 --- a/src/schema_generator/application/aggregate-site-schema-command-handler.php +++ b/src/schema_generator/application/aggregate-site-schema-command-handler.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Piece_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Application\Schema_Pieces_Aggregator; /** * Class that handles the Aggregate_Site_Schema_Command. @@ -17,13 +18,23 @@ class Aggregate_Site_Schema_Command_Handler { */ private $schema_piece_repository; + /** + * The Schema_Pieces_Aggregator instance. + * + * @var Schema_Pieces_Aggregator + */ + private $schema_piece_aggregator; + /** * Aggregate_Site_Schema_Command_Handler constructor. * * @param Schema_Piece_Repository $schema_piece_repository The collector of indexables that need to be aggregated. + * @param Schema_Pieces_Aggregator $schema_piece_aggregator The schema pieces aggregator. + * */ - public function __construct( Schema_Piece_Repository $schema_piece_repository ) { + public function __construct( Schema_Piece_Repository $schema_piece_repository, Schema_Pieces_Aggregator $schema_piece_aggregator ) { $this->schema_piece_repository = $schema_piece_repository; + $this->schema_piece_aggregator = $schema_piece_aggregator; } /** @@ -40,10 +51,10 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { $command->get_page_controls()->get_page_size() ); - // This part should be replaced by the rest of the system. + $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); $schema = []; - foreach ( $schema_pieces as $schema_piece ) { - $schema[] = $schema_piece->get_data(); + foreach ( $aggregated_schema_pieces as $schema_piece ) { + $schema[] = $schema_piece->to_json_ld_graph(); } return $schema; } From 9dc13f3edd7f3beca375223351543ba71bd7a3e1 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:22:13 +0100 Subject: [PATCH 027/319] Move files --- .../aggregate-site-schema-command.php | 0 .../domain/page-controls.php | 0 .../schema-piece-repository-interface.php | 0 .../meta-tags-context-memoizer-adapter.php | 0 .../site-schema-json-conditional.php | 0 .../site-schema-aggregator-cli-command.php | 0 .../site-schema-aggregator-route.php | 2 +- .../aggregate-site-schema-command-handler.php | 61 ------ .../application/schema-pieces-aggregator.php | 188 ------------------ src/schema_generator/domain/schema-piece.php | 78 -------- .../infrastructure/config.php | 41 ---- .../schema-piece-repository.php | 89 --------- 12 files changed, 1 insertion(+), 458 deletions(-) rename src/{schema_generator => schema-aggregator}/application/aggregate-site-schema-command.php (100%) rename src/{schema_generator => schema-aggregator}/domain/page-controls.php (100%) rename src/{schema_generator => schema-aggregator}/domain/schema-piece-repository-interface.php (100%) rename src/{schema_generator => schema-aggregator}/infrastructure/meta-tags-context-memoizer-adapter.php (100%) rename src/{schema_generator => schema-aggregator}/infrastructure/site-schema-json-conditional.php (100%) rename src/{schema_generator => schema-aggregator}/user-interface/site-schema-aggregator-cli-command.php (100%) rename src/{schema_generator => schema-aggregator}/user-interface/site-schema-aggregator-route.php (100%) delete mode 100644 src/schema_generator/application/aggregate-site-schema-command-handler.php delete mode 100644 src/schema_generator/application/schema-pieces-aggregator.php delete mode 100644 src/schema_generator/domain/schema-piece.php delete mode 100644 src/schema_generator/infrastructure/config.php delete mode 100644 src/schema_generator/infrastructure/schema-piece-repository.php diff --git a/src/schema_generator/application/aggregate-site-schema-command.php b/src/schema-aggregator/application/aggregate-site-schema-command.php similarity index 100% rename from src/schema_generator/application/aggregate-site-schema-command.php rename to src/schema-aggregator/application/aggregate-site-schema-command.php diff --git a/src/schema_generator/domain/page-controls.php b/src/schema-aggregator/domain/page-controls.php similarity index 100% rename from src/schema_generator/domain/page-controls.php rename to src/schema-aggregator/domain/page-controls.php diff --git a/src/schema_generator/domain/schema-piece-repository-interface.php b/src/schema-aggregator/domain/schema-piece-repository-interface.php similarity index 100% rename from src/schema_generator/domain/schema-piece-repository-interface.php rename to src/schema-aggregator/domain/schema-piece-repository-interface.php diff --git a/src/schema_generator/infrastructure/meta-tags-context-memoizer-adapter.php b/src/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php similarity index 100% rename from src/schema_generator/infrastructure/meta-tags-context-memoizer-adapter.php rename to src/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php diff --git a/src/schema_generator/infrastructure/site-schema-json-conditional.php b/src/schema-aggregator/infrastructure/site-schema-json-conditional.php similarity index 100% rename from src/schema_generator/infrastructure/site-schema-json-conditional.php rename to src/schema-aggregator/infrastructure/site-schema-json-conditional.php diff --git a/src/schema_generator/user-interface/site-schema-aggregator-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php similarity index 100% rename from src/schema_generator/user-interface/site-schema-aggregator-cli-command.php rename to src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php diff --git a/src/schema_generator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php similarity index 100% rename from src/schema_generator/user-interface/site-schema-aggregator-route.php rename to src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 8d2178ba709..e313038c836 100644 --- a/src/schema_generator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -7,11 +7,11 @@ use WP_REST_Response; use Yoast\WP\SEO\Helpers\Capability_Helper; use Yoast\WP\SEO\Main; +use Yoast\WP\SEO\Routes\Route_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; -use Yoast\WP\SEO\Routes\Route_Interface; /** * Handles the route to represent a site's schema as JSON. diff --git a/src/schema_generator/application/aggregate-site-schema-command-handler.php b/src/schema_generator/application/aggregate-site-schema-command-handler.php deleted file mode 100644 index b95750e211b..00000000000 --- a/src/schema_generator/application/aggregate-site-schema-command-handler.php +++ /dev/null @@ -1,61 +0,0 @@ -schema_piece_repository = $schema_piece_repository; - $this->schema_piece_aggregator = $schema_piece_aggregator; - } - - /** - * Handles the Aggregate_Site_Schema_Command. - * - * @param Aggregate_Site_Schema_Command $command The command. - * - * @return array The aggregated schema. - */ - public function handle( Aggregate_Site_Schema_Command $command ): array { - - $schema_pieces = $this->schema_piece_repository->get( - $command->get_page_controls()->get_page(), - $command->get_page_controls()->get_page_size() - ); - - $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); - $schema = []; - foreach ( $aggregated_schema_pieces as $schema_piece ) { - $schema[] = $schema_piece->to_json_ld_graph(); - } - return $schema; - } -} diff --git a/src/schema_generator/application/schema-pieces-aggregator.php b/src/schema_generator/application/schema-pieces-aggregator.php deleted file mode 100644 index fa5c0da6daf..00000000000 --- a/src/schema_generator/application/schema-pieces-aggregator.php +++ /dev/null @@ -1,188 +0,0 @@ - $schema_pieces The schema pieces to aggregate. - */ - public function aggregate( array $schema_pieces ): array { - $aggregated_schema = []; - - foreach ( $schema_pieces as $piece ) { - $data = $piece->get_data(); - $type = $piece->get_type(); - $id = $piece->get_id(); - if ( \is_null( $id ) ) { - continue; - } - - if ( isset( $aggregated_schema[ $id ] ) ) { - // Merge properties if the piece already exists. - $aggregated_schema[ $id ] = new Schema_Piece( $this->merge_properties( $aggregated_schema[ $id ]->get_data(), $data ), $type ); - - } - else { - // Add new piece. - $aggregated_schema[ $id ] = new Schema_Piece( $data, $type ); - } - } - - // Return only the values to get rid of the keys (which are @id). - return \array_values( $aggregated_schema ); - } - - /** - * Merge properties from two schema entities with the same @id - * - * Strategy (FR-012): - * - @type: Special handling - merge types into unified array - * - @id: Skip (always the same) - * - Arrays: Combine unique values - * - Scalars: Prefer non-empty over empty - * - Objects: Deep merge recursively - * - Null vs value: Prefer non-null - * - * @param array $entity1 First entity. - * @param array $entity2 Second entity. - * @return array Merged entity. - */ - private function merge_properties( array $entity1, array $entity2 ): array { - $merged = $entity1; - - foreach ( $entity2 as $key => $value ) { - // Skip @id - these should always be the same - if ( $key === '@id' ) { - continue; - } - - // Special handling for @type - merge types (JSON-LD allows multiple types) - if ( $key === '@type' ) { - $merged['@type'] = $this->merge_types( - $merged['@type'] ?? null, - $value - ); - continue; - } - - if ( ! isset( $merged[ $key ] ) || $merged[ $key ] === '' ) { - // Property doesn't exist in entity1 or is empty - use entity2's value - $merged[ $key ] = $value; - } - elseif ( \is_array( $merged[ $key ] ) && \is_array( $value ) ) { - // Both are arrays - check if associative (object) or indexed (list) - if ( $this->is_associative_array( $merged[ $key ] ) || $this->is_associative_array( $value ) ) { - // Deep merge objects - $merged[ $key ] = $this->merge_properties( $merged[ $key ], $value ); - } - else { - // Combine arrays and get unique values - $merged[ $key ] = \array_values( \array_unique( \array_merge( $merged[ $key ], $value ), \SORT_REGULAR ) ); - } - } - // Else: entity1's value is non-empty scalar, keep it (prefer first occurrence) - } - - return $merged; - } - - /** - * Merge @type values from two entities - * - * JSON-LD allows @type to be either a string or an array of strings. - * This method combines types from both entities, deduplicates them, - * and normalizes the result (string if 1 type, array if multiple). - * - * Examples: - * - merge_types("Person", "Person") → "Person" - * - merge_types("Person", "Author") → ["Person", "Author"] - * - merge_types("Person", ["Author", "Employee"]) → ["Person", "Author", "Employee"] - * - merge_types(["Person"], "Person") → "Person" - * - merge_types(["Person", "Author"], ["Author", "Employee"]) → ["Person", "Author", "Employee"] - * - * @param string|array|null $type1 First @type value. - * @param string|array|null $type2 Second @type value. - * @return string|array Merged and normalized @type value. - */ - private function merge_types( $type1, $type2 ) { - // Normalize both to arrays - $types1 = $this->normalize_type_to_array( $type1 ); - $types2 = $this->normalize_type_to_array( $type2 ); - - // Combine and deduplicate - $merged = \array_unique( \array_merge( $types1, $types2 ), \SORT_REGULAR ); - - // Normalize result: string if 1 type, array if multiple - return $this->normalize_type_from_array( $merged ); - } - - /** - * Normalize @type value to array format - * - * @param string|array|null $type Type value to normalize. - * @return array Array of type strings. - */ - private function normalize_type_to_array( $type ): array { - if ( $type === null ) { - return []; - } - - if ( \is_string( $type ) ) { - return [ $type ]; - } - - if ( \is_array( $type ) ) { - // Filter out non-strings for safety - return \array_values( \array_filter( $type, 'is_string' ) ); - } - - // Invalid type format - \error_log( 'Yoast NLWeb Aggregator: Invalid @type format: ' . \gettype( $type ) ); - return []; - } - - /** - * Normalize array of types back to string or array - * - * Returns string if single type, array if multiple types. - * This keeps the output compact while supporting multi-type entities. - * - * @param array $types Array of type strings. - * @return string|array Normalized type value. - */ - private function normalize_type_from_array( array $types ) { - // Remove duplicates and re-index - $types = \array_values( \array_unique( $types ) ); - - if ( empty( $types ) ) { - // Fallback - should not happen in normal flow - return 'Thing'; // schema.org root type - } - - if ( \count( $types ) === 1 ) { - return $types[0]; // Return as string for single type - } - - return $types; // Return as array for multiple types - } - - /** - * Check if array is associative (object-like) vs indexed (list-like) - * - * @param array $array Array to check. - * @return bool True if associative. - */ - private function is_associative_array( array $array ): bool { - if ( empty( $array ) ) { - return false; - } - return \array_keys( $array ) !== \range( 0, ( \count( $array ) - 1 ) ); - } -} diff --git a/src/schema_generator/domain/schema-piece.php b/src/schema_generator/domain/schema-piece.php deleted file mode 100644 index 275f8fa1baa..00000000000 --- a/src/schema_generator/domain/schema-piece.php +++ /dev/null @@ -1,78 +0,0 @@ - - */ - protected $data; - - /** - * Class constructor. - * - * @param array $data The data of the schema piece. - * @param string $type The type of the schema piece. - */ - public function __construct( array $data, string $type ) { - $this->data = $data; - $this->type = $type; - } - - /** - * Gets the type of the schema piece. - * - * @return string The type of the schema piece. - */ - public function get_type(): string { - return $this->type; - } - - /** - * Gets the data of the schema piece. - * - * @return array The data of the schema piece. - */ - public function get_data(): array { - return $this->data; - } - - /** - * Gets the ID of the schema piece. - * - * @return string|null The ID of the schema piece, or null if not set. - */ - public function get_id(): ?string { - return $this->data['@id'] ?? null; - } - - /** - * Converts multiple schema pieces to a JSON-LD-encoded graph. - * - * @param Schema_Piece[] $schema_pieces Array of schema pieces. - * - * @return array The JSON-LD graph representation. - */ - public function to_json_ld_graph(): array { - return [ - '@context' => 'https://schema.org', - '@graph' => $this->data, - ]; - } -} diff --git a/src/schema_generator/infrastructure/config.php b/src/schema_generator/infrastructure/config.php deleted file mode 100644 index ac165b8b70c..00000000000 --- a/src/schema_generator/infrastructure/config.php +++ /dev/null @@ -1,41 +0,0 @@ -memoizer = $memoizer; - $this->indexable_helper = $indexable_helper; - $this->indexable_repository = $indexable_repository; - $this->adapter = $adapter; - } - - /** - * Gets the indexables to be aggregated. - * - * @param int $page The page number (1-based). - * @param int $page_size The number of items per page. - * - * @return array The aggregated schema. - */ - public function get( int $page, int $page_size ): array { - $public_indexables = $this->indexable_repository->find_all_public_paginated( - $page, - $page_size, - ); - $schema_pieces = []; - - foreach ( $public_indexables as $indexable ) { - $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); - $context = $this->memoizer->get( $indexable, $page_type ); - $context_array = $this->adapter->meta_tags_context_to_array( $context ); - $schema_pieces[] = new Schema_Piece( $context_array['@graph'][0], $page_type ); - } - - return $schema_pieces; - } -} From 2af1e68846fa1358e817df8f6174996c69753ec0 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:22:46 +0100 Subject: [PATCH 028/319] Add attributes and methods to filter the schema and the properties --- .../infrastructure/config.php | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/config.php diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php new file mode 100644 index 00000000000..af2d23ceef2 --- /dev/null +++ b/src/schema-aggregator/infrastructure/config.php @@ -0,0 +1,139 @@ + + */ + private const DEFAULT_POST_TYPES = [ 'post', 'page' ]; + + /** + * Default schema types to include (whitelist) + * + * @var array + */ + private const DEFAULT_SCHEMA_TYPES = [ + 'Recipe', + 'Article', + 'Product', + 'Event', + 'Person', + 'Organization', + 'WebPage', + 'WebSite', + ]; + + private const PROPERTIES_AVOID_LIST = [ 'breadcrumb', 'potentialAction' ]; + + /** + * Get default items per page + * + * @return int + */ + public function get_per_page(): int { + return (int) \apply_filters( 'wpseo_schema_aggregator_per_page', self::DEFAULT_PER_PAGE ); + } + + /** + * Get maximum items per page + * + * @return int + */ + public function get_max_per_page(): int { + return self::MAX_PER_PAGE; + } + + /** + * Get configured post types + * + * @return array + */ + public function get_allowed_post_types(): array { + $default_post_types = self::DEFAULT_POST_TYPES; + + // Only include 'product' if Yoast WooCommerce SEO extension is active. + // The extension integrates WooCommerce Product schema into Yoast's @graph. + if ( $this->is_yoast_woocommerce_active() ) { + $default_post_types[] = 'product'; + } + + $post_types = \apply_filters( 'wpseo_schema_aggregator_post_types', $default_post_types ); + + // Ensure it's an array. + if ( ! \is_array( $post_types ) ) { + return $default_post_types; + } + + return $post_types; + } + + /** + * Get configured schema types (whitelist) + * + * @return array + */ + public function get_allowed_schema_types(): array { + $schema_types = \apply_filters( 'wpseo_schema_aggregator_schema_types', self::DEFAULT_SCHEMA_TYPES ); + + // Ensure it's an array. + if ( ! \is_array( $schema_types ) ) { + return self::DEFAULT_SCHEMA_TYPES; + } + + return $schema_types; + } + + /** + * Get list of properties to remove from a schema piece. + * + * @return array + */ + public function get_properties_avoid_list(): array { + $properties_avoid_list = \apply_filters( 'wpseo_schema_aggregator_properties_avoid_list', self::PROPERTIES_AVOID_LIST ); + + // Ensure it's an array. + if ( ! \is_array( $properties_avoid_list ) ) { + return self::PROPERTIES_AVOID_LIST; + } + + return $properties_avoid_list; + } + + /** + * Check if Yoast WooCommerce SEO extension is active + * + * @return bool + */ + private function is_yoast_woocommerce_active(): bool { + $addon_manager = new WPSEO_Addon_Manager(); + $plugin_file = $addon_manager->get_plugin_file( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ); + + return $plugin_file && \is_plugin_active( $plugin_file ); + } +} From 46247bf883b23aa9213302e8d82eb20988460b0a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:23:10 +0100 Subject: [PATCH 029/319] Retrieve the correct type value --- .../schema-piece-repository.php | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/schema-piece-repository.php diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php new file mode 100644 index 00000000000..f9f7dc4564b --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -0,0 +1,90 @@ +memoizer = $memoizer; + $this->indexable_helper = $indexable_helper; + $this->indexable_repository = $indexable_repository; + $this->adapter = $adapter; + } + + /** + * Gets the indexables to be aggregated. + * + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * + * @return array The aggregated schema. + */ + public function get( int $page, int $page_size ): array { + $public_indexables = $this->indexable_repository->find_all_public_paginated( + $page, + $page_size, + ); + $schema_pieces = []; + + foreach ( $public_indexables as $indexable ) { + $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); + $context = $this->memoizer->get( $indexable, $page_type ); + $context_array = $this->adapter->meta_tags_context_to_array( $context ); + $data = $context_array['@graph'][0]; + $schema_pieces[] = new Schema_Piece( $data, $data['@type'] ); + } + + return $schema_pieces; + } +} From de9d94dafd5497d5f9e85d7e6dd9305d81d0d88a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:23:37 +0100 Subject: [PATCH 030/319] Move file --- src/schema-aggregator/domain/schema-piece.php | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/schema-aggregator/domain/schema-piece.php diff --git a/src/schema-aggregator/domain/schema-piece.php b/src/schema-aggregator/domain/schema-piece.php new file mode 100644 index 00000000000..2e801a56a85 --- /dev/null +++ b/src/schema-aggregator/domain/schema-piece.php @@ -0,0 +1,74 @@ + + */ + protected $type; + + /** + * The data of the schema piece. + * + * @var array + */ + protected $data; + + /** + * Class constructor. + * + * @param array $data The data of the schema piece. + * @param string|array $type The type of the schema piece. + */ + public function __construct( array $data, $type ) { + $this->data = $data; + $this->type = $type; + } + + /** + * Gets the type of the schema piece. + * + * @return string|array The type(s) of the schema piece. + */ + public function get_type() { + return $this->type; + } + + /** + * Gets the data of the schema piece. + * + * @return array The data of the schema piece. + */ + public function get_data(): array { + return $this->data; + } + + /** + * Gets the ID of the schema piece. + * + * @return string|null The ID of the schema piece, or null if not set. + */ + public function get_id(): ?string { + return ( $this->data['@id'] ?? null ); + } + + /** + * Converts multiple schema pieces to a JSON-LD-encoded graph. + * + * @return array The JSON-LD graph representation. + */ + public function to_json_ld_graph(): array { + return [ + '@context' => 'https://schema.org', + '@graph' => $this->data, + ]; + } +} From 62aeed00d4021189b97744eec669f1e265584762 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:24:31 +0100 Subject: [PATCH 031/319] Filter schema pieces on the basis of type --- .../application/schema-pieces-filter.php | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/schema-aggregator/application/schema-pieces-filter.php diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php new file mode 100644 index 00000000000..5d73743de46 --- /dev/null +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -0,0 +1,88 @@ +config = $config; + } + + /** + * Check if type is allowed. + * + * @param string $type Schema type. + * @return bool True if allowed. + */ + public function is_allowed_type( string $type ): bool { + return \in_array( $type, $this->get_allowed_types(), true ); + } + + /** + * Get allowed types from config. + * + * @return array + */ + public function get_allowed_types(): array { + return $this->config->get_allowed_schema_types(); + } + + /** + * Check if entity has at least one allowed type. + * + * Handles @type as both string and array (per JSON-LD spec). + * Returns true if the entity's @type contains at least one allowed type. + * + * @param Schema_Piece $piece The schema piece. + * @return bool True if at least one type is allowed. + */ + public function has_allowed_type( Schema_Piece $piece ): bool { + $type = $piece->get_type(); + // Handle string @type. + if ( \is_string( $type ) ) { + return $this->is_allowed_type( $type ); + } + + // Handle array @type (JSON-LD allows multiple types). + if ( \is_array( $type ) ) { + foreach ( $type as $single_type ) { + // Validate each type is a string. + if ( ! \is_string( $single_type ) ) { + continue; + } + + // Check if this type is allowed. + if ( $this->is_allowed_type( $single_type ) ) { + return true; // At least one type is allowed. + } + } + + return false; + } + + // Neither an array or a string: Invalid @type format. + \error_log( 'Yoast Schema Aggregator Filter: @type is neither string nor array' ); + return false; + } +} From 5795c6a11a066154b50f2fb42fb5a72e5cd4d0a1 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:24:54 +0100 Subject: [PATCH 032/319] Filter properties on the basis of a property avoid list --- .../application/properties-filter.php | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/schema-aggregator/application/properties-filter.php diff --git a/src/schema-aggregator/application/properties-filter.php b/src/schema-aggregator/application/properties-filter.php new file mode 100644 index 00000000000..cefd8d0ac7e --- /dev/null +++ b/src/schema-aggregator/application/properties-filter.php @@ -0,0 +1,58 @@ +config = $config; + } + + /** + * Remove properties that reference filtered-out entity types + * + * Removes properties like 'breadcrumb' that reference BreadcrumbList entities + * which have been filtered out from the allowed types. + * + * Also removes 'potentialAction' properties (ReadAction, CommentAction, SearchAction) + * which are added by Yoast but not needed for NLWeb integration. + * + * @param Schema_Piece $piece The schema piece. + * + * @return Schema_Piece Cleaned schema piece. + */ + public function filter( Schema_Piece $piece ): Schema_Piece { + // Properties to remove (references to filtered-out entities and unwanted actions). + $properties_to_remove = $this->config->get_properties_avoid_list(); + $data = $piece->get_data(); + + foreach ( $properties_to_remove as $property ) { + if ( isset( $data[ $property ] ) ) { + unset( $data[ $property ] ); + } + } + + return new Schema_Piece( $data, $piece->get_type() ); + } +} From 636bab8aeee833293e66cf7f9627cbecaf3cb7a4 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:25:11 +0100 Subject: [PATCH 033/319] Merge schema pieces with the same id --- .../application/properties-merger.php | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/schema-aggregator/application/properties-merger.php diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php new file mode 100644 index 00000000000..9e24283f483 --- /dev/null +++ b/src/schema-aggregator/application/properties-merger.php @@ -0,0 +1,174 @@ +merge_properties( $piece1->get_data(), $piece2->get_data() ); + // TODO: Shall we check if $type !== null? + return new Schema_Piece( $merged_properties, $merged_properties['@type'] ); + } + + /** + * Merge properties from two schema entities with the same @id + * + * Strategy (FR-012): + * - @type: Special handling - merge types into unified array + * - @id: Skip (always the same) + * - Arrays: Combine unique values + * - Scalars: Prefer non-empty over empty + * - Objects: Deep merge recursively + * - Null vs value: Prefer non-null + * + * @param array $entity1 First entity. + * @param array $entity2 Second entity. + * + * @return array Merged entity. + */ + private function merge_properties( array $entity1, array $entity2 ): array { + $merged = $entity1; + + foreach ( $entity2 as $key => $value ) { + // Skip @id - these should always be the same. + if ( $key === '@id' ) { + continue; + } + + // Special handling for @type - merge types (JSON-LD allows multiple types). + if ( $key === '@type' ) { + $merged['@type'] = $this->merge_types( + ( $merged['@type'] ?? null ), + $value + ); + continue; + } + + if ( ! isset( $merged[ $key ] ) || $merged[ $key ] === '' ) { + // Property doesn't exist in entity1 or is empty - use entity2's value. + $merged[ $key ] = $value; + } + elseif ( \is_array( $merged[ $key ] ) && \is_array( $value ) ) { + // Both are arrays - check if associative (object) or indexed (list). + if ( $this->is_associative_array( $merged[ $key ] ) || $this->is_associative_array( $value ) ) { + // Deep merge objects. + $merged[ $key ] = $this->merge_properties( $merged[ $key ], $value ); + } + else { + // Combine arrays and get unique values. + $merged[ $key ] = \array_values( \array_unique( \array_merge( $merged[ $key ], $value ), \SORT_REGULAR ) ); + } + } + // Else: entity1's value is non-empty scalar, keep it (prefer first occurrence). + } + + return $merged; + } + + /** + * Merge @type values from two entities + * + * JSON-LD allows @type to be either a string or an array of strings. + * This method combines types from both entities, deduplicates them, + * and normalizes the result (string if 1 type, array if multiple). + * + * Examples: + * - merge_types("Person", "Person") → "Person" + * - merge_types("Person", "Author") → ["Person", "Author"] + * - merge_types("Person", ["Author", "Employee"]) → ["Person", "Author", "Employee"] + * - merge_types(["Person"], "Person") → "Person" + * - merge_types(["Person", "Author"], ["Author", "Employee"]) → ["Person", "Author", "Employee"] + * + * @param string|array|null $type1 First @type value. + * @param string|array|null $type2 Second @type value. + * @return string|array Merged and normalized @type value. + */ + private function merge_types( $type1, $type2 ) { + // Normalize both to arrays. + $types1 = $this->normalize_type_to_array( $type1 ); + $types2 = $this->normalize_type_to_array( $type2 ); + + // Combine and deduplicate. + $merged = \array_unique( \array_merge( $types1, $types2 ), \SORT_REGULAR ); + + // Normalize result: string if 1 type, array if multiple. + return $this->normalize_type_from_array( $merged ); + } + + /** + * Normalize @type value to array format + * + * @param string|array|null $type Type value to normalize. + * @return array Array of type strings. + */ + private function normalize_type_to_array( $type ): array { + if ( $type === null ) { + return []; + } + + if ( \is_string( $type ) ) { + return [ $type ]; + } + + if ( \is_array( $type ) ) { + // Filter out non-strings for safety. + return \array_values( \array_filter( $type, 'is_string' ) ); + } + + // Invalid type format. + \error_log( 'Yoast Schema Aggregator: Invalid @type format: ' . \gettype( $type ) ); + return []; + } + + /** + * Normalize array of types back to string or array + * + * Returns string if single type, array if multiple types. + * This keeps the output compact while supporting multi-type entities. + * + * @param array $types Array of type strings. + * @return string|array Normalized type value. + */ + private function normalize_type_from_array( array $types ) { + // Remove duplicates and re-index. + $types = \array_values( \array_unique( $types ) ); + + if ( empty( $types ) ) { + // Fallback - should not happen in normal flow. + return 'Thing'; // schema.org root type. + } + + if ( \count( $types ) === 1 ) { + return $types[0]; // Return as string for single type. + } + + return $types; // Return as array for multiple types. + } + + /** + * Check if array is associative (object-like) vs indexed (list-like) + * + * @param array> $array Array to check. + * @return bool True if associative. + */ + private function is_associative_array( array $array ): bool { + if ( empty( $array ) ) { + return false; + } + return \array_keys( $array ) !== \range( 0, ( \count( $array ) - 1 ) ); + } +} From af7f5e3ccec97cc49086476d3d9ca38468edf076 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:25:35 +0100 Subject: [PATCH 034/319] Aggregates the schema pieces --- .../application/schema-pieces-aggregator.php | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/schema-aggregator/application/schema-pieces-aggregator.php diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php new file mode 100644 index 00000000000..27620ecbc42 --- /dev/null +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -0,0 +1,97 @@ + $schema_pieces The schema pieces to aggregate. + */ +class Schema_Pieces_Aggregator { + + /** + * The configuration instance. + * + * @var Config + */ + private $config; + + /** + * The properties filter instance. + * + * @var Properties_Filter + */ + private $properties_filter; + + /** + * The schema filter instance. + * + * @var Schema_Pieces_Filter + */ + private $schema_pieces_filter; + + /** + * The properties merger object + * + * @var Properties_Merger + */ + private $properties_merger; + + /** + * Class constructor + * + * @param Config $config The configuration object. + * @param Properties_Filter $properties_filter The properties filter object. + * @param Schema_Pieces_Filter $schema_pieces_filter The schema pieces filter object. + * @param Properties_Merger $properties_merger The properties merger object. + */ + public function __construct( Config $config, Properties_Filter $properties_filter, Schema_Pieces_Filter $schema_pieces_filter, Properties_Merger $properties_merger ) { + $this->config = $config; + $this->properties_filter = $properties_filter; + $this->schema_pieces_filter = $schema_pieces_filter; + $this->properties_merger = $properties_merger; + } + + /** + * Main orchestrator method: deduplicates, merges and filter properties. + * + * @param array $schema_pieces The schema pieces to aggregate. + * + * @return array The aggregated schema pieces. + */ + public function aggregate( array $schema_pieces ): array { + $aggregated_schema = []; + + foreach ( $schema_pieces as $piece ) { + if ( ! $this->schema_pieces_filter->has_allowed_type( $piece ) ) { + continue; + } + + $id = $piece->get_id(); + if ( \is_null( $id ) ) { + continue; + } + + if ( isset( $aggregated_schema[ $id ] ) ) { + // Merge properties if the piece already exists. + $aggregated_schema[ $id ] = $this->properties_merger->merge( $aggregated_schema[ $id ], $piece ); + } + else { + // Add new piece. + $aggregated_schema[ $id ] = $piece; + } + + $aggregated_schema[ $id ] = $this->properties_filter->filter( $aggregated_schema[ $id ] ); + } + + // Return only the values to get rid of the keys (which are @id). + return \array_values( $aggregated_schema ); + } +} From 0fc76a471ff426e0c7077934874100338b85a355 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 28 Oct 2025 16:25:47 +0100 Subject: [PATCH 035/319] Make use of the aggregator and the filters --- .../aggregate-site-schema-command-handler.php | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/schema-aggregator/application/aggregate-site-schema-command-handler.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php new file mode 100644 index 00000000000..d02971654be --- /dev/null +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -0,0 +1,59 @@ +schema_piece_repository = $schema_piece_repository; + $this->schema_piece_aggregator = $schema_piece_aggregator; + } + + /** + * Handles the Aggregate_Site_Schema_Command. + * + * @param Aggregate_Site_Schema_Command $command The command. + * + * @return array The aggregated schema. + */ + public function handle( Aggregate_Site_Schema_Command $command ): array { + + $schema_pieces = $this->schema_piece_repository->get( + $command->get_page_controls()->get_page(), + $command->get_page_controls()->get_page_size() + ); + + $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); + $schema = []; + foreach ( $aggregated_schema_pieces as $schema_piece ) { + $schema[] = $schema_piece->to_json_ld_graph(); + } + return $schema; + } +} From 31c24562ef171e01424ef3e0dea1ff20d563c8b3 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 29 Oct 2025 12:56:18 +0100 Subject: [PATCH 036/319] Fix cs --- src/schema-aggregator/application/properties-merger.php | 9 ++++----- .../application/schema-pieces-filter.php | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index 9e24283f483..1dd1d70f8ac 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -130,7 +130,6 @@ private function normalize_type_to_array( $type ): array { } // Invalid type format. - \error_log( 'Yoast Schema Aggregator: Invalid @type format: ' . \gettype( $type ) ); return []; } @@ -162,13 +161,13 @@ private function normalize_type_from_array( array $types ) { /** * Check if array is associative (object-like) vs indexed (list-like) * - * @param array> $array Array to check. + * @param array> $argument Array to check. * @return bool True if associative. */ - private function is_associative_array( array $array ): bool { - if ( empty( $array ) ) { + private function is_associative_array( array $argument ): bool { + if ( empty( $argument ) ) { return false; } - return \array_keys( $array ) !== \range( 0, ( \count( $array ) - 1 ) ); + return \array_keys( $argument ) !== \range( 0, ( \count( $argument ) - 1 ) ); } } diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php index 5d73743de46..9527a9effa3 100644 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -82,7 +82,6 @@ public function has_allowed_type( Schema_Piece $piece ): bool { } // Neither an array or a string: Invalid @type format. - \error_log( 'Yoast Schema Aggregator Filter: @type is neither string nor array' ); return false; } } From c08a4d4b3a2d47337489dbcfe3434e16f71ffc9d Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 29 Oct 2025 14:15:27 +0100 Subject: [PATCH 037/319] Fix cs --- src/schema-aggregator/application/properties-merger.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index 1dd1d70f8ac..e9da1025981 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -161,13 +161,13 @@ private function normalize_type_from_array( array $types ) { /** * Check if array is associative (object-like) vs indexed (list-like) * - * @param array> $argument Array to check. + * @param array> $array Array to check. * @return bool True if associative. */ - private function is_associative_array( array $argument ): bool { - if ( empty( $argument ) ) { + private function is_associative_array( array $array ): bool { + if ( empty( $array ) ) { return false; } - return \array_keys( $argument ) !== \range( 0, ( \count( $argument ) - 1 ) ); + return \array_keys( $array ) !== \range( 0, ( \count( $array ) - 1 ) ); } } From 9bf7571fe08157e07175a96db622751754af417f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 29 Oct 2025 14:15:39 +0100 Subject: [PATCH 038/319] Add post type filter --- .../infrastructure/schema-piece-repository.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index f9f7dc4564b..1035bc9f855 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -42,6 +42,13 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { */ private $adapter; + /** + * Configuration provider. + * + * @var Config + */ + private $config; + /** * Constructor. * @@ -49,17 +56,20 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. * @param Meta_Tags_Context_Memoizer_Adapter $adapter The adapter factory. + * @param Config $config The configuration provider. */ public function __construct( Meta_Tags_Context_Memoizer $memoizer, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository, - Meta_Tags_Context_Memoizer_Adapter $adapter + Meta_Tags_Context_Memoizer_Adapter $adapter, + Config $config ) { $this->memoizer = $memoizer; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; $this->adapter = $adapter; + $this->config = $config; } /** @@ -78,6 +88,10 @@ public function get( int $page, int $page_size ): array { $schema_pieces = []; foreach ( $public_indexables as $indexable ) { + if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { + continue; + } + $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); $context = $this->memoizer->get( $indexable, $page_type ); $context_array = $this->adapter->meta_tags_context_to_array( $context ); From 6e21ea1c11fda8f3af2467dad371c9398483b3da Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 29 Oct 2025 17:00:28 +0100 Subject: [PATCH 039/319] Fix cs --- src/schema-aggregator/application/properties-merger.php | 8 ++++---- .../infrastructure/schema-piece-repository.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index e9da1025981..1dd1d70f8ac 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -161,13 +161,13 @@ private function normalize_type_from_array( array $types ) { /** * Check if array is associative (object-like) vs indexed (list-like) * - * @param array> $array Array to check. + * @param array> $argument Array to check. * @return bool True if associative. */ - private function is_associative_array( array $array ): bool { - if ( empty( $array ) ) { + private function is_associative_array( array $argument ): bool { + if ( empty( $argument ) ) { return false; } - return \array_keys( $array ) !== \range( 0, ( \count( $array ) - 1 ) ); + return \array_keys( $argument ) !== \range( 0, ( \count( $argument ) - 1 ) ); } } diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 1035bc9f855..6f3648e5cbb 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -88,7 +88,7 @@ public function get( int $page, int $page_size ): array { $schema_pieces = []; foreach ( $public_indexables as $indexable ) { - if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { + if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { continue; } From d8650fabd2d7936ec8d857c4c3054c2369febb7a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 30 Oct 2025 16:34:07 +0100 Subject: [PATCH 040/319] Fix schema pieces gathering --- .../infrastructure/schema-piece-repository.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 6f3648e5cbb..367748b0342 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -92,11 +92,14 @@ public function get( int $page, int $page_size ): array { continue; } - $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); - $context = $this->memoizer->get( $indexable, $page_type ); - $context_array = $this->adapter->meta_tags_context_to_array( $context ); - $data = $context_array['@graph'][0]; - $schema_pieces[] = new Schema_Piece( $data, $data['@type'] ); + $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); + $context = $this->memoizer->get( $indexable, $page_type ); + $context_array = $this->adapter->meta_tags_context_to_array( $context ); + + $pieces_data = $context_array['@graph']; + foreach ( $pieces_data as $piece_data ) { + $schema_pieces[] = new Schema_Piece( $piece_data, $piece_data['@type'] ); + } } return $schema_pieces; From d747a1327cd551c1ca8a7eab348684ad875fa906 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Fri, 31 Oct 2025 09:25:59 +0100 Subject: [PATCH 041/319] Enable enhancers for the schema pieces. --- .../aggregate-site-schema-command-handler.php | 0 .../aggregate-site-schema-command.php | 0 .../enhancement/abstract-schema-enhancer.php | 30 +++ .../enhancement/article-schema-enhancer.php | 218 ++++++++++++++++++ .../enhancement/person-schema-enhancer.php | 135 +++++++++++ .../schema-enhancement-factory.php | 31 +++ .../enhancement-config-interface.php | 25 ++ .../schema-enhancement-interface.php | 6 +- .../domain/page-controls.php | 0 .../schema-piece-repository-interface.php | 0 .../domain/schema-piece.php | 1 + .../infrastructure/config.php | 0 .../enhancement/article-config.php | 62 +++++ .../enhancement/person-config.php | 41 ++++ .../meta-tags-context-memoizer-adapter.php | 0 .../schema-piece-repository.php | 55 ++++- .../site-schema-json-conditional.php | 0 .../site-schema-aggregator-cli-command.php | 0 .../site-schema-aggregator-route.php | 2 +- .../enhancement/article-schema-enhancer.php | 20 -- .../enhancement/person-schema-enhancer.php | 20 -- .../schema-enhancement-factory.php | 28 --- 22 files changed, 597 insertions(+), 77 deletions(-) rename src/{schema_generator => schema_aggregator}/application/aggregate-site-schema-command-handler.php (100%) rename src/{schema_generator => schema_aggregator}/application/aggregate-site-schema-command.php (100%) create mode 100644 src/schema_aggregator/application/enhancement/abstract-schema-enhancer.php create mode 100644 src/schema_aggregator/application/enhancement/article-schema-enhancer.php create mode 100644 src/schema_aggregator/application/enhancement/person-schema-enhancer.php create mode 100644 src/schema_aggregator/application/enhancement/schema-enhancement-factory.php create mode 100644 src/schema_aggregator/domain/enhancement/enhancement-config-interface.php rename src/{schema_generator => schema_aggregator}/domain/enhancement/schema-enhancement-interface.php (66%) rename src/{schema_generator => schema_aggregator}/domain/page-controls.php (100%) rename src/{schema_generator => schema_aggregator}/domain/schema-piece-repository-interface.php (100%) rename src/{schema_generator => schema_aggregator}/domain/schema-piece.php (99%) rename src/{schema_generator => schema_aggregator}/infrastructure/config.php (100%) create mode 100644 src/schema_aggregator/infrastructure/enhancement/article-config.php create mode 100644 src/schema_aggregator/infrastructure/enhancement/person-config.php rename src/{schema_generator => schema_aggregator}/infrastructure/meta-tags-context-memoizer-adapter.php (100%) rename src/{schema_generator => schema_aggregator}/infrastructure/schema-piece-repository.php (58%) rename src/{schema_generator => schema_aggregator}/infrastructure/site-schema-json-conditional.php (100%) rename src/{schema_generator => schema_aggregator}/user-interface/site-schema-aggregator-cli-command.php (100%) rename src/{schema_generator => schema_aggregator}/user-interface/site-schema-aggregator-route.php (100%) delete mode 100644 src/schema_generator/application/enhancement/article-schema-enhancer.php delete mode 100644 src/schema_generator/application/enhancement/person-schema-enhancer.php delete mode 100644 src/schema_generator/application/enhancement/schema-enhancement-factory.php diff --git a/src/schema_generator/application/aggregate-site-schema-command-handler.php b/src/schema_aggregator/application/aggregate-site-schema-command-handler.php similarity index 100% rename from src/schema_generator/application/aggregate-site-schema-command-handler.php rename to src/schema_aggregator/application/aggregate-site-schema-command-handler.php diff --git a/src/schema_generator/application/aggregate-site-schema-command.php b/src/schema_aggregator/application/aggregate-site-schema-command.php similarity index 100% rename from src/schema_generator/application/aggregate-site-schema-command.php rename to src/schema_aggregator/application/aggregate-site-schema-command.php diff --git a/src/schema_aggregator/application/enhancement/abstract-schema-enhancer.php b/src/schema_aggregator/application/enhancement/abstract-schema-enhancer.php new file mode 100644 index 00000000000..36a934529cd --- /dev/null +++ b/src/schema_aggregator/application/enhancement/abstract-schema-enhancer.php @@ -0,0 +1,30 @@ + 0 && \strlen( $content ) > $max_length ) { + $content = \substr( $content, 0, $max_length ); + $last_space = \strrpos( $content, ' ' ); + if ( $last_space !== false && $last_space > ( $max_length * 0.9 ) ) { + $content = \substr( $content, 0, $last_space ); + } + $content .= '...'; + } + + return $content; + } +} diff --git a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php new file mode 100644 index 00000000000..c6936041f6c --- /dev/null +++ b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php @@ -0,0 +1,218 @@ +config = $config; + } + + /** + * Enhances specific Article schema pieces. + * + * @param Schema_Piece $schema_piece The schema piece to enhance. + * @param Indexable $indexable The indexable object that is the source of the schema piece. + * + * @return Schema_Piece The enhanced schema piece. + */ + public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Schema_Piece { + + $data = $schema_piece->get_data(); + foreach ( $data as $key => $schema_data ) { + if ( isset( $schema_data['@type'] ) && ( $schema_data['@type'] === 'Article' || $schema_data['@type'] === 'NewsArticle' || $schema_data['@type'] === 'BlogPosting' ) ) { + $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); + } + } + + return new Schema_Piece( $data, $schema_piece->get_type() ); + } + + /** + * Enhance a single schema piece + * + * @param array $schema_data The schema data to enhance. + * @param Indexable $indexable The indexable object that is the source of the schema piece. + * + * @return array The enhanced schema data. + */ + private function enhance_schema_piece( $schema_data, $indexable ) { + try { + $has_excerpt = false; + + if ( $this->config->is_enhancement_enabled( 'use_excerpt' ) ) { + $excerpt = $this->get_excerpt( $indexable->object_id ); + $has_excerpt = ( $excerpt !== null && $excerpt !== '' ); + + if ( $has_excerpt && ! isset( $entity['description'] ) ) { + $schema_data['description'] = $excerpt; + } + } + + if ( $this->config->is_enhancement_enabled( 'article_body' ) && ! isset( $entity['articleBody'] ) ) { + if ( $this->config->should_include_article_body( $has_excerpt ) ) { + $article_body = $this->get_article_body( $indexable->object_id ); + if ( $article_body !== null && $article_body !== '' ) { + $schema_data['articleBody'] = $article_body; + } + } + } + + if ( $this->config->is_enhancement_enabled( 'keywords' ) && ! isset( $entity['keywords'] ) ) { + $keywords = $this->get_article_keywords( $indexable->object_id ); + if ( ! empty( $keywords ) ) { + $schema_data['keywords'] = \implode( ', ', $keywords ); + } + } + + return $schema_data; + } catch ( Exception $e ) { + return $schema_data; + } + } + + /** + * Get article keywords + * + * Extracts post tags and optionally categories as keywords. + * + * @param int $post_id Post ID. + * + * @return array Array of keyword strings. + */ + private function get_article_keywords( int $post_id ): array { + try { + $keywords = []; + + $tags = \get_the_tags( $post_id ); + if ( \is_array( $tags ) && ! empty( $tags ) ) { + foreach ( $tags as $tag ) { + if ( isset( $tag->name ) ) { + $keywords[] = $tag->name; + } + } + } + + if ( $this->config->get_config_value( 'categories_as_keywords', true ) ) { + $categories = \get_the_category( $post_id ); + if ( \is_array( $categories ) && ! empty( $categories ) ) { + foreach ( $categories as $category ) { + if ( isset( $category->name ) && $category->name !== 'Uncategorized' ) { + $keywords[] = $category->name; + } + } + } + } + + return \array_unique( $keywords ); + } catch ( Exception $e ) { + return []; + } + } + + /** + * Get article excerpt for description field + * + * Retrieves post excerpt with robust validation (no empty/whitespace-only). + * Falls back to auto-generated excerpt from content unless prefer_manual is enabled. + * + * @param int $post_id Post ID. + * + * @return string|null Excerpt or null if unavailable/invalid. + */ + private function get_excerpt( int $post_id ): ?string { + try { + $excerpt = \get_post_field( 'post_excerpt', $post_id ); + if ( \is_wp_error( $excerpt ) ) { + $excerpt = ''; + } + + if ( empty( $excerpt ) || \trim( $excerpt ) === '' ) { + if ( $this->config->get_config_value( 'excerpt_prefer_manual', false ) ) { + return null; + } + + $content = \get_post_field( 'post_content', $post_id ); + + if ( \is_wp_error( $content ) || empty( $content ) ) { + return null; + } + $excerpt = \wp_trim_excerpt( $content, $post_id ); + + if ( empty( $excerpt ) || \trim( $excerpt ) === '' ) { + return null; + } + } + $excerpt = \wp_strip_all_tags( $excerpt ); + + // Apply max length if configured. + $max_length = $this->config->get_config_value( 'excerpt_max_length', 0 ); + $excerpt = $this->trim_content_to_max_length( $max_length, $excerpt ); + + $excerpt = \trim( $excerpt ); + + return ( $excerpt !== '' ) ? $excerpt : null; + } catch ( Exception $e ) { + return null; + } + } + + /** + * Get article body (full post content) + * + * Extracts full post content with optional HTML and shortcode stripping. + * Respects max_length configuration if set. + * + * @param int $post_id Post ID. + * + * @return string|null Article body or null if unavailable. + */ + private function get_article_body( int $post_id ): ?string { + try { + $content = \get_post_field( 'post_content', $post_id ); + + if ( \is_wp_error( $content ) || empty( $content ) ) { + return null; + } + + if ( $this->config->get_config_value( 'strip_shortcodes_from_body', true ) ) { + $content = \strip_shortcodes( $content ); + } + + if ( $this->config->get_config_value( 'strip_html_from_body', true ) ) { + $content = \wp_strip_all_tags( $content ); + } + + // Apply max length if configured (default: 500 chars). + $max_length = $this->config->get_config_value( 'article_body_max_length', 500 ); + + return $this->trim_content_to_max_length( $max_length, $content ); + } catch ( Exception $e ) { + return null; + } + } +} diff --git a/src/schema_aggregator/application/enhancement/person-schema-enhancer.php b/src/schema_aggregator/application/enhancement/person-schema-enhancer.php new file mode 100644 index 00000000000..b452835a5c0 --- /dev/null +++ b/src/schema_aggregator/application/enhancement/person-schema-enhancer.php @@ -0,0 +1,135 @@ +config = $config; + } + + /** + * Enhances specific Article schema pieces. + * + * @param Schema_Piece $schema_piece The schema piece to enhance. + * @param Indexable $indexable The indexable object that is the source of the schema piece. + * + * @return Schema_Piece The enhanced schema piece. + */ + public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Schema_Piece { + $data = $schema_piece->get_data(); + foreach ( $data as $key => $schema_data ) { + if ( isset( $schema_data['@type'] ) && $schema_data['@type'] === 'Person' ) { + $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); + } + } + + return new Schema_Piece( $data, $schema_piece->get_type() ); + } + + /** + * Enhance a single schema piece + * + * @param array $schema_data The schema data to enhance. + * @param Indexable $indexable The indexable object that is the source of the schema piece. + * + * @return array The enhanced schema data. + */ + private function enhance_schema_piece( $schema_data, $indexable ) { + try { + // Add jobTitle if enabled and not already present. + if ( $this->config->is_enhancement_enabled( 'person_job_title' ) && ! isset( $entity['jobTitle'] ) ) { + $job_title = $this->get_person_job_title( $indexable->author_id ); + if ( $job_title !== null && $job_title !== '' ) { + $schema_data['jobTitle'] = $job_title; + } + } + + if ( $this->config->is_enhancement_enabled( 'person_bio' ) ) { + $max_length = $this->config->get_config_value( 'person_bio_max_length', 0 ); + $current_bio = ( $schema_data['description'] ?? '' ); + + // Only replace if configured for unlimited or longer than current. + if ( $max_length === 0 || \strlen( $current_bio ) < $max_length ) { + $full_bio = $this->get_person_bio( $indexable->author_id, $max_length ); + if ( $full_bio !== null && $full_bio !== '' && $full_bio !== $current_bio ) { + $schema_data['description'] = $full_bio; + } + } + } + + return $schema_data; + } catch ( Exception $e ) { + return $schema_data; + } + } + + /** + * Get person bio + * + * Retrieves user bio with optional length limit. + * + * @param int $user_id User ID. + * @param int $max_length Maximum length (0 = unlimited). + * + * @return string|null Bio or null if unavailable. + */ + private function get_person_bio( int $user_id, int $max_length = 0 ): ?string { + try { + $bio = \get_user_meta( $user_id, 'description', true ); + + if ( empty( $bio ) ) { + return null; + } + + $bio = \trim( $bio ); + + return $this->trim_content_to_max_length( $max_length, $bio ); + } catch ( Exception $e ) { + return null; + } + } + + /** + * Get person job title + * + * Retrieves job title from user meta. + * + * @param int $user_id User ID. + * + * @return string|null Job title or null if unavailable. + */ + private function get_person_job_title( int $user_id ): ?string { + $job_title = \get_user_meta( $user_id, 'job_title', true ); + + if ( empty( $job_title ) ) { + return null; + } + + return \trim( $job_title ); + } +} diff --git a/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php b/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php new file mode 100644 index 00000000000..7add6539547 --- /dev/null +++ b/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php @@ -0,0 +1,31 @@ + $schema_types The types of schema (e.g., 'Article', 'Person'). + * + * @return Schema_Enhancement_Interface|null The corresponding schema enhancer or null if none exists. + */ + public function get_enhancer( array $schema_types ): ?Schema_Enhancement_Interface { + foreach ( $schema_types as $schema_type_value ) { + switch ( $schema_type_value ) { + case 'Article': + return new Article_Schema_Enhancer(); + case 'Person': + return new Person_Schema_Enhancer(); + default: + return null; // No enhancer available for the given schema type. + } + } + } +} diff --git a/src/schema_aggregator/domain/enhancement/enhancement-config-interface.php b/src/schema_aggregator/domain/enhancement/enhancement-config-interface.php new file mode 100644 index 00000000000..de2ede1ba70 --- /dev/null +++ b/src/schema_aggregator/domain/enhancement/enhancement-config-interface.php @@ -0,0 +1,25 @@ + true, + 'use_excerpt' => true, + 'keywords' => true, + ]; + + $default = ( $defaults[ $enhancement ] ?? false ); + + return (bool) \apply_filters( "wpseo_article_enhance_{$enhancement}", $default ); + } + + /** + * Determine if articleBody should be included + * + * Decision logic: + * - If has excerpt AND article_body_when_excerpt_exists: include + * - If no excerpt AND article_body_fallback: include + * - Otherwise: skip + * + * @param bool $has_excerpt Whether post has valid excerpt. + * + * @return bool True if articleBody should be included. + */ + public function should_include_article_body( bool $has_excerpt ): bool { + if ( $has_excerpt ) { + return (bool) \apply_filters( 'wpseo_article_enhance_body_when_excerpt_exists', false ); + } + + return (bool) \apply_filters( 'wpseo_article_enhance_article_body_fallback', true ); + } +} diff --git a/src/schema_aggregator/infrastructure/enhancement/person-config.php b/src/schema_aggregator/infrastructure/enhancement/person-config.php new file mode 100644 index 00000000000..2abc1b8c269 --- /dev/null +++ b/src/schema_aggregator/infrastructure/enhancement/person-config.php @@ -0,0 +1,41 @@ + true, + 'person_job_title' => true, + ]; + + $default = ( $defaults[ $enhancement ] ?? false ); + + return (bool) \apply_filters( "wpseo_person_enhance_{$enhancement}", $default ); + } +} diff --git a/src/schema_generator/infrastructure/meta-tags-context-memoizer-adapter.php b/src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php similarity index 100% rename from src/schema_generator/infrastructure/meta-tags-context-memoizer-adapter.php rename to src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php diff --git a/src/schema_generator/infrastructure/schema-piece-repository.php b/src/schema_aggregator/infrastructure/schema-piece-repository.php similarity index 58% rename from src/schema_generator/infrastructure/schema-piece-repository.php rename to src/schema_aggregator/infrastructure/schema-piece-repository.php index 8144b005933..26e93a8de9d 100644 --- a/src/schema_generator/infrastructure/schema-piece-repository.php +++ b/src/schema_aggregator/infrastructure/schema-piece-repository.php @@ -5,9 +5,10 @@ use Yoast\WP\SEO\Helpers\Indexable_Helper; use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; +use Yoast\WP\SEO\Repositories\Indexable_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Schema_Enhancement_Factory; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; -use Yoast\WP\SEO\Repositories\Indexable_Repository; /** * Repository for Schema_Piece objects. @@ -42,6 +43,13 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { */ private $adapter; + /** + * The schema enhancement factory. + * + * @var Schema_Enhancement_Factory + */ + private $enhancement_factory; + /** * Constructor. * @@ -49,17 +57,20 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. * @param Meta_Tags_Context_Memoizer_Adapter $adapter The adapter factory. + * @param Schema_Enhancement_Factory $enhancement_factory The schema enhancement factory. */ public function __construct( Meta_Tags_Context_Memoizer $memoizer, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository, - Meta_Tags_Context_Memoizer_Adapter $adapter + Meta_Tags_Context_Memoizer_Adapter $adapter, + Schema_Enhancement_Factory $enhancement_factory ) { $this->memoizer = $memoizer; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; $this->adapter = $adapter; + $this->enhancement_factory = $enhancement_factory; } /** @@ -78,12 +89,44 @@ public function get( int $page, int $page_size ): array { $schema_pieces = []; foreach ( $public_indexables as $indexable ) { - $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); - $context = $this->memoizer->get( $indexable, $page_type ); - $context_array = $this->adapter->meta_tags_context_to_array( $context ); - $schema_pieces[] = new Schema_Piece( $context_array, $page_type ); + $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); + $context = $this->memoizer->get( $indexable, $page_type ); + $context_array = $this->adapter->meta_tags_context_to_array( $context ); + $schema_piece = new Schema_Piece( $context_array, $page_type ); + $enhancer = $this->enhancement_factory->get_enhancer( $this->get_all_schema_types( $context_array['@graph'] ) ); + if ( $enhancer !== null ) { + $schema_piece = $enhancer->enhance( $schema_piece, $indexable ); + } + $schema_pieces[] = $schema_piece; } return $schema_pieces; } + + /** + * All schema types present in the schema piece. + * + * @param array> $graph The current graph. + * + * @return array + */ + public function get_all_schema_types( $graph ): array { + $schema_types = []; + foreach ( $graph as $schema_values ) { + foreach ( $schema_values as $key => $value ) { + if ( $key === '@type' ) { + if ( \is_array( $value ) ) { + foreach ( $value as $type_value ) { + $schema_types[ $type_value ] = $type_value; + } + continue; + } + $schema_types[ $value ] = $value; + + } + } + } + + return $schema_types; + } } diff --git a/src/schema_generator/infrastructure/site-schema-json-conditional.php b/src/schema_aggregator/infrastructure/site-schema-json-conditional.php similarity index 100% rename from src/schema_generator/infrastructure/site-schema-json-conditional.php rename to src/schema_aggregator/infrastructure/site-schema-json-conditional.php diff --git a/src/schema_generator/user-interface/site-schema-aggregator-cli-command.php b/src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php similarity index 100% rename from src/schema_generator/user-interface/site-schema-aggregator-cli-command.php rename to src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php diff --git a/src/schema_generator/user-interface/site-schema-aggregator-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-route.php similarity index 100% rename from src/schema_generator/user-interface/site-schema-aggregator-route.php rename to src/schema_aggregator/user-interface/site-schema-aggregator-route.php index 8d2178ba709..e313038c836 100644 --- a/src/schema_generator/user-interface/site-schema-aggregator-route.php +++ b/src/schema_aggregator/user-interface/site-schema-aggregator-route.php @@ -7,11 +7,11 @@ use WP_REST_Response; use Yoast\WP\SEO\Helpers\Capability_Helper; use Yoast\WP\SEO\Main; +use Yoast\WP\SEO\Routes\Route_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; -use Yoast\WP\SEO\Routes\Route_Interface; /** * Handles the route to represent a site's schema as JSON. diff --git a/src/schema_generator/application/enhancement/article-schema-enhancer.php b/src/schema_generator/application/enhancement/article-schema-enhancer.php deleted file mode 100644 index 9b14ce55202..00000000000 --- a/src/schema_generator/application/enhancement/article-schema-enhancer.php +++ /dev/null @@ -1,20 +0,0 @@ - Date: Fri, 31 Oct 2025 12:28:04 +0100 Subject: [PATCH 042/319] Fix DI --- src/repositories/indexable-repository.php | 1 - .../enhancement/article-schema-enhancer.php | 12 +++++-- .../schema-enhancement-factory.php | 32 +++++++++++++++++-- .../site-schema-aggregator-route.php | 4 +-- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/repositories/indexable-repository.php b/src/repositories/indexable-repository.php index 9ccc1d8b877..f2575acb94b 100644 --- a/src/repositories/indexable-repository.php +++ b/src/repositories/indexable-repository.php @@ -233,7 +233,6 @@ public function find_all_public_paginated( $page, $page_size, $post_type_exclude $query->where_not_in( 'object_sub_type', $post_type_exclude_list ); } $indexables = $query->order_by_asc( 'id' )->limit( $page_size )->offset( $offset )->find_many(); - return \array_map( [ $this, 'upgrade_indexable' ], $indexables ); } diff --git a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php index c6936041f6c..bf4f97a10f7 100644 --- a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php +++ b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php @@ -23,9 +23,10 @@ class Article_Schema_Enhancer extends Abstract_Schema_Enhancer implements Schema /** * Sets the Article_Config instance. * - * @param Article_Config $config The Article_Config instance. * @required * + * @param Article_Config $config The Article_Config instance. + * * @return void */ public function set_article_config( Article_Config $config ) { @@ -43,12 +44,17 @@ public function set_article_config( Article_Config $config ) { public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Schema_Piece { $data = $schema_piece->get_data(); - foreach ( $data as $key => $schema_data ) { + foreach ( $data['@graph'] as $key => $schema_data ) { + if ( isset( $schema_data['@type'] ) && ( $schema_data['@type'] === 'Article' || $schema_data['@type'] === 'NewsArticle' || $schema_data['@type'] === 'BlogPosting' ) ) { $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); } - } + if ( + isset( $schema_data['@type'] ) && \is_array( $schema_data['@type'] ) && \in_array( 'Article', $schema_data['@type'], true ) ) { + $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); + } + } return new Schema_Piece( $data, $schema_piece->get_type() ); } diff --git a/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php b/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php index 7add6539547..fc16636dcca 100644 --- a/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php +++ b/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php @@ -9,6 +9,34 @@ */ class Schema_Enhancement_Factory { + /** + * The schema enhancer. + * + * @var Article_Schema_Enhancer + */ + private $article_schema_enhancer; + + /** + * The person schema enhancer. + * + * @var Person_Schema_Enhancer + */ + private $person_schema_enhancer; + + /** + * Constructor. + * + * @param Article_Schema_Enhancer $article_schema_enhancer The article schema enhancer. + * @param Person_Schema_Enhancer $person_schema_enhancer The person schema enhancer. + */ + public function __construct( + Article_Schema_Enhancer $article_schema_enhancer, + Person_Schema_Enhancer $person_schema_enhancer + ) { + $this->article_schema_enhancer = $article_schema_enhancer; + $this->person_schema_enhancer = $person_schema_enhancer; + } + /** * Returns the appropriate schema enhancer based on the schema type. * @@ -20,9 +48,9 @@ public function get_enhancer( array $schema_types ): ?Schema_Enhancement_Interfa foreach ( $schema_types as $schema_type_value ) { switch ( $schema_type_value ) { case 'Article': - return new Article_Schema_Enhancer(); + return $this->article_schema_enhancer; case 'Person': - return new Person_Schema_Enhancer(); + return $this->person_schema_enhancer; default: return null; // No enhancer available for the given schema type. } diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-route.php index e313038c836..581f7a50e46 100644 --- a/src/schema_aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema_aggregator/user-interface/site-schema-aggregator-route.php @@ -136,9 +136,9 @@ public function aggregate_site_schema( WP_REST_Request $request ) { (object) [] ); } - $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); + return new WP_REST_Response( - $output, + $result, ( $result ) ? 200 : 400 ); } From a33bcb2a085f5973f02931171bb3ce9bfd16bf2c Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Fri, 31 Oct 2025 13:33:37 +0100 Subject: [PATCH 043/319] Final small updates. --- .../enhancement/article-schema-enhancer.php | 2 +- .../enhancement/person-schema-enhancer.php | 42 +------------------ .../enhancement/person-config.php | 1 - 3 files changed, 2 insertions(+), 43 deletions(-) diff --git a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php index bf4f97a10f7..24e64ec3579 100644 --- a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php +++ b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php @@ -123,7 +123,7 @@ private function get_article_keywords( int $post_id ): array { } } - if ( $this->config->get_config_value( 'categories_as_keywords', true ) ) { + if ( $this->config->get_config_value( 'categories_as_keywords', false ) ) { $categories = \get_the_category( $post_id ); if ( \is_array( $categories ) && ! empty( $categories ) ) { foreach ( $categories as $category ) { diff --git a/src/schema_aggregator/application/enhancement/person-schema-enhancer.php b/src/schema_aggregator/application/enhancement/person-schema-enhancer.php index b452835a5c0..952e2e60b16 100644 --- a/src/schema_aggregator/application/enhancement/person-schema-enhancer.php +++ b/src/schema_aggregator/application/enhancement/person-schema-enhancer.php @@ -6,7 +6,6 @@ use Yoast\WP\SEO\Models\Indexable; use Yoast\WP\SEO\Schema_Aggregator\Domain\Enhancement\Schema_Enhancement_Interface; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Article_Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Person_Config; /** @@ -17,7 +16,7 @@ class Person_Schema_Enhancer extends Abstract_Schema_Enhancer implements Schema_ /** * The config. * - * @var Article_Config + * @var Person_Config */ private $config; @@ -69,51 +68,12 @@ private function enhance_schema_piece( $schema_data, $indexable ) { } } - if ( $this->config->is_enhancement_enabled( 'person_bio' ) ) { - $max_length = $this->config->get_config_value( 'person_bio_max_length', 0 ); - $current_bio = ( $schema_data['description'] ?? '' ); - - // Only replace if configured for unlimited or longer than current. - if ( $max_length === 0 || \strlen( $current_bio ) < $max_length ) { - $full_bio = $this->get_person_bio( $indexable->author_id, $max_length ); - if ( $full_bio !== null && $full_bio !== '' && $full_bio !== $current_bio ) { - $schema_data['description'] = $full_bio; - } - } - } - return $schema_data; } catch ( Exception $e ) { return $schema_data; } } - /** - * Get person bio - * - * Retrieves user bio with optional length limit. - * - * @param int $user_id User ID. - * @param int $max_length Maximum length (0 = unlimited). - * - * @return string|null Bio or null if unavailable. - */ - private function get_person_bio( int $user_id, int $max_length = 0 ): ?string { - try { - $bio = \get_user_meta( $user_id, 'description', true ); - - if ( empty( $bio ) ) { - return null; - } - - $bio = \trim( $bio ); - - return $this->trim_content_to_max_length( $max_length, $bio ); - } catch ( Exception $e ) { - return null; - } - } - /** * Get person job title * diff --git a/src/schema_aggregator/infrastructure/enhancement/person-config.php b/src/schema_aggregator/infrastructure/enhancement/person-config.php index 2abc1b8c269..fc51a9cb0a0 100644 --- a/src/schema_aggregator/infrastructure/enhancement/person-config.php +++ b/src/schema_aggregator/infrastructure/enhancement/person-config.php @@ -30,7 +30,6 @@ public function get_config_value( string $key, $the_default ) { */ public function is_enhancement_enabled( string $enhancement ): bool { $defaults = [ - 'person_bio' => true, 'person_job_title' => true, ]; From 0275873c3184cf6efee9676bdc54d87fb0f3c370 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:14:24 +0100 Subject: [PATCH 044/319] Update src/schema-aggregator/application/properties-filter.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/application/properties-filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/properties-filter.php b/src/schema-aggregator/application/properties-filter.php index cefd8d0ac7e..04f5ff10654 100644 --- a/src/schema-aggregator/application/properties-filter.php +++ b/src/schema-aggregator/application/properties-filter.php @@ -36,7 +36,7 @@ public function __construct( Config $config ) { * which have been filtered out from the allowed types. * * Also removes 'potentialAction' properties (ReadAction, CommentAction, SearchAction) - * which are added by Yoast but not needed for NLWeb integration. + * which are added by Yoast but not needed for schema aggregation integration. * * @param Schema_Piece $piece The schema piece. * From 546124d8be058939bba29dc15955f229a2fdb693 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:14:33 +0100 Subject: [PATCH 045/319] Update src/schema-aggregator/application/properties-filter.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/application/properties-filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/properties-filter.php b/src/schema-aggregator/application/properties-filter.php index 04f5ff10654..83201e05e4a 100644 --- a/src/schema-aggregator/application/properties-filter.php +++ b/src/schema-aggregator/application/properties-filter.php @@ -43,7 +43,7 @@ public function __construct( Config $config ) { * @return Schema_Piece Cleaned schema piece. */ public function filter( Schema_Piece $piece ): Schema_Piece { - // Properties to remove (references to filtered-out entities and unwanted actions). + $properties_to_remove = $this->config->get_properties_avoid_list(); $data = $piece->get_data(); From 5b9f123cc4d09fbe1fae45031c988b6ac2a747e5 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:14:48 +0100 Subject: [PATCH 046/319] Update src/schema-aggregator/application/properties-merger.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/application/properties-merger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index 1dd1d70f8ac..1a893d47df3 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -27,7 +27,7 @@ public function merge( Schema_Piece $piece1, Schema_Piece $piece2 ): Schema_Piec /** * Merge properties from two schema entities with the same @id * - * Strategy (FR-012): + * Strategy: * - @type: Special handling - merge types into unified array * - @id: Skip (always the same) * - Arrays: Combine unique values From edd78ae219250154f3f097460644dec089fdabc4 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:15:14 +0100 Subject: [PATCH 047/319] Update src/schema-aggregator/application/properties-merger.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/application/properties-merger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index 1a893d47df3..f59694fd21a 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -44,7 +44,7 @@ private function merge_properties( array $entity1, array $entity2 ): array { $merged = $entity1; foreach ( $entity2 as $key => $value ) { - // Skip @id - these should always be the same. + if ( $key === '@id' ) { continue; } From 64681d371f6907953519f3b687c0bf663ced1cd2 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:15:24 +0100 Subject: [PATCH 048/319] Update src/schema-aggregator/application/properties-merger.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/application/properties-merger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index f59694fd21a..3b9ee929786 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -59,7 +59,7 @@ private function merge_properties( array $entity1, array $entity2 ): array { } if ( ! isset( $merged[ $key ] ) || $merged[ $key ] === '' ) { - // Property doesn't exist in entity1 or is empty - use entity2's value. + $merged[ $key ] = $value; } elseif ( \is_array( $merged[ $key ] ) && \is_array( $value ) ) { From bf73f9972a1b5c833c4dffe5588086aef6bbaa89 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:15:39 +0100 Subject: [PATCH 049/319] Update src/schema-aggregator/infrastructure/config.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/infrastructure/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index af2d23ceef2..d013e1c99aa 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -78,7 +78,7 @@ public function get_allowed_post_types(): array { $default_post_types = self::DEFAULT_POST_TYPES; // Only include 'product' if Yoast WooCommerce SEO extension is active. - // The extension integrates WooCommerce Product schema into Yoast's @graph. + if ( $this->is_yoast_woocommerce_active() ) { $default_post_types[] = 'product'; } From 394e15426987b06e4c2bd29fc42df004deeb009b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:16:05 +0100 Subject: [PATCH 050/319] Update src/schema-aggregator/infrastructure/config.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/infrastructure/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index d013e1c99aa..3f9b2779b9d 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -101,7 +101,7 @@ public function get_allowed_post_types(): array { public function get_allowed_schema_types(): array { $schema_types = \apply_filters( 'wpseo_schema_aggregator_schema_types', self::DEFAULT_SCHEMA_TYPES ); - // Ensure it's an array. + if ( ! \is_array( $schema_types ) ) { return self::DEFAULT_SCHEMA_TYPES; } From 5e73213c415e5391a34031ad86e25d52d30de920 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:16:14 +0100 Subject: [PATCH 051/319] Update src/schema-aggregator/infrastructure/config.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/infrastructure/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 3f9b2779b9d..9a860b3ef34 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -117,7 +117,7 @@ public function get_allowed_schema_types(): array { public function get_properties_avoid_list(): array { $properties_avoid_list = \apply_filters( 'wpseo_schema_aggregator_properties_avoid_list', self::PROPERTIES_AVOID_LIST ); - // Ensure it's an array. + if ( ! \is_array( $properties_avoid_list ) ) { return self::PROPERTIES_AVOID_LIST; } From 7a1b734bdda767b4e4cc2163b96f2a22c76479d6 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:16:47 +0100 Subject: [PATCH 052/319] Update src/schema-aggregator/application/properties-merger.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/application/properties-merger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index 3b9ee929786..58215e0e7d2 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -98,7 +98,7 @@ private function merge_properties( array $entity1, array $entity2 ): array { * @return string|array Merged and normalized @type value. */ private function merge_types( $type1, $type2 ) { - // Normalize both to arrays. + $types1 = $this->normalize_type_to_array( $type1 ); $types2 = $this->normalize_type_to_array( $type2 ); From f5c29dd0f02401d7625729b998586d6661b110e8 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:36:33 +0100 Subject: [PATCH 053/319] Update src/schema-aggregator/application/schema-pieces-filter.php Co-authored-by: Thijs van der Heijden --- src/schema-aggregator/application/schema-pieces-filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php index 9527a9effa3..9e12bb33089 100644 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -81,7 +81,7 @@ public function has_allowed_type( Schema_Piece $piece ): bool { return false; } - // Neither an array or a string: Invalid @type format. + return false; } } From a958c4aafcfe5cb50210a9ea7c36c319c440f5b7 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 3 Nov 2025 14:39:57 +0100 Subject: [PATCH 054/319] Remove superfluous comments --- .../application/properties-merger.php | 20 +++++++++---------- .../application/schema-pieces-aggregator.php | 2 +- .../application/schema-pieces-filter.php | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index 58215e0e7d2..f287838295e 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -44,7 +44,7 @@ private function merge_properties( array $entity1, array $entity2 ): array { $merged = $entity1; foreach ( $entity2 as $key => $value ) { - + if ( $key === '@id' ) { continue; } @@ -59,7 +59,7 @@ private function merge_properties( array $entity1, array $entity2 ): array { } if ( ! isset( $merged[ $key ] ) || $merged[ $key ] === '' ) { - + $merged[ $key ] = $value; } elseif ( \is_array( $merged[ $key ] ) && \is_array( $value ) ) { @@ -98,14 +98,14 @@ private function merge_properties( array $entity1, array $entity2 ): array { * @return string|array Merged and normalized @type value. */ private function merge_types( $type1, $type2 ) { - + $types1 = $this->normalize_type_to_array( $type1 ); $types2 = $this->normalize_type_to_array( $type2 ); - // Combine and deduplicate. + $merged = \array_unique( \array_merge( $types1, $types2 ), \SORT_REGULAR ); - // Normalize result: string if 1 type, array if multiple. + return $this->normalize_type_from_array( $merged ); } @@ -125,16 +125,16 @@ private function normalize_type_to_array( $type ): array { } if ( \is_array( $type ) ) { - // Filter out non-strings for safety. + return \array_values( \array_filter( $type, 'is_string' ) ); } - // Invalid type format. + return []; } /** - * Normalize array of types back to string or array + * Normalize array of types back to string or array. * * Returns string if single type, array if multiple types. * This keeps the output compact while supporting multi-type entities. @@ -152,10 +152,10 @@ private function normalize_type_from_array( array $types ) { } if ( \count( $types ) === 1 ) { - return $types[0]; // Return as string for single type. + return $types[0]; } - return $types; // Return as array for multiple types. + return $types; } /** diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 27620ecbc42..0dc4af24762 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -80,7 +80,7 @@ public function aggregate( array $schema_pieces ): array { } if ( isset( $aggregated_schema[ $id ] ) ) { - // Merge properties if the piece already exists. + $aggregated_schema[ $id ] = $this->properties_merger->merge( $aggregated_schema[ $id ], $piece ); } else { diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php index 9e12bb33089..c9b6797cbe5 100644 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -59,12 +59,12 @@ public function get_allowed_types(): array { */ public function has_allowed_type( Schema_Piece $piece ): bool { $type = $piece->get_type(); - // Handle string @type. + if ( \is_string( $type ) ) { return $this->is_allowed_type( $type ); } - // Handle array @type (JSON-LD allows multiple types). + if ( \is_array( $type ) ) { foreach ( $type as $single_type ) { // Validate each type is a string. @@ -72,16 +72,16 @@ public function has_allowed_type( Schema_Piece $piece ): bool { continue; } - // Check if this type is allowed. + if ( $this->is_allowed_type( $single_type ) ) { - return true; // At least one type is allowed. + return true; } } return false; } - + return false; } } From ab81aaa57f072dc1aeef56aa23e8603c21c950ab Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 3 Nov 2025 14:46:40 +0100 Subject: [PATCH 055/319] Fix cs --- src/schema-aggregator/application/properties-filter.php | 2 +- src/schema-aggregator/application/properties-merger.php | 3 --- src/schema-aggregator/application/schema-pieces-filter.php | 3 --- src/schema-aggregator/infrastructure/config.php | 4 +--- 4 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/schema-aggregator/application/properties-filter.php b/src/schema-aggregator/application/properties-filter.php index 83201e05e4a..6e5c4edb708 100644 --- a/src/schema-aggregator/application/properties-filter.php +++ b/src/schema-aggregator/application/properties-filter.php @@ -43,7 +43,7 @@ public function __construct( Config $config ) { * @return Schema_Piece Cleaned schema piece. */ public function filter( Schema_Piece $piece ): Schema_Piece { - + $properties_to_remove = $this->config->get_properties_avoid_list(); $data = $piece->get_data(); diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index f287838295e..5fb1f0cb71e 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -102,10 +102,8 @@ private function merge_types( $type1, $type2 ) { $types1 = $this->normalize_type_to_array( $type1 ); $types2 = $this->normalize_type_to_array( $type2 ); - $merged = \array_unique( \array_merge( $types1, $types2 ), \SORT_REGULAR ); - return $this->normalize_type_from_array( $merged ); } @@ -129,7 +127,6 @@ private function normalize_type_to_array( $type ): array { return \array_values( \array_filter( $type, 'is_string' ) ); } - return []; } diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php index c9b6797cbe5..6ad03fa6a2c 100644 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -64,7 +64,6 @@ public function has_allowed_type( Schema_Piece $piece ): bool { return $this->is_allowed_type( $type ); } - if ( \is_array( $type ) ) { foreach ( $type as $single_type ) { // Validate each type is a string. @@ -72,7 +71,6 @@ public function has_allowed_type( Schema_Piece $piece ): bool { continue; } - if ( $this->is_allowed_type( $single_type ) ) { return true; } @@ -81,7 +79,6 @@ public function has_allowed_type( Schema_Piece $piece ): bool { return false; } - return false; } } diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 9a860b3ef34..7df73433bc7 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -78,7 +78,7 @@ public function get_allowed_post_types(): array { $default_post_types = self::DEFAULT_POST_TYPES; // Only include 'product' if Yoast WooCommerce SEO extension is active. - + if ( $this->is_yoast_woocommerce_active() ) { $default_post_types[] = 'product'; } @@ -101,7 +101,6 @@ public function get_allowed_post_types(): array { public function get_allowed_schema_types(): array { $schema_types = \apply_filters( 'wpseo_schema_aggregator_schema_types', self::DEFAULT_SCHEMA_TYPES ); - if ( ! \is_array( $schema_types ) ) { return self::DEFAULT_SCHEMA_TYPES; } @@ -117,7 +116,6 @@ public function get_allowed_schema_types(): array { public function get_properties_avoid_list(): array { $properties_avoid_list = \apply_filters( 'wpseo_schema_aggregator_properties_avoid_list', self::PROPERTIES_AVOID_LIST ); - if ( ! \is_array( $properties_avoid_list ) ) { return self::PROPERTIES_AVOID_LIST; } From 51ab902763bee26cc8a6c70e292d319700fdc078 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 3 Nov 2025 14:49:42 +0100 Subject: [PATCH 056/319] Feedback Paolo --- .../enhancement/article-schema-enhancer.php | 31 +++++++++++++------ .../enhancement/article-config.php | 2 ++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php index 24e64ec3579..47184375b53 100644 --- a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php +++ b/src/schema_aggregator/application/enhancement/article-schema-enhancer.php @@ -45,16 +45,28 @@ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Sch $data = $schema_piece->get_data(); foreach ( $data['@graph'] as $key => $schema_data ) { - - if ( isset( $schema_data['@type'] ) && ( $schema_data['@type'] === 'Article' || $schema_data['@type'] === 'NewsArticle' || $schema_data['@type'] === 'BlogPosting' ) ) { + if ( ! isset( $schema_data['@type'] ) ) { + continue; + } + if ( + \in_array( + $schema_data['@type'], + [ + 'Article', + 'NewsArticle', + 'BlogPosting', + ], + true + ) ) { $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); } if ( - isset( $schema_data['@type'] ) && \is_array( $schema_data['@type'] ) && \in_array( 'Article', $schema_data['@type'], true ) ) { + \is_array( $schema_data['@type'] ) && \in_array( 'Article', $schema_data['@type'], true ) ) { $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); } } + return new Schema_Piece( $data, $schema_piece->get_type() ); } @@ -72,23 +84,23 @@ private function enhance_schema_piece( $schema_data, $indexable ) { if ( $this->config->is_enhancement_enabled( 'use_excerpt' ) ) { $excerpt = $this->get_excerpt( $indexable->object_id ); - $has_excerpt = ( $excerpt !== null && $excerpt !== '' ); + $has_excerpt = ! empty( $excerpt ); - if ( $has_excerpt && ! isset( $entity['description'] ) ) { + if ( $has_excerpt && ! isset( $schema_data['description'] ) ) { $schema_data['description'] = $excerpt; } } - if ( $this->config->is_enhancement_enabled( 'article_body' ) && ! isset( $entity['articleBody'] ) ) { + if ( $this->config->is_enhancement_enabled( 'article_body' ) && ! isset( $schema_data['articleBody'] ) ) { if ( $this->config->should_include_article_body( $has_excerpt ) ) { $article_body = $this->get_article_body( $indexable->object_id ); - if ( $article_body !== null && $article_body !== '' ) { + if ( ! empty( $article_body ) ) { $schema_data['articleBody'] = $article_body; } } } - if ( $this->config->is_enhancement_enabled( 'keywords' ) && ! isset( $entity['keywords'] ) ) { + if ( $this->config->is_enhancement_enabled( 'keywords' ) && ! isset( $schema_data['keywords'] ) ) { $keywords = $this->get_article_keywords( $indexable->object_id ); if ( ! empty( $keywords ) ) { $schema_data['keywords'] = \implode( ', ', $keywords ); @@ -213,8 +225,7 @@ private function get_article_body( int $post_id ): ?string { $content = \wp_strip_all_tags( $content ); } - // Apply max length if configured (default: 500 chars). - $max_length = $this->config->get_config_value( 'article_body_max_length', 500 ); + $max_length = $this->config->get_config_value( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ); return $this->trim_content_to_max_length( $max_length, $content ); } catch ( Exception $e ) { diff --git a/src/schema_aggregator/infrastructure/enhancement/article-config.php b/src/schema_aggregator/infrastructure/enhancement/article-config.php index 5011cee1f25..294c9d782d4 100644 --- a/src/schema_aggregator/infrastructure/enhancement/article-config.php +++ b/src/schema_aggregator/infrastructure/enhancement/article-config.php @@ -9,6 +9,8 @@ */ class Article_Config implements Enhancement_Config_Interface { + public const DEFAULT_MAX_ARTICLE_BODY_LENGTH = 500; + /** * Get configuration value * From 6c6c97a06bca30f79fc9ab5d192220a3b31ad28e Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 4 Nov 2025 13:37:39 +0100 Subject: [PATCH 057/319] Rename mistake by me... --- .../application/aggregate-site-schema-command-handler.php | 0 .../application/aggregate-site-schema-command.php | 0 .../domain/page-controls.php | 0 .../domain/schema-piece-repository-interface.php | 0 .../domain/schema-piece.php | 0 .../infrastructure/config.php | 0 .../infrastructure/meta-tags-context-memoizer-adapter.php | 0 .../infrastructure/schema-piece-repository.php | 0 .../infrastructure/site-schema-json-conditional.php | 0 .../user-interface/site-schema-aggregator-cli-command.php | 0 .../user-interface/site-schema-aggregator-route.php | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename src/{schema_generator => schema_aggregator}/application/aggregate-site-schema-command-handler.php (100%) rename src/{schema_generator => schema_aggregator}/application/aggregate-site-schema-command.php (100%) rename src/{schema_generator => schema_aggregator}/domain/page-controls.php (100%) rename src/{schema_generator => schema_aggregator}/domain/schema-piece-repository-interface.php (100%) rename src/{schema_generator => schema_aggregator}/domain/schema-piece.php (100%) rename src/{schema_generator => schema_aggregator}/infrastructure/config.php (100%) rename src/{schema_generator => schema_aggregator}/infrastructure/meta-tags-context-memoizer-adapter.php (100%) rename src/{schema_generator => schema_aggregator}/infrastructure/schema-piece-repository.php (100%) rename src/{schema_generator => schema_aggregator}/infrastructure/site-schema-json-conditional.php (100%) rename src/{schema_generator => schema_aggregator}/user-interface/site-schema-aggregator-cli-command.php (100%) rename src/{schema_generator => schema_aggregator}/user-interface/site-schema-aggregator-route.php (100%) diff --git a/src/schema_generator/application/aggregate-site-schema-command-handler.php b/src/schema_aggregator/application/aggregate-site-schema-command-handler.php similarity index 100% rename from src/schema_generator/application/aggregate-site-schema-command-handler.php rename to src/schema_aggregator/application/aggregate-site-schema-command-handler.php diff --git a/src/schema_generator/application/aggregate-site-schema-command.php b/src/schema_aggregator/application/aggregate-site-schema-command.php similarity index 100% rename from src/schema_generator/application/aggregate-site-schema-command.php rename to src/schema_aggregator/application/aggregate-site-schema-command.php diff --git a/src/schema_generator/domain/page-controls.php b/src/schema_aggregator/domain/page-controls.php similarity index 100% rename from src/schema_generator/domain/page-controls.php rename to src/schema_aggregator/domain/page-controls.php diff --git a/src/schema_generator/domain/schema-piece-repository-interface.php b/src/schema_aggregator/domain/schema-piece-repository-interface.php similarity index 100% rename from src/schema_generator/domain/schema-piece-repository-interface.php rename to src/schema_aggregator/domain/schema-piece-repository-interface.php diff --git a/src/schema_generator/domain/schema-piece.php b/src/schema_aggregator/domain/schema-piece.php similarity index 100% rename from src/schema_generator/domain/schema-piece.php rename to src/schema_aggregator/domain/schema-piece.php diff --git a/src/schema_generator/infrastructure/config.php b/src/schema_aggregator/infrastructure/config.php similarity index 100% rename from src/schema_generator/infrastructure/config.php rename to src/schema_aggregator/infrastructure/config.php diff --git a/src/schema_generator/infrastructure/meta-tags-context-memoizer-adapter.php b/src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php similarity index 100% rename from src/schema_generator/infrastructure/meta-tags-context-memoizer-adapter.php rename to src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php diff --git a/src/schema_generator/infrastructure/schema-piece-repository.php b/src/schema_aggregator/infrastructure/schema-piece-repository.php similarity index 100% rename from src/schema_generator/infrastructure/schema-piece-repository.php rename to src/schema_aggregator/infrastructure/schema-piece-repository.php diff --git a/src/schema_generator/infrastructure/site-schema-json-conditional.php b/src/schema_aggregator/infrastructure/site-schema-json-conditional.php similarity index 100% rename from src/schema_generator/infrastructure/site-schema-json-conditional.php rename to src/schema_aggregator/infrastructure/site-schema-json-conditional.php diff --git a/src/schema_generator/user-interface/site-schema-aggregator-cli-command.php b/src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php similarity index 100% rename from src/schema_generator/user-interface/site-schema-aggregator-cli-command.php rename to src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php diff --git a/src/schema_generator/user-interface/site-schema-aggregator-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-route.php similarity index 100% rename from src/schema_generator/user-interface/site-schema-aggregator-route.php rename to src/schema_aggregator/user-interface/site-schema-aggregator-route.php From 2dcd4014019300e65dc7bda7c0d76f8d7e26fc01 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 4 Nov 2025 15:10:08 +0100 Subject: [PATCH 058/319] Start implementation. --- ...regate-site-schema-map-command-handler.php | 16 +++ .../aggregate-site-schema-map-command.php | 46 +++++++ .../site-schema-aggregator-xml-route.php | 124 ++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php create mode 100644 src/schema_aggregator/application/aggregate-site-schema-map-command.php create mode 100644 src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php new file mode 100644 index 00000000000..a0366a6991b --- /dev/null +++ b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php @@ -0,0 +1,16 @@ + The schema map xml. + */ + public function handle( Aggregate_Site_Schema_Map_Command $command ): string { + + } +} diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command.php b/src/schema_aggregator/application/aggregate-site-schema-map-command.php new file mode 100644 index 00000000000..f7f03ae81bf --- /dev/null +++ b/src/schema_aggregator/application/aggregate-site-schema-map-command.php @@ -0,0 +1,46 @@ + + */ + private $post_types; + + /** + * The schema map threshold. + * + * @var int + */ + private $schema_map_threshold; + + public function __construct( array $post_types, int $schema_map_threshold ) { + $this->post_types = $post_types; + $this->schema_map_threshold = $schema_map_threshold; + } + + /** + * Gets the post types to include in the schema map. + * + * @return array The post types. + */ + public function get_post_types(): array { + return $this->post_types; + } + + /** + * Gets the schema map threshold. + * + * @return int The schema map threshold. + */ + public function get_schema_map_threshold(): int { + return $this->schema_map_threshold; + } + + +} + diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php new file mode 100644 index 00000000000..7ef0266b5bf --- /dev/null +++ b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -0,0 +1,124 @@ + The conditionals that must be met to load this. + */ + public static function get_conditionals() { + return [ Site_Schema_Json_Conditional::class ]; + } + + /** + * Site_Schema_Aggregator_Route constructor. + * + * @param Config $config The config object. + * @param Capability_Helper $capability_helper The capability helper. + * @param Aggregate_Site_Schema_Map_Command $aggregate_site_schema_map_command_handler The command handler. + */ + public function __construct( Config $config, Capability_Helper $capability_helper, Aggregate_Site_Schema_Map_Command $aggregate_site_schema_map_command_handler ) { + $this->config = $config; + $this->capability_helper = $capability_helper; + $this->aggregate_site_schema_map_command_handler = $aggregate_site_schema_map_command_handler; + } + + /** + * Registers routes with WordPress. + * + * @return void + */ + public function register_routes() { + $schema_aggregator_xml_route = [ + 'methods' => 'GET', + 'callback' => [ $this, 'render_schema_xml' ], + 'permission_callback' => [ $this, 'get_permission_callback' ], + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE, $schema_aggregator_xml_route ); + } + + /** + * Permission callback for the route. + * + * @return bool True if the user has permission, false otherwise. + */ + public function get_permission_callback(): bool { + return true; + } + + /** + * Returns a XML representation of the possible post types that can be used for schema. + * + * @param WP_REST_Request $request The request object. + * + * @return WP_REST_Response|WP_Error The success or failure response. + */ + public function render_schema_xml( WP_REST_Request $request ) { + + + + $response = new WP_REST_Response($xml, 200); + $response->header('Content-Type', 'application/xml; charset=UTF-8'); + $response->header('Cache-Control', 'public, max-age=300'); + + return $response; + + + } + +} From f468c3dbe39ba635f836ca81ab469579bb093ddb Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 5 Nov 2025 13:01:21 +0100 Subject: [PATCH 059/319] Implement schema map based on indexables. --- ...regate-site-schema-map-command-handler.php | 48 +++++++++- .../aggregate-site-schema-map-command.php | 7 +- .../schema_map/schema-map-builder.php | 50 +++++++++++ .../schema_map/schema-map-xml-renderer.php | 89 +++++++++++++++++++ .../infrastructure/config.php | 16 ++++ .../schema-piece-repository.php | 2 +- .../schema_map/schema-map-config.php | 45 ++++++++++ .../schema-map-indexable-repository.php | 50 +++++++++++ .../site-schema-aggregator-route.php | 2 +- .../site-schema-aggregator-xml-route.php | 48 ++++++---- ...ite-schema-response-header-integration.php | 72 +++++++++++++++ 11 files changed, 404 insertions(+), 25 deletions(-) create mode 100644 src/schema_aggregator/application/schema_map/schema-map-builder.php create mode 100644 src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php create mode 100644 src/schema_aggregator/infrastructure/schema_map/schema-map-config.php create mode 100644 src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php create mode 100644 src/schema_aggregator/user-interface/site-schema-response-header-integration.php diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php index a0366a6991b..58f73adb2e3 100644 --- a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php +++ b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php @@ -1,16 +1,62 @@ schema_map_indexable_repository = $schema_map_indexable_repository; + $this->schema_map_builder = $schema_map_builder; + $this->schema_map_xml_renderer = $schema_map_xml_renderer; + } + /** * Handles the Aggregate_Site_Schema_Map_Command. * * @param Aggregate_Site_Schema_Map_Command $command The command. * - * @return array The schema map xml. + * @return string The schema map xml. */ public function handle( Aggregate_Site_Schema_Map_Command $command ): string { + $indexable_counts = $this->schema_map_indexable_repository->get_indexable_count_per_post_type( $command->get_post_types() ); + + $threshold = $command->get_schema_map_threshold(); + + $schema_map = $this->schema_map_builder->get_schema_map( $indexable_counts, $threshold ); + + return $this->schema_map_xml_renderer->to_xml( $schema_map ); } } diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command.php b/src/schema_aggregator/application/aggregate-site-schema-map-command.php index f7f03ae81bf..ec37455229e 100644 --- a/src/schema_aggregator/application/aggregate-site-schema-map-command.php +++ b/src/schema_aggregator/application/aggregate-site-schema-map-command.php @@ -1,8 +1,8 @@ post_types = $post_types; + $this->post_types = $post_types; $this->schema_map_threshold = $schema_map_threshold; } @@ -40,7 +40,4 @@ public function get_post_types(): array { public function get_schema_map_threshold(): int { return $this->schema_map_threshold; } - - } - diff --git a/src/schema_aggregator/application/schema_map/schema-map-builder.php b/src/schema_aggregator/application/schema_map/schema-map-builder.php new file mode 100644 index 00000000000..b949e4fbb3a --- /dev/null +++ b/src/schema_aggregator/application/schema_map/schema-map-builder.php @@ -0,0 +1,50 @@ + $indexable_counts The indexable counts per post type. + * @param int $threshold The threshold for items per page. + * + * @return array> The schema map. + */ + public function get_schema_map( array $indexable_counts, int $threshold ): array { + $schema_map = []; + foreach ( $indexable_counts as $post_type => $count ) { + $total_pages = (int) \ceil( $count / $threshold ); + + for ( $page = 1; $page <= $total_pages; $page++ ) { + if ( $page === 1 && $total_pages === 1 ) { + $url = \rest_url( 'schema-aggregator/get-schema/' . $post_type ); + } + elseif ( $page === 1 ) { + $url = \rest_url( 'schema-aggregator/get-schema/' . $post_type ); + } + else { + $url = \rest_url( 'schema-aggregator/get-schema/' . $post_type . '/' . $page ); + } + + // Get lastmod for this specific page range. + // $lastmod = $this->get_lastmod_for_post_type($post_type, $page, $threshold); + + $page_count = ( $page === $total_pages ) ? ( $count - ( ( $page - 1 ) * $threshold ) ) : $threshold; + + $schema_map[] = [ + 'post_type' => $post_type, + 'url' => $url, + 'lastmod' => '', + 'count' => $page_count, + ]; + } + } + + return $schema_map; + } +} diff --git a/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php b/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php new file mode 100644 index 00000000000..2649dcbdc51 --- /dev/null +++ b/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php @@ -0,0 +1,89 @@ +config = $config; + } + + /** + * Converts the schema map to an XML string. + * + * @param array> $schema_map The schema map data. + * + * @return string The XML representation of the schema map. + * + * @throws RuntimeException If the input structure is invalid or XML generation fails. + */ + public function to_xml( array $schema_map ): string { + if ( ! isset( $schema_map ) || ! \is_array( $schema_map ) ) { + throw new RuntimeException( 'Invalid schemamap data structure: missing or invalid "schemamap" key' ); + } + + $dom = new DOMDocument( '1.0', 'UTF-8' ); + $dom->formatOutput = true; + + $url_set = $dom->createElement( 'urlset' ); + $url_set->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' ); + $dom->appendChild( $url_set ); + + $change_freq = $this->config->getChangefreq(); + $priority = $this->config->getPriority(); + + foreach ( $schema_map as $entry ) { + if ( ! isset( $entry['url'] ) || ! isset( $entry['lastmod'] ) ) { + continue; + } + + $url = $dom->createElement( 'url' ); + + $url->setAttribute( 'contentType', 'structuredData/schema.org' ); + + $loc = $dom->createElement( 'loc' ); + $loc->appendChild( $dom->createTextNode( $entry['url'] ) ); + $url->appendChild( $loc ); + + $last_mod = $dom->createElement( 'lastmod' ); + $last_mod->appendChild( $dom->createTextNode( $entry['lastmod'] ) ); + $url->appendChild( $last_mod ); + + $cf = $dom->createElement( 'changefreq' ); + $cf->appendChild( $dom->createTextNode( $change_freq ) ); + $url->appendChild( $cf ); + + $prio = $dom->createElement( 'priority' ); + $prio->appendChild( $dom->createTextNode( $priority ) ); + $url->appendChild( $prio ); + + $url_set->appendChild( $url ); + } + + $xml = $dom->saveXML(); + if ( $xml === false ) { + throw new RuntimeException( 'Failed to generate XML from DOMDocument' ); + } + + return $xml; + } +} diff --git a/src/schema_aggregator/infrastructure/config.php b/src/schema_aggregator/infrastructure/config.php index ac165b8b70c..becf00f9cc2 100644 --- a/src/schema_aggregator/infrastructure/config.php +++ b/src/schema_aggregator/infrastructure/config.php @@ -21,6 +21,13 @@ class Config { */ private const MAX_PER_PAGE = 100; + /** + * Maximum items per page + * + * @var int + */ + private const DEFAULT_SCHEMA_MAP_THRESHOLD = 10; + /** * Get default items per page * @@ -30,6 +37,15 @@ public function get_per_page(): int { return (int) \apply_filters( 'wpseo_schema_aggregator_aggregator_per_page', self::DEFAULT_PER_PAGE ); } + /** + * Get default items per page + * + * @return int + */ + public function get_schema_map_threshold(): int { + return (int) \apply_filters( 'wpseo_schema_aggregator_schema_map_threshold', self::DEFAULT_SCHEMA_MAP_THRESHOLD ); + } + /** * Get maximum items per page * diff --git a/src/schema_aggregator/infrastructure/schema-piece-repository.php b/src/schema_aggregator/infrastructure/schema-piece-repository.php index 8144b005933..428c363577d 100644 --- a/src/schema_aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema_aggregator/infrastructure/schema-piece-repository.php @@ -5,9 +5,9 @@ use Yoast\WP\SEO\Helpers\Indexable_Helper; use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; +use Yoast\WP\SEO\Repositories\Indexable_Repository; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; -use Yoast\WP\SEO\Repositories\Indexable_Repository; /** * Repository for Schema_Piece objects. diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php new file mode 100644 index 00000000000..37c6599c42f --- /dev/null +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php @@ -0,0 +1,45 @@ + 1.0 ) { + \error_log( "Yoast NLWeb SitemapRenderer: Invalid priority '{$priority}', using default '0.8'" ); + return '0.8'; + } + + // Return as string with one decimal place + return \number_format( $priority_float, 1, '.', '' ); + } +} diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php new file mode 100644 index 00000000000..5162890cb43 --- /dev/null +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -0,0 +1,50 @@ +indexable_repository = $indexable_repository; + } + + /** + * Gets the indexable count per post type. + * + * @param array $post_types The post types to get the indexable count for. + * + * @return array The indexable count per post type. + */ + public function get_indexable_count_per_post_type( array $post_types ): array { + $post_type_counts = []; + $indexable_raw_value = $this->indexable_repository->query() + ->select_expr( 'object_sub_type,count(object_sub_type) as count' ) + ->where_in( 'object_sub_type', $post_types ) + ->group_by( [ 'object_type', 'object_sub_type' ] ) + ->find_array(); + + if ( empty( $indexable_raw_value ) ) { + return $post_type_counts; + } + + foreach ( $indexable_raw_value as $indexable ) { + $post_type_counts[ $indexable['object_sub_type'] ] = $indexable['count']; + } + + return $post_type_counts; + } +} diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-route.php index 8d2178ba709..e313038c836 100644 --- a/src/schema_aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema_aggregator/user-interface/site-schema-aggregator-route.php @@ -7,11 +7,11 @@ use WP_REST_Response; use Yoast\WP\SEO\Helpers\Capability_Helper; use Yoast\WP\SEO\Main; +use Yoast\WP\SEO\Routes\Route_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; -use Yoast\WP\SEO\Routes\Route_Interface; /** * Handles the route to represent a site's schema as JSON. diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php index 7ef0266b5bf..8a095a20770 100644 --- a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -6,13 +6,13 @@ use WP_REST_Request; use WP_REST_Response; use Yoast\WP\SEO\Helpers\Capability_Helper; +use Yoast\WP\SEO\Helpers\Post_Type_Helper; use Yoast\WP\SEO\Main; -use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; -use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; +use Yoast\WP\SEO\Routes\Route_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command; +use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; -use Yoast\WP\SEO\Routes\Route_Interface; /** * Handles the route to represent all indexable post types as XML. @@ -51,10 +51,17 @@ class Site_Schema_Aggregator_Xml_Route implements Route_Interface { /** * The command handler instance. * - * @var Aggregate_Site_Schema_Map_Command + * @var Aggregate_Site_Schema_Map_Command_Handler */ private $aggregate_site_schema_map_command_handler; + /** + * The post type helper instance. + * + * @var Post_Type_Helper + */ + private $post_type_helper; + /** * Returns the conditional for this route. * @@ -67,14 +74,21 @@ public static function get_conditionals() { /** * Site_Schema_Aggregator_Route constructor. * - * @param Config $config The config object. - * @param Capability_Helper $capability_helper The capability helper. - * @param Aggregate_Site_Schema_Map_Command $aggregate_site_schema_map_command_handler The command handler. + * @param Config $config The config object. + * @param Capability_Helper $capability_helper The capability helper. + * @param Aggregate_Site_Schema_Map_Command_Handler $aggregate_site_schema_map_command_handler The command handler. + * @param Post_type_Helper $post_type_helper The post type helper. */ - public function __construct( Config $config, Capability_Helper $capability_helper, Aggregate_Site_Schema_Map_Command $aggregate_site_schema_map_command_handler ) { - $this->config = $config; - $this->capability_helper = $capability_helper; + public function __construct( + Config $config, + Capability_Helper $capability_helper, + Aggregate_Site_Schema_Map_Command_Handler $aggregate_site_schema_map_command_handler, + Post_type_Helper $post_type_helper + ) { + $this->config = $config; + $this->capability_helper = $capability_helper; $this->aggregate_site_schema_map_command_handler = $aggregate_site_schema_map_command_handler; + $this->post_type_helper = $post_type_helper; } /** @@ -110,15 +124,15 @@ public function get_permission_callback(): bool { */ public function render_schema_xml( WP_REST_Request $request ) { + $post_types = $this->post_type_helper->get_indexable_post_types(); + $command = new Aggregate_Site_Schema_Map_Command( $post_types, $this->config->get_schema_map_threshold() ); + $xml = $this->aggregate_site_schema_map_command_handler->handle( $command ); - $response = new WP_REST_Response($xml, 200); - $response->header('Content-Type', 'application/xml; charset=UTF-8'); - $response->header('Cache-Control', 'public, max-age=300'); - - return $response; - + $response = new WP_REST_Response( $xml, 200 ); + $response->header( 'Content-Type', 'application/xml; charset=UTF-8' ); + $response->header( 'Cache-Control', 'public, max-age=300' ); + return $response; } - } diff --git a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php new file mode 100644 index 00000000000..4dcb2bd9165 --- /dev/null +++ b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php @@ -0,0 +1,72 @@ +get_route(), '/yoast/v1/schema-aggregator' ) !== 0 ) { + return $served; + } + + if ( ! $result instanceof WP_REST_Response || $result->is_error() ) { + return $served; + } + + $data = $result->get_data(); + + foreach ( $result->get_headers() as $key => $value ) { + \header( \sprintf( '%s: %s', $key, $value ) ); + } + + $headers = $result->get_headers(); + $content_type = ( $headers['Content-Type'] ?? 'application/json; charset=UTF-8' ); + + if ( \strpos( $content_type, 'application/xml' ) !== false ) { + // For XML responses, data is already an XML string + \header( 'Content-Type: application/xml; charset=UTF-8' ); + echo $data; + } + else { + // For JSON responses, encode with unescaped slashes for cleaner URLs. + $json = \json_encode( + $data, + ( \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE ) + ); + + \header( 'Content-Type: application/json; charset=UTF-8' ); + echo $json; + } + + return true; + } +} From 0281bc61a9fe9ebd71e87d4c5d99aa86859dbc68 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 5 Nov 2025 13:51:04 +0100 Subject: [PATCH 060/319] CS --- ...regate-site-schema-map-command-handler.php | 5 ++++ .../aggregate-site-schema-map-command.php | 9 +++++++ .../schema_map/schema-map-builder.php | 4 +-- .../schema_map/schema-map-xml-renderer.php | 7 +++--- .../schema_map/schema-map-config.php | 17 ++++++------- .../schema-map-indexable-repository.php | 5 ++++ .../site-schema-aggregator-xml-route.php | 5 +--- ...ite-schema-response-header-integration.php | 25 +++++++++++-------- 8 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php index 58f73adb2e3..e75b4934eed 100644 --- a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php +++ b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php @@ -6,6 +6,11 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Schema_Map\Schema_Map_Xml_Renderer; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Indexable_Repository; +/** + * Class that handles the command to aggregate site schema map. + * + * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded + */ class Aggregate_Site_Schema_Map_Command_Handler { /** diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command.php b/src/schema_aggregator/application/aggregate-site-schema-map-command.php index ec37455229e..9cb9d62aa17 100644 --- a/src/schema_aggregator/application/aggregate-site-schema-map-command.php +++ b/src/schema_aggregator/application/aggregate-site-schema-map-command.php @@ -2,6 +2,9 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; +/** + * Class that represents the command to aggregate site schema map. + */ class Aggregate_Site_Schema_Map_Command { /** @@ -18,6 +21,12 @@ class Aggregate_Site_Schema_Map_Command { */ private $schema_map_threshold; + /** + * The constructor. + * + * @param array $post_types The post types to include in the schema map. + * @param int $schema_map_threshold The schema map threshold. + */ public function __construct( array $post_types, int $schema_map_threshold ) { $this->post_types = $post_types; $this->schema_map_threshold = $schema_map_threshold; diff --git a/src/schema_aggregator/application/schema_map/schema-map-builder.php b/src/schema_aggregator/application/schema_map/schema-map-builder.php index b949e4fbb3a..7411836a60a 100644 --- a/src/schema_aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema_aggregator/application/schema_map/schema-map-builder.php @@ -13,7 +13,7 @@ class Schema_Map_Builder { * @param array $indexable_counts The indexable counts per post type. * @param int $threshold The threshold for items per page. * - * @return array> The schema map. + * @return array> The schema map. */ public function get_schema_map( array $indexable_counts, int $threshold ): array { $schema_map = []; @@ -32,7 +32,7 @@ public function get_schema_map( array $indexable_counts, int $threshold ): array } // Get lastmod for this specific page range. - // $lastmod = $this->get_lastmod_for_post_type($post_type, $page, $threshold); + // $lastmod = $this->get_lastmod_for_post_type($post_type, $page, $threshold);. $page_count = ( $page === $total_pages ) ? ( $count - ( ( $page - 1 ) * $threshold ) ) : $threshold; diff --git a/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php b/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php index 2649dcbdc51..c364182244c 100644 --- a/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php +++ b/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php @@ -41,15 +41,14 @@ public function to_xml( array $schema_map ): string { throw new RuntimeException( 'Invalid schemamap data structure: missing or invalid "schemamap" key' ); } - $dom = new DOMDocument( '1.0', 'UTF-8' ); - $dom->formatOutput = true; + $dom = new DOMDocument( '1.0', 'UTF-8' ); $url_set = $dom->createElement( 'urlset' ); $url_set->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' ); $dom->appendChild( $url_set ); - $change_freq = $this->config->getChangefreq(); - $priority = $this->config->getPriority(); + $change_freq = $this->config->get_changefreq(); + $priority = $this->config->get_priority(); foreach ( $schema_map as $entry ) { if ( ! isset( $entry['url'] ) || ! isset( $entry['lastmod'] ) ) { diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php index 37c6599c42f..56922beb1d2 100644 --- a/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php @@ -2,6 +2,9 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map; +/** + * Configuration for the Schema Map. + */ class Schema_Map_Config { /** @@ -9,13 +12,11 @@ class Schema_Map_Config { * * @return string Valid changefreq value (always|hourly|daily|weekly|monthly|yearly|never). */ - public function getChangefreq(): string { - $changefreq = \apply_filters( 'yoast_nlweb_schemamap_changefreq', 'daily' ); + public function get_changefreq(): string { + $changefreq = \apply_filters( 'wpseo_schema_aggregator_schemamap_changefreq', 'daily' ); - // Validate against allowed values $allowed = [ 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never' ]; if ( ! \in_array( $changefreq, $allowed, true ) ) { - \error_log( "Yoast NLWeb SitemapRenderer: Invalid changefreq '{$changefreq}', using default 'daily'" ); return 'daily'; } @@ -27,19 +28,15 @@ public function getChangefreq(): string { * * @return string Priority value as string (float between 0.0 and 1.0). */ - public function getPriority(): string { - $priority = \apply_filters( 'yoast_nlweb_schemamap_priority', '0.8' ); + public function get_priority(): string { + $priority = \apply_filters( 'wpseo_schema_aggregator_schemamap_priority', '0.8' ); - // Convert to float for validation $priority_float = \is_numeric( $priority ) ? (float) $priority : 0.8; - // Validate range if ( $priority_float < 0.0 || $priority_float > 1.0 ) { - \error_log( "Yoast NLWeb SitemapRenderer: Invalid priority '{$priority}', using default '0.8'" ); return '0.8'; } - // Return as string with one decimal place return \number_format( $priority_float, 1, '.', '' ); } } diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index 5162890cb43..8928034cb9f 100644 --- a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -4,6 +4,11 @@ use Yoast\WP\SEO\Repositories\Indexable_Repository; +/** + * Class Schema_Map_Indexable_Repository + * + * Maps indexable repository queries for schema map needs. + */ class Schema_Map_Indexable_Repository { /** diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php index 8a095a20770..0217b8e41c9 100644 --- a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -3,7 +3,6 @@ namespace Yoast\WP\SEO\Schema_Aggregator\User_Interface; use WP_Error; -use WP_REST_Request; use WP_REST_Response; use Yoast\WP\SEO\Helpers\Capability_Helper; use Yoast\WP\SEO\Helpers\Post_Type_Helper; @@ -118,11 +117,9 @@ public function get_permission_callback(): bool { /** * Returns a XML representation of the possible post types that can be used for schema. * - * @param WP_REST_Request $request The request object. - * * @return WP_REST_Response|WP_Error The success or failure response. */ - public function render_schema_xml( WP_REST_Request $request ) { + public function render_schema_xml() { $post_types = $this->post_type_helper->get_indexable_post_types(); diff --git a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php index 4dcb2bd9165..b8cd322fadd 100644 --- a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php +++ b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php @@ -4,14 +4,22 @@ use WP_REST_Request; use WP_REST_Response; -use WP_REST_Server; +use WPSEO_Utils; use Yoast\WP\SEO\Conditionals\No_Conditionals; use Yoast\WP\SEO\Integrations\Integration_Interface; -class Site_Schema_Reponse_Header_Integration implements Integration_Interface { +/** + * Integration to set proper response headers for Site Schema endpoints. + */ +class Site_Schema_Response_Header_Integration implements Integration_Interface { use No_Conditionals; + /** + * Registers the hooks for the integration. + * + * @return void + */ public function register_hooks() { \add_filter( 'rest_pre_serve_request', [ $this, 'serve_custom_response' ], 10, 4 ); } @@ -29,11 +37,10 @@ public function register_hooks() { * @param bool $served Whether the request has already been served. * @param WP_REST_Response $result Result to send to the client. * @param WP_REST_Request $request Request object. - * @param WP_REST_Server $server Server instance. * * @return bool True if we served the request, false otherwise. */ - public function serve_custom_response( $served, $result, $request, $server ): bool { + public function serve_custom_response( $served, $result, $request ): bool { if ( \strpos( $request->get_route(), '/yoast/v1/schema-aggregator' ) !== 0 ) { return $served; } @@ -52,19 +59,15 @@ public function serve_custom_response( $served, $result, $request, $server ): bo $content_type = ( $headers['Content-Type'] ?? 'application/json; charset=UTF-8' ); if ( \strpos( $content_type, 'application/xml' ) !== false ) { - // For XML responses, data is already an XML string \header( 'Content-Type: application/xml; charset=UTF-8' ); - echo $data; + echo $data; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $data should already be escaped here since this just adds headers to the request. } else { // For JSON responses, encode with unescaped slashes for cleaner URLs. - $json = \json_encode( - $data, - ( \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE ) - ); + $json = WPSEO_Utils::format_json_encode( $data ); \header( 'Content-Type: application/json; charset=UTF-8' ); - echo $json; + echo $json; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $json should already be escaped here since this just adds headers to the request. } return true; From 20002f391fd9811ce6588208a50824129300f9db Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 5 Nov 2025 22:25:46 +0100 Subject: [PATCH 061/319] Made class attributes private --- src/schema-aggregator/domain/schema-piece.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schema-aggregator/domain/schema-piece.php b/src/schema-aggregator/domain/schema-piece.php index 2e801a56a85..fb12d96d728 100644 --- a/src/schema-aggregator/domain/schema-piece.php +++ b/src/schema-aggregator/domain/schema-piece.php @@ -13,14 +13,14 @@ class Schema_Piece { * * @var string|array */ - protected $type; + private $type; /** * The data of the schema piece. * * @var array */ - protected $data; + private $data; /** * Class constructor. From 2c656088339f5d682a0b1e2bff47faaa04fb1a42 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 5 Nov 2025 22:26:15 +0100 Subject: [PATCH 062/319] Moved all the methods specific for the aggregator feature to a separate class --- .../infrastructure/aggregator-config.php | 107 ++++++++++++++++++ .../infrastructure/config.php | 96 ---------------- 2 files changed, 107 insertions(+), 96 deletions(-) create mode 100644 src/schema-aggregator/infrastructure/aggregator-config.php diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php new file mode 100644 index 00000000000..3a4a77f4899 --- /dev/null +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -0,0 +1,107 @@ + + */ + private const DEFAULT_POST_TYPES = [ 'post', 'page' ]; + + /** + * Default schema types to include (whitelist) + * + * @var array + */ + private const DEFAULT_SCHEMA_TYPES = [ + 'Recipe', + 'Article', + 'Product', + 'Event', + 'Person', + 'Organization', + 'WebPage', + 'WebSite', + ]; + + private const PROPERTIES_AVOID_LIST = [ 'breadcrumb', 'potentialAction' ]; + + /** + * The WooCommerce Conditional. + * + * @var WooCommerce_Conditional + */ + private $woocommerce_conditional; + + /** + * Aggregator_Config constructor. + * + * @param WooCommerce_Conditional $woocommerce_conditional The WooCommerce Conditional. + */ + public function __construct( WooCommerce_Conditional $woocommerce_conditional ) { + $this->woocommerce_conditional = $woocommerce_conditional; + } + + /** + * Get configured post types + * + * @return array + */ + public function get_allowed_post_types(): array { + $default_post_types = self::DEFAULT_POST_TYPES; + + // Only include 'product' if Yoast WooCommerce SEO extension is active. + + if ( $this->woocommerce_conditional->is_met() ) { + $default_post_types[] = 'product'; + } + + $post_types = \apply_filters( 'wpseo_schema_aggregator_post_types', $default_post_types ); + + // Ensure it's an array. + if ( ! \is_array( $post_types ) ) { + return $default_post_types; + } + + return \array_intersect( $post_types, \YoastSEO()->helpers->post_type->get_indexable_post_types() ); + } + + /** + * Get configured schema types (whitelist) + * + * @return array + */ + public function get_allowed_schema_types(): array { + $schema_types = \apply_filters( 'wpseo_schema_aggregator_schema_types', self::DEFAULT_SCHEMA_TYPES ); + + if ( ! \is_array( $schema_types ) ) { + return self::DEFAULT_SCHEMA_TYPES; + } + + return $schema_types; + } + + /** + * Get list of properties to remove from a schema piece. + * + * @return array + */ + public function get_properties_avoid_list(): array { + $properties_avoid_list = \apply_filters( 'wpseo_schema_aggregator_properties_avoid_list', self::PROPERTIES_AVOID_LIST ); + + if ( ! \is_array( $properties_avoid_list ) ) { + return self::PROPERTIES_AVOID_LIST; + } + + return $properties_avoid_list; + } +} diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 7df73433bc7..bcba5bf7408 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -2,8 +2,6 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure; -use WPSEO_Addon_Manager; - /** * Configuration for the Schema Aggregator. */ @@ -23,34 +21,6 @@ class Config { */ private const MAX_PER_PAGE = 100; - /** - * Default post types to include in schema aggregation - * - * Note: 'product' is only included if Yoast WooCommerce SEO extension is active - * because without it, WooCommerce products don't generate Product schema in Yoast's graph - * - * @var array - */ - private const DEFAULT_POST_TYPES = [ 'post', 'page' ]; - - /** - * Default schema types to include (whitelist) - * - * @var array - */ - private const DEFAULT_SCHEMA_TYPES = [ - 'Recipe', - 'Article', - 'Product', - 'Event', - 'Person', - 'Organization', - 'WebPage', - 'WebSite', - ]; - - private const PROPERTIES_AVOID_LIST = [ 'breadcrumb', 'potentialAction' ]; - /** * Get default items per page * @@ -68,70 +38,4 @@ public function get_per_page(): int { public function get_max_per_page(): int { return self::MAX_PER_PAGE; } - - /** - * Get configured post types - * - * @return array - */ - public function get_allowed_post_types(): array { - $default_post_types = self::DEFAULT_POST_TYPES; - - // Only include 'product' if Yoast WooCommerce SEO extension is active. - - if ( $this->is_yoast_woocommerce_active() ) { - $default_post_types[] = 'product'; - } - - $post_types = \apply_filters( 'wpseo_schema_aggregator_post_types', $default_post_types ); - - // Ensure it's an array. - if ( ! \is_array( $post_types ) ) { - return $default_post_types; - } - - return $post_types; - } - - /** - * Get configured schema types (whitelist) - * - * @return array - */ - public function get_allowed_schema_types(): array { - $schema_types = \apply_filters( 'wpseo_schema_aggregator_schema_types', self::DEFAULT_SCHEMA_TYPES ); - - if ( ! \is_array( $schema_types ) ) { - return self::DEFAULT_SCHEMA_TYPES; - } - - return $schema_types; - } - - /** - * Get list of properties to remove from a schema piece. - * - * @return array - */ - public function get_properties_avoid_list(): array { - $properties_avoid_list = \apply_filters( 'wpseo_schema_aggregator_properties_avoid_list', self::PROPERTIES_AVOID_LIST ); - - if ( ! \is_array( $properties_avoid_list ) ) { - return self::PROPERTIES_AVOID_LIST; - } - - return $properties_avoid_list; - } - - /** - * Check if Yoast WooCommerce SEO extension is active - * - * @return bool - */ - private function is_yoast_woocommerce_active(): bool { - $addon_manager = new WPSEO_Addon_Manager(); - $plugin_file = $addon_manager->get_plugin_file( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ); - - return $plugin_file && \is_plugin_active( $plugin_file ); - } } From 966f4283f28ede2199ff90925287cc2fc3bc5966 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 5 Nov 2025 22:27:00 +0100 Subject: [PATCH 063/319] Use the new Aggregator_Config class --- .../application/properties-filter.php | 8 ++++---- .../application/schema-pieces-aggregator.php | 12 +----------- .../application/schema-pieces-filter.php | 7 ++++--- .../infrastructure/schema-piece-repository.php | 6 +++--- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/schema-aggregator/application/properties-filter.php b/src/schema-aggregator/application/properties-filter.php index 6e5c4edb708..6b6e58a342f 100644 --- a/src/schema-aggregator/application/properties-filter.php +++ b/src/schema-aggregator/application/properties-filter.php @@ -4,7 +4,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config; /** * Properties filter @@ -16,16 +16,16 @@ class Properties_Filter { /** * Configuration provider * - * @var Config + * @var Aggregator_Config */ private $config; /** * Constructor * - * @param Config $config Configuration provider. + * @param Aggregator_Config $config Configuration provider. */ - public function __construct( Config $config ) { + public function __construct( Aggregator_Config $config ) { $this->config = $config; } diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 0dc4af24762..141d51ceec7 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -4,7 +4,6 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; /** * This class is responsible for taking an array of Schema_Pieces and return another array of Schema_Pieces where: @@ -16,13 +15,6 @@ */ class Schema_Pieces_Aggregator { - /** - * The configuration instance. - * - * @var Config - */ - private $config; - /** * The properties filter instance. * @@ -47,13 +39,11 @@ class Schema_Pieces_Aggregator { /** * Class constructor * - * @param Config $config The configuration object. * @param Properties_Filter $properties_filter The properties filter object. * @param Schema_Pieces_Filter $schema_pieces_filter The schema pieces filter object. * @param Properties_Merger $properties_merger The properties merger object. */ - public function __construct( Config $config, Properties_Filter $properties_filter, Schema_Pieces_Filter $schema_pieces_filter, Properties_Merger $properties_merger ) { - $this->config = $config; + public function __construct( Properties_Filter $properties_filter, Schema_Pieces_Filter $schema_pieces_filter, Properties_Merger $properties_merger ) { $this->properties_filter = $properties_filter; $this->schema_pieces_filter = $schema_pieces_filter; $this->properties_merger = $properties_merger; diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php index 6ad03fa6a2c..27878ee8c88 100644 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -5,6 +5,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config; /** * Schema filter @@ -16,16 +17,16 @@ class Schema_Pieces_Filter { /** * Configuration provider * - * @var Config + * @var Aggregator_Config */ private $config; /** * Constructor * - * @param Config $config Configuration provider. + * @param Aggregator_Config $config Configuration provider. */ - public function __construct( Config $config ) { + public function __construct( Aggregator_Config $config ) { $this->config = $config; } diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 367748b0342..36ba413aead 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -45,7 +45,7 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { /** * Configuration provider. * - * @var Config + * @var Aggregator_Config */ private $config; @@ -56,14 +56,14 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. * @param Meta_Tags_Context_Memoizer_Adapter $adapter The adapter factory. - * @param Config $config The configuration provider. + * @param Aggregator_Config $config The configuration provider. */ public function __construct( Meta_Tags_Context_Memoizer $memoizer, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository, Meta_Tags_Context_Memoizer_Adapter $adapter, - Config $config + Aggregator_Config $config ) { $this->memoizer = $memoizer; $this->indexable_helper = $indexable_helper; From b6ec352356157898a1af4095292377e71814d030 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 5 Nov 2025 22:27:42 +0100 Subject: [PATCH 064/319] Remove unused import --- src/schema-aggregator/application/schema-pieces-filter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php index 27878ee8c88..cb379aadc43 100644 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -4,7 +4,6 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config; /** From aef1bdcc2a3eb8adc46581d6179a05228fa74640 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 5 Nov 2025 22:28:07 +0100 Subject: [PATCH 065/319] Cast type to string --- src/schema-aggregator/application/schema-pieces-filter.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php index cb379aadc43..c742b8c1e95 100644 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ b/src/schema-aggregator/application/schema-pieces-filter.php @@ -66,12 +66,7 @@ public function has_allowed_type( Schema_Piece $piece ): bool { if ( \is_array( $type ) ) { foreach ( $type as $single_type ) { - // Validate each type is a string. - if ( ! \is_string( $single_type ) ) { - continue; - } - - if ( $this->is_allowed_type( $single_type ) ) { + if ( $this->is_allowed_type( (string) $single_type ) ) { return true; } } From d947f2059d183c5ce334610f73e98c23dc4a7f74 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 6 Nov 2025 10:43:31 +0100 Subject: [PATCH 066/319] Implement last mod. --- .../schema_map/schema-map-builder.php | 23 ++++++++++-- .../schema-map-indexable-repository.php | 35 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/schema_aggregator/application/schema_map/schema-map-builder.php b/src/schema_aggregator/application/schema_map/schema-map-builder.php index 7411836a60a..968b3119b0c 100644 --- a/src/schema_aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema_aggregator/application/schema_map/schema-map-builder.php @@ -2,11 +2,29 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application\Schema_Map; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Indexable_Repository; + /** * Builds the schema map. */ class Schema_Map_Builder { + /** + * The indexable repository. + * + * @var Schema_Map_Indexable_Repository + */ + private $indexable_repository; + + /** + * Schema_Map_Builder constructor. + * + * @param Schema_Map_Indexable_Repository $indexable_repository The indexable repository. + */ + public function __construct( Schema_Map_Indexable_Repository $indexable_repository ) { + $this->indexable_repository = $indexable_repository; + } + /** * Builds the schema map based on indexable counts and threshold. * @@ -31,15 +49,14 @@ public function get_schema_map( array $indexable_counts, int $threshold ): array $url = \rest_url( 'schema-aggregator/get-schema/' . $post_type . '/' . $page ); } - // Get lastmod for this specific page range. - // $lastmod = $this->get_lastmod_for_post_type($post_type, $page, $threshold);. + $lastmod = $this->indexable_repository->get_lastmod_for_post_type( $post_type, $page, $threshold ); $page_count = ( $page === $total_pages ) ? ( $count - ( ( $page - 1 ) * $threshold ) ) : $threshold; $schema_map[] = [ 'post_type' => $post_type, 'url' => $url, - 'lastmod' => '', + 'lastmod' => $lastmod, 'count' => $page_count, ]; } diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index 8928034cb9f..afa873ad611 100644 --- a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -2,6 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map; +use Exception; use Yoast\WP\SEO\Repositories\Indexable_Repository; /** @@ -52,4 +53,38 @@ public function get_indexable_count_per_post_type( array $post_types ): array { return $post_type_counts; } + + /** + * Get lastmod timestamp for a post type and page range + * + * Returns the latest post_modified_gmt timestamp for posts in the given range. + * Used for schemamap index to enable selective updates. + * + * @param string $post_type Post type slug. + * @param int $page Page number (1-indexed). + * @param int $per_page Items per page. + * @return string ISO 8601 timestamp (e.g., "2025-10-21T14:23:17Z"). + */ + public function get_lastmod_for_post_type( string $post_type, int $page, int $per_page ): string { + $fallback = \gmdate( 'Y-m-d\TH:i:s\Z' ); + + try { + $offset = ( ( $page - 1 ) * $per_page ); + $lastmod = $this->indexable_repository->query() + ->select_expr( 'MAX(object_last_modified)' ) + ->where( 'object_sub_type', $post_type ) + ->where_raw( '( is_public IS NULL OR is_public = 1 )' ) + ->order_by_asc( 'id' )->limit( $per_page )->offset( $offset ) + ->find_one(); + + // Convert to ISO 8601 format or use current time if no posts. + if ( $lastmod && ! empty( $lastmod ) ) { + return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod ) ); + } + + return $fallback; + } catch ( Exception $e ) { + return $fallback; + } + } } From 0053df1176404c9ce3e0ccce774b674cda52d2db Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 6 Nov 2025 10:57:11 +0100 Subject: [PATCH 067/319] Reset threshold. --- src/schema_aggregator/infrastructure/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema_aggregator/infrastructure/config.php b/src/schema_aggregator/infrastructure/config.php index becf00f9cc2..b567c92e65e 100644 --- a/src/schema_aggregator/infrastructure/config.php +++ b/src/schema_aggregator/infrastructure/config.php @@ -26,7 +26,7 @@ class Config { * * @var int */ - private const DEFAULT_SCHEMA_MAP_THRESHOLD = 10; + private const DEFAULT_SCHEMA_MAP_THRESHOLD = 1000; /** * Get default items per page From 6daa95c53cf44e82137c9749b84fd811aa35e4b4 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 6 Nov 2025 12:45:18 +0100 Subject: [PATCH 068/319] Rename top level. --- .../application/aggregate-site-schema-command-handler.php | 0 .../application/aggregate-site-schema-command.php | 0 .../application/enhancement/abstract-schema-enhancer.php | 0 .../application/enhancement/article-schema-enhancer.php | 0 .../application/enhancement/person-schema-enhancer.php | 0 .../application/enhancement/schema-enhancement-factory.php | 0 .../domain/enhancement/enhancement-config-interface.php | 0 .../domain/enhancement/schema-enhancement-interface.php | 0 .../domain/page-controls.php | 0 .../domain/schema-piece-repository-interface.php | 0 .../domain/schema-piece.php | 0 .../infrastructure/config.php | 0 .../infrastructure/enhancement/article-config.php | 0 .../infrastructure/enhancement/person-config.php | 0 .../infrastructure/meta-tags-context-memoizer-adapter.php | 0 .../infrastructure/schema-piece-repository.php | 0 .../infrastructure/site-schema-json-conditional.php | 0 .../user-interface/site-schema-aggregator-cli-command.php | 0 .../user-interface/site-schema-aggregator-route.php | 0 19 files changed, 0 insertions(+), 0 deletions(-) rename src/{schema_aggregator => schema-aggregator}/application/aggregate-site-schema-command-handler.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/aggregate-site-schema-command.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/enhancement/abstract-schema-enhancer.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/enhancement/article-schema-enhancer.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/enhancement/person-schema-enhancer.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/enhancement/schema-enhancement-factory.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/enhancement/enhancement-config-interface.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/enhancement/schema-enhancement-interface.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/page-controls.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/schema-piece-repository-interface.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/schema-piece.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/config.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/enhancement/article-config.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/enhancement/person-config.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/meta-tags-context-memoizer-adapter.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/schema-piece-repository.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/site-schema-json-conditional.php (100%) rename src/{schema_aggregator => schema-aggregator}/user-interface/site-schema-aggregator-cli-command.php (100%) rename src/{schema_aggregator => schema-aggregator}/user-interface/site-schema-aggregator-route.php (100%) diff --git a/src/schema_aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php similarity index 100% rename from src/schema_aggregator/application/aggregate-site-schema-command-handler.php rename to src/schema-aggregator/application/aggregate-site-schema-command-handler.php diff --git a/src/schema_aggregator/application/aggregate-site-schema-command.php b/src/schema-aggregator/application/aggregate-site-schema-command.php similarity index 100% rename from src/schema_aggregator/application/aggregate-site-schema-command.php rename to src/schema-aggregator/application/aggregate-site-schema-command.php diff --git a/src/schema_aggregator/application/enhancement/abstract-schema-enhancer.php b/src/schema-aggregator/application/enhancement/abstract-schema-enhancer.php similarity index 100% rename from src/schema_aggregator/application/enhancement/abstract-schema-enhancer.php rename to src/schema-aggregator/application/enhancement/abstract-schema-enhancer.php diff --git a/src/schema_aggregator/application/enhancement/article-schema-enhancer.php b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php similarity index 100% rename from src/schema_aggregator/application/enhancement/article-schema-enhancer.php rename to src/schema-aggregator/application/enhancement/article-schema-enhancer.php diff --git a/src/schema_aggregator/application/enhancement/person-schema-enhancer.php b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php similarity index 100% rename from src/schema_aggregator/application/enhancement/person-schema-enhancer.php rename to src/schema-aggregator/application/enhancement/person-schema-enhancer.php diff --git a/src/schema_aggregator/application/enhancement/schema-enhancement-factory.php b/src/schema-aggregator/application/enhancement/schema-enhancement-factory.php similarity index 100% rename from src/schema_aggregator/application/enhancement/schema-enhancement-factory.php rename to src/schema-aggregator/application/enhancement/schema-enhancement-factory.php diff --git a/src/schema_aggregator/domain/enhancement/enhancement-config-interface.php b/src/schema-aggregator/domain/enhancement/enhancement-config-interface.php similarity index 100% rename from src/schema_aggregator/domain/enhancement/enhancement-config-interface.php rename to src/schema-aggregator/domain/enhancement/enhancement-config-interface.php diff --git a/src/schema_aggregator/domain/enhancement/schema-enhancement-interface.php b/src/schema-aggregator/domain/enhancement/schema-enhancement-interface.php similarity index 100% rename from src/schema_aggregator/domain/enhancement/schema-enhancement-interface.php rename to src/schema-aggregator/domain/enhancement/schema-enhancement-interface.php diff --git a/src/schema_aggregator/domain/page-controls.php b/src/schema-aggregator/domain/page-controls.php similarity index 100% rename from src/schema_aggregator/domain/page-controls.php rename to src/schema-aggregator/domain/page-controls.php diff --git a/src/schema_aggregator/domain/schema-piece-repository-interface.php b/src/schema-aggregator/domain/schema-piece-repository-interface.php similarity index 100% rename from src/schema_aggregator/domain/schema-piece-repository-interface.php rename to src/schema-aggregator/domain/schema-piece-repository-interface.php diff --git a/src/schema_aggregator/domain/schema-piece.php b/src/schema-aggregator/domain/schema-piece.php similarity index 100% rename from src/schema_aggregator/domain/schema-piece.php rename to src/schema-aggregator/domain/schema-piece.php diff --git a/src/schema_aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php similarity index 100% rename from src/schema_aggregator/infrastructure/config.php rename to src/schema-aggregator/infrastructure/config.php diff --git a/src/schema_aggregator/infrastructure/enhancement/article-config.php b/src/schema-aggregator/infrastructure/enhancement/article-config.php similarity index 100% rename from src/schema_aggregator/infrastructure/enhancement/article-config.php rename to src/schema-aggregator/infrastructure/enhancement/article-config.php diff --git a/src/schema_aggregator/infrastructure/enhancement/person-config.php b/src/schema-aggregator/infrastructure/enhancement/person-config.php similarity index 100% rename from src/schema_aggregator/infrastructure/enhancement/person-config.php rename to src/schema-aggregator/infrastructure/enhancement/person-config.php diff --git a/src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php b/src/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php similarity index 100% rename from src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php rename to src/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php diff --git a/src/schema_aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php similarity index 100% rename from src/schema_aggregator/infrastructure/schema-piece-repository.php rename to src/schema-aggregator/infrastructure/schema-piece-repository.php diff --git a/src/schema_aggregator/infrastructure/site-schema-json-conditional.php b/src/schema-aggregator/infrastructure/site-schema-json-conditional.php similarity index 100% rename from src/schema_aggregator/infrastructure/site-schema-json-conditional.php rename to src/schema-aggregator/infrastructure/site-schema-json-conditional.php diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php similarity index 100% rename from src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php rename to src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php similarity index 100% rename from src/schema_aggregator/user-interface/site-schema-aggregator-route.php rename to src/schema-aggregator/user-interface/site-schema-aggregator-route.php From d3155e66e837425d60b510c7fe4fa0cf22203214 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 10 Nov 2025 09:29:43 +0100 Subject: [PATCH 069/319] cs fix. --- .../infrastructure/schema-piece-repository.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 6a0af56198a..329041d1ad3 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -105,14 +105,14 @@ public function get( int $page, int $page_size ): array { $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); $context = $this->memoizer->get( $indexable, $page_type ); $context_array = $this->adapter->meta_tags_context_to_array( $context ); - $pieces_data = $context_array['@graph']; + $pieces_data = $context_array['@graph']; foreach ( $pieces_data as $piece_data ) { $schema_piece = new Schema_Piece( $piece_data, $piece_data['@type'] ); - $enhancer = $this->enhancement_factory->get_enhancer( $this->get_all_schema_types( $context_array['@graph'] ) ); + $enhancer = $this->enhancement_factory->get_enhancer( $this->get_all_schema_types( $context_array['@graph'] ) ); if ( $enhancer !== null ) { $schema_piece = $enhancer->enhance( $schema_piece, $indexable ); } - $schema_pieces[] = $schema_piece + $schema_pieces[] = $schema_piece; } } From 60099593ce59f6e2dc70c635ec075e9d8950ff59 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 10 Nov 2025 11:03:58 +0100 Subject: [PATCH 070/319] Some small merge improvements. --- .../enhancement/article-schema-enhancer.php | 2 +- .../infrastructure/aggregator-config.php | 14 ++++++++++++-- .../infrastructure/schema-piece-repository.php | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php index 47184375b53..ebece01559d 100644 --- a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php @@ -44,7 +44,7 @@ public function set_article_config( Article_Config $config ) { public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Schema_Piece { $data = $schema_piece->get_data(); - foreach ( $data['@graph'] as $key => $schema_data ) { + foreach ( $data as $key => $schema_data ) { if ( ! isset( $schema_data['@type'] ) ) { continue; } diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index 3a4a77f4899..9c6be78f979 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -3,6 +3,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure; use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional; +use Yoast\WP\SEO\Helpers\Post_Type_Helper; /** * Configuration for the Schema Aggregator. */ @@ -42,13 +43,22 @@ class Aggregator_Config { */ private $woocommerce_conditional; + /** + * The Post Type Helper. + * + * @var Post_Type_Helper + */ + private $post_type_helper; + /** * Aggregator_Config constructor. * * @param WooCommerce_Conditional $woocommerce_conditional The WooCommerce Conditional. + * @param Post_Type_Helper $post_type_helper The Post Type Helper. */ - public function __construct( WooCommerce_Conditional $woocommerce_conditional ) { + public function __construct( WooCommerce_Conditional $woocommerce_conditional, Post_Type_Helper $post_type_helper ) { $this->woocommerce_conditional = $woocommerce_conditional; + $this->post_type_helper = $post_type_helper; } /** @@ -72,7 +82,7 @@ public function get_allowed_post_types(): array { return $default_post_types; } - return \array_intersect( $post_types, \YoastSEO()->helpers->post_type->get_indexable_post_types() ); + return \array_intersect( $post_types, $this->post_type_helper->get_indexable_post_types() ); } /** diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 329041d1ad3..e5a442133cd 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -126,7 +126,7 @@ public function get( int $page, int $page_size ): array { * * @return array */ - public function get_all_schema_types( $graph ): array { + private function get_all_schema_types( $graph ): array { $schema_types = []; foreach ( $graph as $schema_values ) { foreach ( $schema_values as $key => $value ) { From e3100305834cb5ad329cb01d9fdbc215e30c5d03 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 10 Nov 2025 14:15:44 +0100 Subject: [PATCH 071/319] Make the repo post-type based. --- src/repositories/indexable-repository.php | 17 ++++---- .../aggregate-site-schema-command-handler.php | 3 +- .../aggregate-site-schema-command.php | 9 ++-- .../domain/page-controls.php | 24 +++++++++-- .../schema-piece-repository-interface.php | 7 ++-- .../schema-piece-repository.php | 8 ++-- .../site-schema-aggregator-route.php | 42 +++++++++++-------- 7 files changed, 71 insertions(+), 39 deletions(-) diff --git a/src/repositories/indexable-repository.php b/src/repositories/indexable-repository.php index f2575acb94b..f3c0eb6d554 100644 --- a/src/repositories/indexable-repository.php +++ b/src/repositories/indexable-repository.php @@ -107,7 +107,8 @@ public function query() { * This may be the result of the indexable not existing or of being unable to determine what type of page the * current page is. * - * @return bool|Indexable The indexable. If no indexable is found returns an empty indexable. Returns false if there is a database error. + * @return bool|Indexable The indexable. If no indexable is found returns an empty indexable. Returns false if + * there is a database error. */ public function for_current_page() { $indexable = false; @@ -219,20 +220,20 @@ public function find_all_with_type_and_sub_type( $object_type, $object_sub_type /** * Retrieves a paginated set of indexable instances of public indexables. * - * @param int $page The page number (1-based). - * @param int $page_size The number of items per page. - * @param array $post_type_exclude_list Post types to ignore (can be empty). + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * @param string $post_type The post type indexables to find. * * @return Indexable[] The array with the paginated indexable instances which are public. */ - public function find_all_public_paginated( $page, $page_size, $post_type_exclude_list = [] ): array { + public function find_all_public_paginated( int $page, int $page_size, string $post_type ): array { $offset = ( ( $page - 1 ) * $page_size ); $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 )' ); - if ( $post_type_exclude_list ) { - $query->where_not_in( 'object_sub_type', $post_type_exclude_list ); - } + $query->where( 'object_sub_type', $post_type ); + $indexables = $query->order_by_asc( 'id' )->limit( $page_size )->offset( $offset )->find_many(); + return \array_map( [ $this, 'upgrade_indexable' ], $indexables ); } diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index d02971654be..439bc5fdbc0 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -46,7 +46,8 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { $schema_pieces = $this->schema_piece_repository->get( $command->get_page_controls()->get_page(), - $command->get_page_controls()->get_page_size() + $command->get_page_controls()->get_page_size(), + $command->get_page_controls()->get_post_type() ); $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); diff --git a/src/schema-aggregator/application/aggregate-site-schema-command.php b/src/schema-aggregator/application/aggregate-site-schema-command.php index 7353b7ad84c..1e08d532ac9 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command.php @@ -20,11 +20,12 @@ class Aggregate_Site_Schema_Command { /** * The constructor. * - * @param int $page The current page. - * @param int $per_page The number of items per page. + * @param int $page The current page. + * @param int $per_page The number of items per page. + * @param string $post_type The post type to aggregate schema for. */ - public function __construct( int $page, int $per_page ) { - $this->page_controls = new Page_Controls( $page, $per_page ); + public function __construct( int $page, int $per_page, string $post_type ) { + $this->page_controls = new Page_Controls( $page, $per_page, $post_type ); } /** diff --git a/src/schema-aggregator/domain/page-controls.php b/src/schema-aggregator/domain/page-controls.php index 3923390f306..a29a69ca8dc 100644 --- a/src/schema-aggregator/domain/page-controls.php +++ b/src/schema-aggregator/domain/page-controls.php @@ -21,15 +21,24 @@ class Page_Controls { */ private $page_size; + /** + * The post type. + * + * @var string + */ + private $post_type; + /** * The constructor. * - * @param int $page The current page. - * @param int $page_size The page size. + * @param int $page The current page. + * @param int $page_size The page size. + * @param string $post_type The post type. */ - public function __construct( int $page, int $page_size ) { + public function __construct( int $page, int $page_size, string $post_type ) { $this->page = $page; $this->page_size = $page_size; + $this->post_type = $post_type; } /** @@ -49,4 +58,13 @@ public function get_page(): int { public function get_page_size(): int { return $this->page_size; } + + /** + * Gets the post type. + * + * @return string + */ + public function get_post_type(): string { + return $this->post_type; + } } diff --git a/src/schema-aggregator/domain/schema-piece-repository-interface.php b/src/schema-aggregator/domain/schema-piece-repository-interface.php index 72d5b3ac49b..1a73a58ef53 100644 --- a/src/schema-aggregator/domain/schema-piece-repository-interface.php +++ b/src/schema-aggregator/domain/schema-piece-repository-interface.php @@ -11,10 +11,11 @@ interface Schema_Piece_Repository_Interface { /** * Gets schema pieces by indexable IDs. * - * @param int $page The page number. - * @param int $page_size The number of items per page. + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. * * @return array The schema pieces. */ - public function get( int $page, int $page_size ): array; + public function get( int $page, int $page_size, string $post_type ): array; } diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index e5a442133cd..0ee2e9dbccb 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -86,15 +86,17 @@ public function __construct( /** * Gets the indexables to be aggregated. * - * @param int $page The page number (1-based). - * @param int $page_size The number of items per page. + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. * * @return array The aggregated schema. */ - public function get( int $page, int $page_size ): array { + public function get( int $page, int $page_size, string $post_type ): array { $public_indexables = $this->indexable_repository->find_all_public_paginated( $page, $page_size, + $post_type ); $schema_pieces = []; diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 581f7a50e46..ca2d52caf20 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -70,7 +70,11 @@ public static function get_conditionals() { * @param Capability_Helper $capability_helper The capability helper. * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler. */ - public function __construct( Config $config, Capability_Helper $capability_helper, Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler ) { + public function __construct( + Config $config, + Capability_Helper $capability_helper, + Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler + ) { $this->config = $config; $this->capability_helper = $capability_helper; $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; @@ -82,29 +86,32 @@ public function __construct( Config $config, Capability_Helper $capability_helpe * @return void */ public function register_routes() { - $schema_aggregator_route = [ + $base_route_config = [ 'methods' => 'GET', 'callback' => [ $this, 'aggregate_site_schema' ], 'permission_callback' => [ $this, 'get_permission_callback' ], 'args' => [ - 'page' => [ - 'default' => 1, + 'post_type' => [ + 'required' => true, 'validate_callback' => static function ( $param ) { - return \is_numeric( $param ) && $param > 0; + return \is_string( $param ) && \preg_match( '/^[a-z0-9_-]+$/', $param ); }, - 'sanitize_callback' => 'absint', - ], - 'per_page' => [ - 'default' => $this->config->get_per_page(), - 'validate_callback' => function ( $param ) { - return \is_numeric( $param ) && $param > 0 && $param <= $this->config->get_max_per_page(); - }, - 'sanitize_callback' => 'absint', + 'sanitize_callback' => 'sanitize_key', ], ], ]; - \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE, $schema_aggregator_route ); + $schema_aggregator_route_page = $base_route_config; + $schema_aggregator_route_page['args']['page'] = [ + 'default' => 1, + 'validate_callback' => static function ( $param ) { + return \is_numeric( $param ) && $param > 0; + }, + 'sanitize_callback' => 'absint', + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE . '/(?P[a-z0-9_-]+)', $base_route_config ); + \register_rest_route( Main::API_V1_NAMESPACE, self::GET_SCHEMA_ROUTE . '/(?P[a-z0-9_-]+)/(?P\d+)', $schema_aggregator_route_page ); } /** @@ -124,11 +131,12 @@ public function get_permission_callback(): bool { * @return WP_REST_Response|WP_Error The success or failure response. */ public function aggregate_site_schema( WP_REST_Request $request ) { - $page = $request->get_param( 'page' ); - $per_page = $request->get_param( 'per_page' ); + $post_type = $request->get_param( 'post_type' ); + $page = ( $request->get_param( 'page' ) ?? 1 ); + $per_page = $this->config->get_per_page(); try { - $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); + $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); } catch ( Exception $exception ) { return new WP_Error( 'wpseo_aggregate_site_schema_error', From 718808fa6835ee1c55ba4da7098495be6f7c7c7a Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 11 Nov 2025 09:00:25 +0100 Subject: [PATCH 072/319] Update config. --- .../infrastructure/config.php | 22 +++++-------------- .../site-schema-aggregator-xml-route.php | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/schema_aggregator/infrastructure/config.php b/src/schema_aggregator/infrastructure/config.php index b567c92e65e..4ccfc5e7218 100644 --- a/src/schema_aggregator/infrastructure/config.php +++ b/src/schema_aggregator/infrastructure/config.php @@ -21,29 +21,19 @@ class Config { */ private const MAX_PER_PAGE = 100; - /** - * Maximum items per page - * - * @var int - */ - private const DEFAULT_SCHEMA_MAP_THRESHOLD = 1000; - /** * Get default items per page * * @return int */ public function get_per_page(): int { - return (int) \apply_filters( 'wpseo_schema_aggregator_aggregator_per_page', self::DEFAULT_PER_PAGE ); - } + $per_page = (int) \apply_filters( 'wpseo_schema_aggregator_aggregator_per_page', self::DEFAULT_PER_PAGE ); - /** - * Get default items per page - * - * @return int - */ - public function get_schema_map_threshold(): int { - return (int) \apply_filters( 'wpseo_schema_aggregator_schema_map_threshold', self::DEFAULT_SCHEMA_MAP_THRESHOLD ); + if($per_page > self::MAX_PER_PAGE) { + $per_page = self::MAX_PER_PAGE; + } + + return $per_page; } /** diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php index 0217b8e41c9..04c515fed4f 100644 --- a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -123,7 +123,7 @@ public function render_schema_xml() { $post_types = $this->post_type_helper->get_indexable_post_types(); - $command = new Aggregate_Site_Schema_Map_Command( $post_types, $this->config->get_schema_map_threshold() ); + $command = new Aggregate_Site_Schema_Map_Command( $post_types, $this->config->get_per_page() ); $xml = $this->aggregate_site_schema_map_command_handler->handle( $command ); $response = new WP_REST_Response( $xml, 200 ); From 5c30fc01a7940a0207b31d14dccb1b69ae92d0e5 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 11 Nov 2025 10:59:24 +0100 Subject: [PATCH 073/319] Render headers in its own class. --- .../schema_map/schema-map-header-adapter.php | 41 +++++++++++++++++++ ...ite-schema-response-header-integration.php | 38 ++++++++--------- 2 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 src/schema_aggregator/infrastructure/schema_map/schema-map-header-adapter.php diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-header-adapter.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-header-adapter.php new file mode 100644 index 00000000000..a2fa6de0d64 --- /dev/null +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-header-adapter.php @@ -0,0 +1,41 @@ +get_data(); + + foreach ( $response->get_headers() as $key => $value ) { + \header( \sprintf( '%s: %s', $key, $value ) ); + } + + $headers = $response->get_headers(); + $content_type = ( $headers['Content-Type'] ?? 'application/json; charset=UTF-8' ); + + if ( \strpos( $content_type, 'application/xml' ) !== false ) { + \header( 'Content-Type: application/xml; charset=UTF-8' ); + echo $data; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $data should already be escaped here since this just adds headers to the request. + } + else { + // For JSON responses, encode with unescaped slashes for cleaner URLs. + $json = WPSEO_Utils::format_json_encode( $data ); + + \header( 'Content-Type: application/json; charset=UTF-8' ); + echo $json; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $json should already be escaped here since this just adds headers to the request. + } + } +} diff --git a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php index b8cd322fadd..eb616a96803 100644 --- a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php +++ b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php @@ -4,7 +4,6 @@ use WP_REST_Request; use WP_REST_Response; -use WPSEO_Utils; use Yoast\WP\SEO\Conditionals\No_Conditionals; use Yoast\WP\SEO\Integrations\Integration_Interface; @@ -15,6 +14,22 @@ class Site_Schema_Response_Header_Integration implements Integration_Interface { use No_Conditionals; + /** + * The schema map header adapter. + * + * @var mixed + */ + private $schema_map_header_adapter; + + /** + * Constructor. + * + * @param mixed $schema_map_header_adapter The schema map header adapter. + */ + public function __construct( $schema_map_header_adapter ) { + $this->schema_map_header_adapter = $schema_map_header_adapter; + } + /** * Registers the hooks for the integration. * @@ -49,26 +64,7 @@ public function serve_custom_response( $served, $result, $request ): bool { return $served; } - $data = $result->get_data(); - - foreach ( $result->get_headers() as $key => $value ) { - \header( \sprintf( '%s: %s', $key, $value ) ); - } - - $headers = $result->get_headers(); - $content_type = ( $headers['Content-Type'] ?? 'application/json; charset=UTF-8' ); - - if ( \strpos( $content_type, 'application/xml' ) !== false ) { - \header( 'Content-Type: application/xml; charset=UTF-8' ); - echo $data; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $data should already be escaped here since this just adds headers to the request. - } - else { - // For JSON responses, encode with unescaped slashes for cleaner URLs. - $json = WPSEO_Utils::format_json_encode( $data ); - - \header( 'Content-Type: application/json; charset=UTF-8' ); - echo $json; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $json should already be escaped here since this just adds headers to the request. - } + $this->schema_map_header_adapter->set_header_for_request( $result ); return true; } From a50719a7ee0af30aba40c82d9411f9514e087cf3 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 11 Nov 2025 10:59:40 +0100 Subject: [PATCH 074/319] Abstract to class const for constant values --- .../infrastructure/schema_map/schema-map-config.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php index 56922beb1d2..41f1e033215 100644 --- a/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php @@ -7,6 +7,16 @@ */ class Schema_Map_Config { + private const ALLOWED_FREQUENCIES = [ + 'always', + 'hourly', + 'daily', + 'weekly', + 'monthly', + 'yearly', + 'never', + ]; + /** * Get changefreq value from configuration * @@ -15,8 +25,7 @@ class Schema_Map_Config { public function get_changefreq(): string { $changefreq = \apply_filters( 'wpseo_schema_aggregator_schemamap_changefreq', 'daily' ); - $allowed = [ 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never' ]; - if ( ! \in_array( $changefreq, $allowed, true ) ) { + if ( ! \in_array( $changefreq, self::ALLOWED_FREQUENCIES, true ) ) { return 'daily'; } From 21c8efa20c29c7e4764dc2fa65ba558c5dc71ff9 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 11 Nov 2025 11:00:08 +0100 Subject: [PATCH 075/319] Update naming. --- .../application/aggregate-site-schema-map-command-handler.php | 4 ++-- .../application/schema_map/schema-map-builder.php | 2 +- .../application/schema_map/schema-map-xml-renderer.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php index e75b4934eed..34462f39496 100644 --- a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php +++ b/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php @@ -60,8 +60,8 @@ public function handle( Aggregate_Site_Schema_Map_Command $command ): string { $threshold = $command->get_schema_map_threshold(); - $schema_map = $this->schema_map_builder->get_schema_map( $indexable_counts, $threshold ); + $schema_map = $this->schema_map_builder->build( $indexable_counts, $threshold ); - return $this->schema_map_xml_renderer->to_xml( $schema_map ); + return $this->schema_map_xml_renderer->render( $schema_map ); } } diff --git a/src/schema_aggregator/application/schema_map/schema-map-builder.php b/src/schema_aggregator/application/schema_map/schema-map-builder.php index 968b3119b0c..c26a5caa490 100644 --- a/src/schema_aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema_aggregator/application/schema_map/schema-map-builder.php @@ -33,7 +33,7 @@ public function __construct( Schema_Map_Indexable_Repository $indexable_reposito * * @return array> The schema map. */ - public function get_schema_map( array $indexable_counts, int $threshold ): array { + public function build( array $indexable_counts, int $threshold ): array { $schema_map = []; foreach ( $indexable_counts as $post_type => $count ) { $total_pages = (int) \ceil( $count / $threshold ); diff --git a/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php b/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php index c364182244c..e2175ada2fc 100644 --- a/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php +++ b/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php @@ -36,7 +36,7 @@ public function __construct( Schema_Map_Config $config ) { * * @throws RuntimeException If the input structure is invalid or XML generation fails. */ - public function to_xml( array $schema_map ): string { + public function render( array $schema_map ): string { if ( ! isset( $schema_map ) || ! \is_array( $schema_map ) ) { throw new RuntimeException( 'Invalid schemamap data structure: missing or invalid "schemamap" key' ); } From da023c5c25332bddee1b4bbde8b2b9ac14739c41 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 11 Nov 2025 11:06:17 +0100 Subject: [PATCH 076/319] cs --- src/schema_aggregator/infrastructure/config.php | 2 +- .../site-schema-response-header-integration.php | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/schema_aggregator/infrastructure/config.php b/src/schema_aggregator/infrastructure/config.php index 4ccfc5e7218..610b0d3f0d2 100644 --- a/src/schema_aggregator/infrastructure/config.php +++ b/src/schema_aggregator/infrastructure/config.php @@ -29,7 +29,7 @@ class Config { public function get_per_page(): int { $per_page = (int) \apply_filters( 'wpseo_schema_aggregator_aggregator_per_page', self::DEFAULT_PER_PAGE ); - if($per_page > self::MAX_PER_PAGE) { + if ( $per_page > self::MAX_PER_PAGE ) { $per_page = self::MAX_PER_PAGE; } diff --git a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php index eb616a96803..e37356426a8 100644 --- a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php +++ b/src/schema_aggregator/user-interface/site-schema-response-header-integration.php @@ -6,6 +6,7 @@ use WP_REST_Response; use Yoast\WP\SEO\Conditionals\No_Conditionals; use Yoast\WP\SEO\Integrations\Integration_Interface; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Header_Adapter; /** * Integration to set proper response headers for Site Schema endpoints. @@ -17,16 +18,16 @@ class Site_Schema_Response_Header_Integration implements Integration_Interface { /** * The schema map header adapter. * - * @var mixed + * @var Schema_Map_Header_Adapter */ private $schema_map_header_adapter; /** * Constructor. * - * @param mixed $schema_map_header_adapter The schema map header adapter. + * @param Schema_Map_Header_Adapter $schema_map_header_adapter The schema map header adapter. */ - public function __construct( $schema_map_header_adapter ) { + public function __construct( Schema_Map_Header_Adapter $schema_map_header_adapter ) { $this->schema_map_header_adapter = $schema_map_header_adapter; } From 00ae45455a419b80e49a151443b28e08f24e9160 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 11 Nov 2025 12:37:58 +0100 Subject: [PATCH 077/319] Add indexable count value types. --- .../schema_map/schema-map-builder.php | 12 +++-- .../domain/indexable-count-collection.php | 35 ++++++++++++++ .../domain/indexable-count.php | 48 +++++++++++++++++++ .../schema-map-indexable-repository.php | 10 ++-- 4 files changed, 97 insertions(+), 8 deletions(-) create mode 100644 src/schema_aggregator/domain/indexable-count-collection.php create mode 100644 src/schema_aggregator/domain/indexable-count.php diff --git a/src/schema_aggregator/application/schema_map/schema-map-builder.php b/src/schema_aggregator/application/schema_map/schema-map-builder.php index c26a5caa490..cab072054b9 100644 --- a/src/schema_aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema_aggregator/application/schema_map/schema-map-builder.php @@ -2,6 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application\Schema_Map; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Indexable_Repository; /** @@ -28,14 +29,17 @@ public function __construct( Schema_Map_Indexable_Repository $indexable_reposito /** * Builds the schema map based on indexable counts and threshold. * - * @param array $indexable_counts The indexable counts per post type. - * @param int $threshold The threshold for items per page. + * @param Indexable_Count_Collection $indexable_counts The indexable counts per post type. + * @param int $threshold The threshold for items per page. * * @return array> The schema map. */ - public function build( array $indexable_counts, int $threshold ): array { + public function build( Indexable_Count_Collection $indexable_counts, int $threshold ): array { $schema_map = []; - foreach ( $indexable_counts as $post_type => $count ) { + foreach ( $indexable_counts->get_indexable_counts() as $indexable_count ) { + $post_type = $indexable_count->get_post_type(); + $count = $indexable_count->get_count(); + $total_pages = (int) \ceil( $count / $threshold ); for ( $page = 1; $page <= $total_pages; $page++ ) { diff --git a/src/schema_aggregator/domain/indexable-count-collection.php b/src/schema_aggregator/domain/indexable-count-collection.php new file mode 100644 index 00000000000..49bf27eb894 --- /dev/null +++ b/src/schema_aggregator/domain/indexable-count-collection.php @@ -0,0 +1,35 @@ + + */ + private array $indexable_counts; + + /** + * Adds an Indexable_Count object to the collection. + * + * @param Indexable_Count $indexable_count The Indexable_Count object to add. + * @return void + */ + public function add_indexable_count( Indexable_Count $indexable_count ): void { + $this->indexable_counts[] = $indexable_count; + } + + /** + * Gets all indexable counts. + * + * @return array The array of Indexable_Count objects. + */ + public function get_indexable_counts(): array { + return $this->indexable_counts; + } +} diff --git a/src/schema_aggregator/domain/indexable-count.php b/src/schema_aggregator/domain/indexable-count.php new file mode 100644 index 00000000000..cc2fb9a59b7 --- /dev/null +++ b/src/schema_aggregator/domain/indexable-count.php @@ -0,0 +1,48 @@ +post_type = $post_type; + $this->count = $count; + } + + /** + * Gets the count of indexables. + * + * @return int The count of indexables. + */ + public function get_count(): int { + return $this->count; + } + + /** + * Gets the post type. + * + * @return string The post type. + */ + public function get_post_type(): string { + return $this->post_type; + } +} diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index afa873ad611..9f4f2c405b6 100644 --- a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -4,6 +4,8 @@ use Exception; use Yoast\WP\SEO\Repositories\Indexable_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; /** * Class Schema_Map_Indexable_Repository @@ -33,10 +35,10 @@ public function __construct( Indexable_Repository $indexable_repository ) { * * @param array $post_types The post types to get the indexable count for. * - * @return array The indexable count per post type. + * @return Indexable_Count_Collection The indexable count per post type. */ - public function get_indexable_count_per_post_type( array $post_types ): array { - $post_type_counts = []; + public function get_indexable_count_per_post_type( array $post_types ): Indexable_Count_Collection { + $post_type_counts = new Indexable_Count_Collection(); $indexable_raw_value = $this->indexable_repository->query() ->select_expr( 'object_sub_type,count(object_sub_type) as count' ) ->where_in( 'object_sub_type', $post_types ) @@ -48,7 +50,7 @@ public function get_indexable_count_per_post_type( array $post_types ): array { } foreach ( $indexable_raw_value as $indexable ) { - $post_type_counts[ $indexable['object_sub_type'] ] = $indexable['count']; + $post_type_counts->add_indexable_count( new Indexable_Count( $indexable['object_sub_type'], (int) $indexable['count'] ) ); } return $post_type_counts; From f3c61599affdca71b97181d4ffed28576a2e9081 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 12 Nov 2025 10:28:27 +0100 Subject: [PATCH 078/319] Rename because I am an idiot. --- .../application/aggregate-site-schema-command-handler.php | 0 .../application/aggregate-site-schema-command.php | 0 .../application/aggregate-site-schema-map-command-handler.php | 0 .../application/aggregate-site-schema-map-command.php | 0 .../application/schema_map/schema-map-builder.php | 0 .../application/schema_map/schema-map-xml-renderer.php | 0 .../domain/indexable-count-collection.php | 0 .../domain/indexable-count.php | 0 .../domain/page-controls.php | 0 .../domain/schema-piece-repository-interface.php | 0 .../domain/schema-piece.php | 0 .../infrastructure/config.php | 0 .../infrastructure/meta-tags-context-memoizer-adapter.php | 0 .../infrastructure/schema-piece-repository.php | 0 .../infrastructure/schema_map/schema-map-config.php | 0 .../infrastructure/schema_map/schema-map-header-adapter.php | 0 .../infrastructure/schema_map/schema-map-indexable-repository.php | 0 .../infrastructure/site-schema-json-conditional.php | 0 .../user-interface/site-schema-aggregator-cli-command.php | 0 .../user-interface/site-schema-aggregator-route.php | 0 .../user-interface/site-schema-aggregator-xml-route.php | 0 .../user-interface/site-schema-response-header-integration.php | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename src/{schema_aggregator => schema-aggregator}/application/aggregate-site-schema-command-handler.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/aggregate-site-schema-command.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/aggregate-site-schema-map-command-handler.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/aggregate-site-schema-map-command.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/schema_map/schema-map-builder.php (100%) rename src/{schema_aggregator => schema-aggregator}/application/schema_map/schema-map-xml-renderer.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/indexable-count-collection.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/indexable-count.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/page-controls.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/schema-piece-repository-interface.php (100%) rename src/{schema_aggregator => schema-aggregator}/domain/schema-piece.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/config.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/meta-tags-context-memoizer-adapter.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/schema-piece-repository.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/schema_map/schema-map-config.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/schema_map/schema-map-header-adapter.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/schema_map/schema-map-indexable-repository.php (100%) rename src/{schema_aggregator => schema-aggregator}/infrastructure/site-schema-json-conditional.php (100%) rename src/{schema_aggregator => schema-aggregator}/user-interface/site-schema-aggregator-cli-command.php (100%) rename src/{schema_aggregator => schema-aggregator}/user-interface/site-schema-aggregator-route.php (100%) rename src/{schema_aggregator => schema-aggregator}/user-interface/site-schema-aggregator-xml-route.php (100%) rename src/{schema_aggregator => schema-aggregator}/user-interface/site-schema-response-header-integration.php (100%) diff --git a/src/schema_aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php similarity index 100% rename from src/schema_aggregator/application/aggregate-site-schema-command-handler.php rename to src/schema-aggregator/application/aggregate-site-schema-command-handler.php diff --git a/src/schema_aggregator/application/aggregate-site-schema-command.php b/src/schema-aggregator/application/aggregate-site-schema-command.php similarity index 100% rename from src/schema_aggregator/application/aggregate-site-schema-command.php rename to src/schema-aggregator/application/aggregate-site-schema-command.php diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php similarity index 100% rename from src/schema_aggregator/application/aggregate-site-schema-map-command-handler.php rename to src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php diff --git a/src/schema_aggregator/application/aggregate-site-schema-map-command.php b/src/schema-aggregator/application/aggregate-site-schema-map-command.php similarity index 100% rename from src/schema_aggregator/application/aggregate-site-schema-map-command.php rename to src/schema-aggregator/application/aggregate-site-schema-map-command.php diff --git a/src/schema_aggregator/application/schema_map/schema-map-builder.php b/src/schema-aggregator/application/schema_map/schema-map-builder.php similarity index 100% rename from src/schema_aggregator/application/schema_map/schema-map-builder.php rename to src/schema-aggregator/application/schema_map/schema-map-builder.php diff --git a/src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php b/src/schema-aggregator/application/schema_map/schema-map-xml-renderer.php similarity index 100% rename from src/schema_aggregator/application/schema_map/schema-map-xml-renderer.php rename to src/schema-aggregator/application/schema_map/schema-map-xml-renderer.php diff --git a/src/schema_aggregator/domain/indexable-count-collection.php b/src/schema-aggregator/domain/indexable-count-collection.php similarity index 100% rename from src/schema_aggregator/domain/indexable-count-collection.php rename to src/schema-aggregator/domain/indexable-count-collection.php diff --git a/src/schema_aggregator/domain/indexable-count.php b/src/schema-aggregator/domain/indexable-count.php similarity index 100% rename from src/schema_aggregator/domain/indexable-count.php rename to src/schema-aggregator/domain/indexable-count.php diff --git a/src/schema_aggregator/domain/page-controls.php b/src/schema-aggregator/domain/page-controls.php similarity index 100% rename from src/schema_aggregator/domain/page-controls.php rename to src/schema-aggregator/domain/page-controls.php diff --git a/src/schema_aggregator/domain/schema-piece-repository-interface.php b/src/schema-aggregator/domain/schema-piece-repository-interface.php similarity index 100% rename from src/schema_aggregator/domain/schema-piece-repository-interface.php rename to src/schema-aggregator/domain/schema-piece-repository-interface.php diff --git a/src/schema_aggregator/domain/schema-piece.php b/src/schema-aggregator/domain/schema-piece.php similarity index 100% rename from src/schema_aggregator/domain/schema-piece.php rename to src/schema-aggregator/domain/schema-piece.php diff --git a/src/schema_aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php similarity index 100% rename from src/schema_aggregator/infrastructure/config.php rename to src/schema-aggregator/infrastructure/config.php diff --git a/src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php b/src/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php similarity index 100% rename from src/schema_aggregator/infrastructure/meta-tags-context-memoizer-adapter.php rename to src/schema-aggregator/infrastructure/meta-tags-context-memoizer-adapter.php diff --git a/src/schema_aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php similarity index 100% rename from src/schema_aggregator/infrastructure/schema-piece-repository.php rename to src/schema-aggregator/infrastructure/schema-piece-repository.php diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-config.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-config.php similarity index 100% rename from src/schema_aggregator/infrastructure/schema_map/schema-map-config.php rename to src/schema-aggregator/infrastructure/schema_map/schema-map-config.php diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-header-adapter.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php similarity index 100% rename from src/schema_aggregator/infrastructure/schema_map/schema-map-header-adapter.php rename to src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php diff --git a/src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php similarity index 100% rename from src/schema_aggregator/infrastructure/schema_map/schema-map-indexable-repository.php rename to src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php diff --git a/src/schema_aggregator/infrastructure/site-schema-json-conditional.php b/src/schema-aggregator/infrastructure/site-schema-json-conditional.php similarity index 100% rename from src/schema_aggregator/infrastructure/site-schema-json-conditional.php rename to src/schema-aggregator/infrastructure/site-schema-json-conditional.php diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php similarity index 100% rename from src/schema_aggregator/user-interface/site-schema-aggregator-cli-command.php rename to src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php similarity index 100% rename from src/schema_aggregator/user-interface/site-schema-aggregator-route.php rename to src/schema-aggregator/user-interface/site-schema-aggregator-route.php diff --git a/src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php similarity index 100% rename from src/schema_aggregator/user-interface/site-schema-aggregator-xml-route.php rename to src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php diff --git a/src/schema_aggregator/user-interface/site-schema-response-header-integration.php b/src/schema-aggregator/user-interface/site-schema-response-header-integration.php similarity index 100% rename from src/schema_aggregator/user-interface/site-schema-response-header-integration.php rename to src/schema-aggregator/user-interface/site-schema-response-header-integration.php From e339a254a03155e0d6c5af4c521472dda14941b3 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 12 Nov 2025 10:35:39 +0100 Subject: [PATCH 079/319] Cleanup cs. --- src/schema-aggregator/domain/indexable-count.php | 8 ++++++-- src/schema-aggregator/domain/schema-piece.php | 2 -- .../infrastructure/schema-piece-repository.php | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/schema-aggregator/domain/indexable-count.php b/src/schema-aggregator/domain/indexable-count.php index cc2fb9a59b7..d041e4bce15 100644 --- a/src/schema-aggregator/domain/indexable-count.php +++ b/src/schema-aggregator/domain/indexable-count.php @@ -9,13 +9,17 @@ class Indexable_Count { /** * The count of indexables. + * + * @var int */ - private int $count; + private $count; /** * The post type. + * + * @var string */ - private string $post_type; + private $post_type; /** * Constructor for Indexable_Count. diff --git a/src/schema-aggregator/domain/schema-piece.php b/src/schema-aggregator/domain/schema-piece.php index 2e2e9bfd4c3..fb12d96d728 100644 --- a/src/schema-aggregator/domain/schema-piece.php +++ b/src/schema-aggregator/domain/schema-piece.php @@ -3,8 +3,6 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Domain; -use WPSEO_Utils; - /** * Represents a piece of schema.org data. */ diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 30783354352..e5a442133cd 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -9,7 +9,6 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Schema_Enhancement_Factory; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; -use Yoast\WP\SEO\Repositories\Indexable_Repository; /** * Repository for Schema_Piece objects. From 0080f7e6f7ec6d11a8b04052eeff70d99ad8b9db Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 12 Nov 2025 15:22:52 +0100 Subject: [PATCH 080/319] weird import fix. --- .../infrastructure/schema_map/schema-map-header-adapter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php index a2fa6de0d64..1883022b952 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php @@ -3,6 +3,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map; use WP_REST_Response; +use WPSEO_Utils; /** * Adapter to set proper response headers for Schema Map responses. From 06275ac208cd3c85bc735a2043c31752f5fde0b8 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 12 Nov 2025 16:00:50 +0100 Subject: [PATCH 081/319] Start composing the request. --- .../aggregate-site-schema-command-handler.php | 28 ++++++++++------ .../schema-aggregator-response-composer.php | 32 +++++++++++++++++++ src/schema-aggregator/domain/schema-piece.php | 1 - .../infrastructure/config.php | 2 +- .../schema-map-indexable-repository.php | 2 +- 5 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 src/schema-aggregator/application/schema-aggregator-response-composer.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index 439bc5fdbc0..b6b7d77f787 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -24,15 +24,28 @@ class Aggregate_Site_Schema_Command_Handler { */ private $schema_piece_aggregator; + /** + * The Schema_Aggregator_Response_Composer instance. + * + * @var Schema_Aggregator_Response_Composer + */ + private $schema_response_composer; + /** * Aggregate_Site_Schema_Command_Handler constructor. * - * @param Schema_Piece_Repository $schema_piece_repository The collector of indexables that need to be aggregated. - * @param Schema_Pieces_Aggregator $schema_piece_aggregator The schema pieces aggregator. + * @param Schema_Piece_Repository $schema_piece_repository The collector of indexables that need to be aggregated. + * @param Schema_Pieces_Aggregator $schema_piece_aggregator The schema pieces aggregator. + * @param Schema_Aggregator_Response_Composer $schema_response_composer The schema response composer. */ - public function __construct( Schema_Piece_Repository $schema_piece_repository, Schema_Pieces_Aggregator $schema_piece_aggregator ) { - $this->schema_piece_repository = $schema_piece_repository; - $this->schema_piece_aggregator = $schema_piece_aggregator; + public function __construct( + Schema_Piece_Repository $schema_piece_repository, + Schema_Pieces_Aggregator $schema_piece_aggregator, + Schema_Aggregator_Response_Composer $schema_response_composer + ) { + $this->schema_piece_repository = $schema_piece_repository; + $this->schema_piece_aggregator = $schema_piece_aggregator; + $this->schema_response_composer = $schema_response_composer; } /** @@ -51,10 +64,7 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { ); $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); - $schema = []; - foreach ( $aggregated_schema_pieces as $schema_piece ) { - $schema[] = $schema_piece->to_json_ld_graph(); - } + $schema = $this->schema_response_composer->compose( $aggregated_schema_pieces ); return $schema; } } diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php new file mode 100644 index 00000000000..7fcdbab3169 --- /dev/null +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -0,0 +1,32 @@ + $schema_pieces The schema pieces to include in the response. + * + * @return array The composed schema response. + */ + public function compose( array $schema_pieces ): array { + return [ + '@context' => 'https://schema.org', + '@graph' => \array_map( + static function ( $piece ) { + return $piece->get_data(); + }, + \array_values( $schema_pieces ) + ), + ]; + } +} diff --git a/src/schema-aggregator/domain/schema-piece.php b/src/schema-aggregator/domain/schema-piece.php index fb12d96d728..a98615fcb74 100644 --- a/src/schema-aggregator/domain/schema-piece.php +++ b/src/schema-aggregator/domain/schema-piece.php @@ -67,7 +67,6 @@ public function get_id(): ?string { */ public function to_json_ld_graph(): array { return [ - '@context' => 'https://schema.org', '@graph' => $this->data, ]; } diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 556663eda5b..77e88bd4556 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -12,7 +12,7 @@ class Config { * * @var int */ - private const DEFAULT_PER_PAGE = 100; + private const DEFAULT_PER_PAGE = 5; /** * Maximum items per page diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index 9f4f2c405b6..c54ec3e5f22 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -81,7 +81,7 @@ public function get_lastmod_for_post_type( string $post_type, int $page, int $pe // Convert to ISO 8601 format or use current time if no posts. if ( $lastmod && ! empty( $lastmod ) ) { - return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod ) ); + return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod->object_last_modified ) ); } return $fallback; From a4a83b3066e966c1072ae17f3bc901e4c4e017bf Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 15:24:29 +0100 Subject: [PATCH 082/319] Add new options --- inc/options/class-wpseo-option-wpseo.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/inc/options/class-wpseo-option-wpseo.php b/inc/options/class-wpseo-option-wpseo.php index 5bd2db69979..7b4cc8c3cdc 100644 --- a/inc/options/class-wpseo-option-wpseo.php +++ b/inc/options/class-wpseo-option-wpseo.php @@ -154,6 +154,8 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { 'default_seo_title' => [], 'default_seo_meta_desc' => [], 'first_activated_by' => 0, + 'enable_schema_aggregator' => false, + 'schema_aggregator_enabled_on' => null, ]; /** @@ -354,6 +356,7 @@ protected function validate_option( $dirty, $clean, $old ) { case 'site_kit_tracking_setup_widget_temporarily_dismissed': case 'site_kit_tracking_setup_widget_permanently_dismissed': case 'ai_free_sparks_started_on': + case 'schema_aggregator_enabled_on': if ( isset( $dirty[ $key ] ) ) { $clean[ $key ] = sanitize_text_field( $dirty[ $key ] ); } @@ -547,6 +550,7 @@ protected function validate_option( $dirty, $clean, $old ) { * 'site_kit_connected', * 'google_site_kit_feature_enabled', * 'enable_llms_txt', + * 'enable_schema_aggregator' * and most of the feature variables. */ default: @@ -617,6 +621,7 @@ public function verify_features_against_network( $options = [] ) { 'algolia_integration_active' => false, 'google_site_kit_feature_enabled' => false, 'enable_llms_txt' => false, + 'enable_schema_aggregator' => false, ]; // We can reuse this logic from the base class with the above defaults to parse with the correct feature values. From 49f5b81fee9cc44329e1f27fc52f273528c27fa8 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 15:24:45 +0100 Subject: [PATCH 083/319] Add new options to the tracked ones --- admin/tracking/class-tracking-settings-data.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/admin/tracking/class-tracking-settings-data.php b/admin/tracking/class-tracking-settings-data.php index 24ff864506e..714e03d3891 100644 --- a/admin/tracking/class-tracking-settings-data.php +++ b/admin/tracking/class-tracking-settings-data.php @@ -244,6 +244,8 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection { 'enable_llms_txt', 'llms_txt_selection_mode', 'configuration_finished_steps', + 'enable_schema_aggregator', + 'schema_aggregator_enabled_on', ]; /** From 65b183ea449801e90562dfbb83908fe646041c47 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 15:24:56 +0100 Subject: [PATCH 084/319] Temporary icon --- images/icon-schema-aggregator.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 images/icon-schema-aggregator.svg diff --git a/images/icon-schema-aggregator.svg b/images/icon-schema-aggregator.svg new file mode 100644 index 00000000000..5cd00ba4d21 --- /dev/null +++ b/images/icon-schema-aggregator.svg @@ -0,0 +1 @@ + \ No newline at end of file From 633e7cdc9589fb2ba5efb17e67d231002172f42f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 15:25:29 +0100 Subject: [PATCH 085/319] Add and use the new conditional dependent on the toggle state --- .../schema-aggregator-conditional.php | 38 +++++++++++++++++++ .../site-schema-aggregator-route.php | 3 +- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/schema-aggregator/infrastructure/schema-aggregator-conditional.php diff --git a/src/schema-aggregator/infrastructure/schema-aggregator-conditional.php b/src/schema-aggregator/infrastructure/schema-aggregator-conditional.php new file mode 100644 index 00000000000..5d3b6e4a147 --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema-aggregator-conditional.php @@ -0,0 +1,38 @@ +options = $options; + } + + /** + * Returns `true` when the Schema aggregator feature is enabled. + * + * @return bool `true` when the Schema aggregator feature is enabled. + */ + public function is_met(): bool { + return $this->options->get( 'enable_schema_aggregator' ) === true; + } +} diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index ca2d52caf20..35530b5e229 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -11,6 +11,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; /** @@ -60,7 +61,7 @@ class Site_Schema_Aggregator_Route implements Route_Interface { * @return array The conditionals that must be met to load this. */ public static function get_conditionals() { - return [ Site_Schema_Json_Conditional::class ]; + return [ Site_Schema_Json_Conditional::class, Schema_Aggregator_Conditional::class ]; } /** From d2f5ef5ebe7c96d5031557a18c2390797b212204 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 15:28:44 +0100 Subject: [PATCH 086/319] Add the watcher to write a timestamp the first time the toggle is set to on --- .../schema-aggregator-watcher.php | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/schema-aggregator-watcher.php diff --git a/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php new file mode 100644 index 00000000000..65f2343b321 --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php @@ -0,0 +1,83 @@ +options_helper = $options_helper; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'update_option_wpseo', [ $this, 'check_schema_aggregator_enabled' ], 10, 2 ); + } + + // phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification -- They can really be anything. + + /** + * Checks if the enable_schema_aggregator option has been enabled for the first time. + * + * @param array $old_value The old value of the option. + * @param array $new_value The new value of the option. + * + * @return bool Whether the schema_aggregator_enabled_on timestamp was set. + */ + public function check_schema_aggregator_enabled( $old_value, $new_value ): bool { + if ( $old_value === false ) { + $old_value = []; + } + + if ( ! \is_array( $old_value ) || ! \is_array( $new_value ) ) { + return false; + } + + $option_key = 'enable_schema_aggregator'; + $timestamp_key = 'schema_aggregator_enabled_on'; + + $old_enabled = isset( $old_value[ $option_key ] ) && (bool) $old_value[ $option_key ]; + $new_enabled = isset( $new_value[ $option_key ] ) && (bool) $new_value[ $option_key ]; + + if ( ! $old_enabled && $new_enabled ) { + $current_timestamp = $this->options_helper->get( $timestamp_key ); + + if ( empty( $current_timestamp ) ) { + $this->options_helper->set( $timestamp_key, \time() ); + return true; + } + } + + return false; + } + // phpcs:enable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification +} From 210aa923337cd356cc6579df8f22d968b31e6583 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 15:56:49 +0100 Subject: [PATCH 087/319] Fix cs --- .../infrastructure/schema-aggregator-watcher.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php index 65f2343b321..94faa79bac4 100644 --- a/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php +++ b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php @@ -79,5 +79,6 @@ public function check_schema_aggregator_enabled( $old_value, $new_value ): bool return false; } + // phpcs:enable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification } From b4c787a1a5faae69b004db91b5ae2527b172a916 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 16:01:32 +0100 Subject: [PATCH 088/319] Add feature card --- packages/js/src/settings/routes/site-features.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/js/src/settings/routes/site-features.js b/packages/js/src/settings/routes/site-features.js index 36d4eea6e28..9685e0b9ca5 100644 --- a/packages/js/src/settings/routes/site-features.js +++ b/packages/js/src/settings/routes/site-features.js @@ -243,6 +243,16 @@ const SiteFeatures = () => { + +

{ __( "Surprisingly, this feature aggregates the schema..", "wordpress-seo" ) }

+ +

From 9f1181b2be3b5cb8032b88c9fdd00b577d0753bf Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 11 Nov 2025 16:06:01 +0100 Subject: [PATCH 089/319] Fix cs --- .../infrastructure/schema-aggregator-watcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php index 94faa79bac4..45e70df7373 100644 --- a/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php +++ b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php @@ -79,6 +79,6 @@ public function check_schema_aggregator_enabled( $old_value, $new_value ): bool return false; } - + // phpcs:enable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification } From 4d21c458a366d2b9c4b5907df1df65f151a574d0 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 13 Nov 2025 11:33:45 +0100 Subject: [PATCH 090/319] Remove old conditional and use the new one --- .../site-schema-json-conditional.php | 37 ------------------- .../site-schema-aggregator-route.php | 3 +- .../site-schema-aggregator-xml-route.php | 4 +- 3 files changed, 3 insertions(+), 41 deletions(-) delete mode 100644 src/schema-aggregator/infrastructure/site-schema-json-conditional.php diff --git a/src/schema-aggregator/infrastructure/site-schema-json-conditional.php b/src/schema-aggregator/infrastructure/site-schema-json-conditional.php deleted file mode 100644 index 7e9fd72deff..00000000000 --- a/src/schema-aggregator/infrastructure/site-schema-json-conditional.php +++ /dev/null @@ -1,37 +0,0 @@ -options = $options; - } - - /** - * Returns whether the 'Site schema route' setting has been enabled. - * - * @return bool `true` when the 'Site schema route' setting has been enabled. - */ - public function is_met() { - return true; - } -} diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 35530b5e229..1b1b28b74fb 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -12,7 +12,6 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; /** * Handles the route to represent a site's schema as JSON. @@ -61,7 +60,7 @@ class Site_Schema_Aggregator_Route implements Route_Interface { * @return array The conditionals that must be met to load this. */ public static function get_conditionals() { - return [ Site_Schema_Json_Conditional::class, Schema_Aggregator_Conditional::class ]; + return [ Schema_Aggregator_Conditional::class ]; } /** diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php index 04c515fed4f..ac0df9451fd 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -11,7 +11,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; /** * Handles the route to represent all indexable post types as XML. @@ -67,7 +67,7 @@ class Site_Schema_Aggregator_Xml_Route implements Route_Interface { * @return array The conditionals that must be met to load this. */ public static function get_conditionals() { - return [ Site_Schema_Json_Conditional::class ]; + return [ Schema_Aggregator_Conditional::class ]; } /** From d701dd31f13502d998e3f361d23fc59f0e1318c5 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 13 Nov 2025 13:24:43 +0100 Subject: [PATCH 091/319] Add more meta info --- .../aggregate-site-schema-command-handler.php | 2 +- .../meta/response-meta-provider.php | 102 ++++++++++++++++++ .../schema-aggregator-response-composer.php | 25 ++++- .../schema_map/schema-map-builder.php | 24 ++++- .../schema-map-indexable-repository.php | 20 ++++ 5 files changed, 168 insertions(+), 5 deletions(-) create mode 100644 src/schema-aggregator/application/meta/response-meta-provider.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index b6b7d77f787..e5457ac8cf3 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -64,7 +64,7 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { ); $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); - $schema = $this->schema_response_composer->compose( $aggregated_schema_pieces ); + $schema = $this->schema_response_composer->compose( $aggregated_schema_pieces, $command->get_page_controls()->get_post_type(), $command->get_page_controls()->get_page(), $command->get_page_controls()->get_page_size() ); return $schema; } } diff --git a/src/schema-aggregator/application/meta/response-meta-provider.php b/src/schema-aggregator/application/meta/response-meta-provider.php new file mode 100644 index 00000000000..ffcdf4edf74 --- /dev/null +++ b/src/schema-aggregator/application/meta/response-meta-provider.php @@ -0,0 +1,102 @@ +schema_map_repository = $schema_map_repository; + $this->schema_map_builder = $schema_map_builder; + } + + /** + * Build metadata structure for API response + * + * @param string $post_type The post type being queried. + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. + * + * @return array> Metadata structure. + */ + public function get_metadata( string $post_type, int $page, int $page_size ): array { + $metadata = [ + 'generator' => [ + 'name' => 'Yoast NLWeb Integration', + 'version' => \WPSEO_VERSION, + 'vendor' => 'Yoast', + 'url' => 'https://yoast.com', + ], + 'dependencies' => [ + 'wordpress' => \function_exists( 'get_bloginfo' ) ? \get_bloginfo( 'version' ) : 'unknown', + 'yoast_seo' => \WPSEO_VERSION, + ], + 'generated_at' => \gmdate( 'Y-m-d\TH:i:s\Z' ), + ]; + + if ( \defined( 'WPSEO_WOO_VERSION' ) ) { + $metadata['dependencies']['yoast_seo_woocommerce'] = \WPSEO_WOO_VERSION; + } + + return $this->maybe_add_pagination_metadata( $metadata, $post_type, $page, $page_size ); + } + + /** + * Add pagination metadata to the response if applicable. + * + * @param array> $metadata The metadata array to add pagination info to. + * @param string $post_type The post type being queried. + * @param int $page The current page number (1-based). + * @param int $page_size The number of items per page. + * + * @return array> The updated metadata array. + */ + private function maybe_add_pagination_metadata( + array $metadata, + string $post_type, + int $page, + int $page_size + ): array { + + $indexable_count = $this->schema_map_repository->get_indexable_count_for_post_type( $post_type ); + $total_items = $indexable_count->get_count(); + + if ( $total_items === 0 ) { + return $metadata; + } + + $total_pages = (int) \ceil( $total_items / $page_size ); + + if ( $page < $total_pages ) { + $next_page_url = $this->schema_map_builder->get_rest_route( $post_type, ( $page + 1 ) ); + $metadata['next'] = $next_page_url; + + } + return $metadata; + } +} diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php index 7fcdbab3169..fe9d9c8a347 100644 --- a/src/schema-aggregator/application/schema-aggregator-response-composer.php +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -2,6 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; +use Yoast\WP\SEO\Schema_Aggregator\Application\Meta\Response_Meta_Provider; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; /** @@ -11,14 +12,35 @@ */ class Schema_Aggregator_Response_Composer { + /** + * The meta provider. + * + * @var Response_Meta_Provider + */ + private $meta_provider; + + /** + * Schema_Aggregator_Response_Composer constructor. + * + * @param Response_Meta_Provider $meta_provider The meta provider. + */ + public function __construct( Response_Meta_Provider $meta_provider ) { + $this->meta_provider = $meta_provider; + } + /** * Composes the final schema response. * * @param array $schema_pieces The schema pieces to include in the response. + * @param string $post_type The post type being queried. + * @param int $page The page number (1-based). + * @param int $page_size The number of items per page. * * @return array The composed schema response. */ - public function compose( array $schema_pieces ): array { + public function compose( array $schema_pieces, string $post_type, int $page, int $page_size ): array { + + $meta = $this->meta_provider->get_metadata( $post_type, $page, $page_size ); return [ '@context' => 'https://schema.org', '@graph' => \array_map( @@ -27,6 +49,7 @@ static function ( $piece ) { }, \array_values( $schema_pieces ) ), + 'meta' => $meta, ]; } } diff --git a/src/schema-aggregator/application/schema_map/schema-map-builder.php b/src/schema-aggregator/application/schema_map/schema-map-builder.php index cab072054b9..4dce60a9ace 100644 --- a/src/schema-aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema-aggregator/application/schema_map/schema-map-builder.php @@ -2,6 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application\Schema_Map; +use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Indexable_Repository; @@ -44,13 +45,13 @@ public function build( Indexable_Count_Collection $indexable_counts, int $thresh for ( $page = 1; $page <= $total_pages; $page++ ) { if ( $page === 1 && $total_pages === 1 ) { - $url = \rest_url( 'schema-aggregator/get-schema/' . $post_type ); + $url = $this->get_rest_route( $post_type ); } elseif ( $page === 1 ) { - $url = \rest_url( 'schema-aggregator/get-schema/' . $post_type ); + $url = $this->get_rest_route( $post_type ); } else { - $url = \rest_url( 'schema-aggregator/get-schema/' . $post_type . '/' . $page ); + $url = $this->get_rest_route( $post_type, $page ); } $lastmod = $this->indexable_repository->get_lastmod_for_post_type( $post_type, $page, $threshold ); @@ -68,4 +69,21 @@ public function build( Indexable_Count_Collection $indexable_counts, int $thresh return $schema_map; } + + /** + * Gets the REST route for the given post type and page. + * + * @param string $post_type The post type. + * @param int $page The page number (default is 1). + * + * @return string The REST route URL. + */ + public function get_rest_route( $post_type, $page = 1 ): string { + if ( $page === 1 ) { + return \rest_url( Main::API_V1_NAMESPACE . '/schema-aggregator/get-schema/' . $post_type ); + } + else { + return \rest_url( Main::API_V1_NAMESPACE . '/schema-aggregator/get-schema/' . $post_type . '/' . $page ); + } + } } diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index c54ec3e5f22..17ef75dfe69 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -56,6 +56,26 @@ public function get_indexable_count_per_post_type( array $post_types ): Indexabl return $post_type_counts; } + /** + * Gets the indexable count for a single post type. + * + * @param string $post_type The post type to get the indexable count for. + * + * @return Indexable_Count The indexable count for the post type. + */ + public function get_indexable_count_for_post_type( string $post_type ): Indexable_Count { + $indexable_raw_value = $this->indexable_repository->query() + ->select_expr( 'object_sub_type,count(object_sub_type) as count' ) + ->where( 'object_sub_type', $post_type ) + ->find_one(); + + if ( empty( $indexable_raw_value ) ) { + return new Indexable_Count( $post_type, 0 ); + } + + return new Indexable_Count( $indexable_raw_value->object_sub_type, (int) $indexable_raw_value->count ); + } + /** * Get lastmod timestamp for a post type and page range * From f00641d4e0437f6b8952a81dc4b34e6dba18532f Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 13 Nov 2025 15:33:46 +0100 Subject: [PATCH 092/319] Change default back. --- src/schema-aggregator/infrastructure/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 77e88bd4556..556663eda5b 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -12,7 +12,7 @@ class Config { * * @var int */ - private const DEFAULT_PER_PAGE = 5; + private const DEFAULT_PER_PAGE = 100; /** * Maximum items per page From 124ea811fc714dc91b168ba31150ae537c3739cd Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 13 Nov 2025 15:47:26 +0100 Subject: [PATCH 093/319] User copy from UX --- packages/js/src/settings/routes/site-features.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/js/src/settings/routes/site-features.js b/packages/js/src/settings/routes/site-features.js index 9685e0b9ca5..fab38c31553 100644 --- a/packages/js/src/settings/routes/site-features.js +++ b/packages/js/src/settings/routes/site-features.js @@ -248,9 +248,9 @@ const SiteFeatures = () => { cardId="card-wpseo-enable_schema_aggregator" inputId="input-wpseo-enable_schema_aggregator" imageSrc="/images/icon-schema-aggregator.svg" - title={ __( "Schema aggregator", "wordpress-seo" ) } + title={ __( "Schema aggregation endpoint", "wordpress-seo" ) } > -

{ __( "Surprisingly, this feature aggregates the schema..", "wordpress-seo" ) }

+

{ __( "Provides a single JSON endpoint with all your site’s structured data, enabling NLWeb to power natural language AI queries on your content.", "wordpress-seo" ) }

From 80365eb8dc9cd237d2963e0d8d989ff9a8322b2a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 13 Nov 2025 15:47:33 +0100 Subject: [PATCH 094/319] Use icon from UX --- images/icon-schema-aggregator.svg | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/images/icon-schema-aggregator.svg b/images/icon-schema-aggregator.svg index 5cd00ba4d21..6bef9849c1c 100644 --- a/images/icon-schema-aggregator.svg +++ b/images/icon-schema-aggregator.svg @@ -1 +1,19 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + From a895b9081dfdbf3082d3cbe390e6f6da7ed7b1dc Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 13 Nov 2025 16:05:03 +0100 Subject: [PATCH 095/319] Move feature card --- .../js/src/settings/routes/site-features.js | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/js/src/settings/routes/site-features.js b/packages/js/src/settings/routes/site-features.js index fab38c31553..54284ee60b2 100644 --- a/packages/js/src/settings/routes/site-features.js +++ b/packages/js/src/settings/routes/site-features.js @@ -243,16 +243,6 @@ const SiteFeatures = () => { - -

{ __( "Provides a single JSON endpoint with all your site’s structured data, enabling NLWeb to power natural language AI queries on your content.", "wordpress-seo" ) }

- -

@@ -472,7 +462,16 @@ const SiteFeatures = () => {

{ __( "Automatically ping search engines like Bing and Yandex whenever you publish, update or delete a post.", "wordpress-seo" ) }

- + +

{ __( "Provides a single JSON endpoint with all your site’s structured data, enabling NLWeb to power natural language AI queries on your content.", "wordpress-seo" ) }

+ +
From 49007c97f3cb17070467d1d584a61d618214c3e6 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 13 Nov 2025 16:30:32 +0100 Subject: [PATCH 096/319] Update queries to be correct. --- .../schema-map-indexable-repository.php | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index 17ef75dfe69..bc5a996d6ac 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -3,6 +3,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map; use Exception; +use Yoast\WP\Lib\Model; use Yoast\WP\SEO\Repositories\Indexable_Repository; use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count; use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; @@ -42,8 +43,10 @@ public function get_indexable_count_per_post_type( array $post_types ): Indexabl $indexable_raw_value = $this->indexable_repository->query() ->select_expr( 'object_sub_type,count(object_sub_type) as count' ) ->where_in( 'object_sub_type', $post_types ) + ->where_in( 'object_type', [ 'post', 'page' ] ) + ->where_raw( '( is_public IS NULL OR is_public = 1 )' ) ->group_by( [ 'object_type', 'object_sub_type' ] ) - ->find_array(); + ->get_sql(); if ( empty( $indexable_raw_value ) ) { return $post_type_counts; @@ -67,6 +70,8 @@ public function get_indexable_count_for_post_type( string $post_type ): Indexabl $indexable_raw_value = $this->indexable_repository->query() ->select_expr( 'object_sub_type,count(object_sub_type) as count' ) ->where( 'object_sub_type', $post_type ) + ->where_in( 'object_type', [ 'post', 'page' ] ) + ->where_raw( '( is_public IS NULL OR is_public = 1 )' ) ->find_one(); if ( empty( $indexable_raw_value ) ) { @@ -88,17 +93,33 @@ public function get_indexable_count_for_post_type( string $post_type ): Indexabl * @return string ISO 8601 timestamp (e.g., "2025-10-21T14:23:17Z"). */ public function get_lastmod_for_post_type( string $post_type, int $page, int $per_page ): string { + global $wpdb; $fallback = \gmdate( 'Y-m-d\TH:i:s\Z' ); try { - $offset = ( ( $page - 1 ) * $per_page ); - $lastmod = $this->indexable_repository->query() - ->select_expr( 'MAX(object_last_modified)' ) - ->where( 'object_sub_type', $post_type ) - ->where_raw( '( is_public IS NULL OR is_public = 1 )' ) - ->order_by_asc( 'id' )->limit( $per_page )->offset( $offset ) - ->find_one(); + $offset = ( ( $page - 1 ) * $per_page ); + $indexable_table = Model::get_table_name( 'Indexable' ); + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + $lastmod = $wpdb->get_var( + $wpdb->prepare( + " + SELECT MAX(object_last_modified) + FROM ( + + SELECT indexable_table.object_last_modified + FROM {$indexable_table} indexable_table + WHERE object_sub_type = %s + AND ( is_public IS NULL OR is_public = 1 ) + ORDER BY ID + LIMIT %d OFFSET %d + )AS posts_range +", + $post_type, + $per_page, + $offset + ) + ); // Convert to ISO 8601 format or use current time if no posts. if ( $lastmod && ! empty( $lastmod ) ) { return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod->object_last_modified ) ); From 89d2fafb0748320c3121d1f8150406c6d33ebfad Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 17 Nov 2025 14:46:23 +0100 Subject: [PATCH 097/319] Rename icon --- images/icon-schema-aggregation-endpoint.svg | 1 + images/icon-schema-aggregator.svg | 19 ------------------- 2 files changed, 1 insertion(+), 19 deletions(-) create mode 100644 images/icon-schema-aggregation-endpoint.svg delete mode 100644 images/icon-schema-aggregator.svg diff --git a/images/icon-schema-aggregation-endpoint.svg b/images/icon-schema-aggregation-endpoint.svg new file mode 100644 index 00000000000..b02e97ad009 --- /dev/null +++ b/images/icon-schema-aggregation-endpoint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icon-schema-aggregator.svg b/images/icon-schema-aggregator.svg deleted file mode 100644 index 6bef9849c1c..00000000000 --- a/images/icon-schema-aggregator.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - From ed371f4541fd770abc120f7b77a6a9ddd393e3ab Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 17 Nov 2025 14:46:37 +0100 Subject: [PATCH 098/319] Renaming for uniformity --- packages/js/src/settings/routes/site-features.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/js/src/settings/routes/site-features.js b/packages/js/src/settings/routes/site-features.js index 54284ee60b2..f414b4124b7 100644 --- a/packages/js/src/settings/routes/site-features.js +++ b/packages/js/src/settings/routes/site-features.js @@ -463,14 +463,14 @@ const SiteFeatures = () => {

{ __( "Provides a single JSON endpoint with all your site’s structured data, enabling NLWeb to power natural language AI queries on your content.", "wordpress-seo" ) }

- +
From d13c7ce74ab6cb416fa74016b7b4e5f0560ea2c2 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 18 Nov 2025 09:41:37 +0100 Subject: [PATCH 099/319] Fix options naming --- admin/tracking/class-tracking-settings-data.php | 4 ++-- inc/options/class-wpseo-option-wpseo.php | 10 +++++----- .../infrastructure/schema-aggregator-conditional.php | 2 +- .../infrastructure/schema-aggregator-watcher.php | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/admin/tracking/class-tracking-settings-data.php b/admin/tracking/class-tracking-settings-data.php index 714e03d3891..ebf838ea16b 100644 --- a/admin/tracking/class-tracking-settings-data.php +++ b/admin/tracking/class-tracking-settings-data.php @@ -244,8 +244,8 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection { 'enable_llms_txt', 'llms_txt_selection_mode', 'configuration_finished_steps', - 'enable_schema_aggregator', - 'schema_aggregator_enabled_on', + 'enable_schema_aggregation_endpoint', + 'schema_aggregation_endpoint_enabled_on', ]; /** diff --git a/inc/options/class-wpseo-option-wpseo.php b/inc/options/class-wpseo-option-wpseo.php index 7b4cc8c3cdc..bbebc1ce242 100644 --- a/inc/options/class-wpseo-option-wpseo.php +++ b/inc/options/class-wpseo-option-wpseo.php @@ -154,8 +154,8 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { 'default_seo_title' => [], 'default_seo_meta_desc' => [], 'first_activated_by' => 0, - 'enable_schema_aggregator' => false, - 'schema_aggregator_enabled_on' => null, + 'enable_schema_aggregation_endpoint' => false, + 'schema_aggregation_endpoint_enabled_on' => null, ]; /** @@ -356,7 +356,7 @@ protected function validate_option( $dirty, $clean, $old ) { case 'site_kit_tracking_setup_widget_temporarily_dismissed': case 'site_kit_tracking_setup_widget_permanently_dismissed': case 'ai_free_sparks_started_on': - case 'schema_aggregator_enabled_on': + case 'schema_aggregation_endpoint_enabled_on': if ( isset( $dirty[ $key ] ) ) { $clean[ $key ] = sanitize_text_field( $dirty[ $key ] ); } @@ -550,7 +550,7 @@ protected function validate_option( $dirty, $clean, $old ) { * 'site_kit_connected', * 'google_site_kit_feature_enabled', * 'enable_llms_txt', - * 'enable_schema_aggregator' + * 'enable_schema_aggregation_endpoint' * and most of the feature variables. */ default: @@ -621,7 +621,7 @@ public function verify_features_against_network( $options = [] ) { 'algolia_integration_active' => false, 'google_site_kit_feature_enabled' => false, 'enable_llms_txt' => false, - 'enable_schema_aggregator' => false, + 'enable_schema_aggregation_endpoint' => false, ]; // We can reuse this logic from the base class with the above defaults to parse with the correct feature values. diff --git a/src/schema-aggregator/infrastructure/schema-aggregator-conditional.php b/src/schema-aggregator/infrastructure/schema-aggregator-conditional.php index 5d3b6e4a147..eb1e087d9fe 100644 --- a/src/schema-aggregator/infrastructure/schema-aggregator-conditional.php +++ b/src/schema-aggregator/infrastructure/schema-aggregator-conditional.php @@ -33,6 +33,6 @@ public function __construct( Options_Helper $options ) { * @return bool `true` when the Schema aggregator feature is enabled. */ public function is_met(): bool { - return $this->options->get( 'enable_schema_aggregator' ) === true; + return $this->options->get( 'enable_schema_aggregation_endpoint' ) === true; } } diff --git a/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php index 45e70df7373..9888b7140b1 100644 --- a/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php +++ b/src/schema-aggregator/infrastructure/schema-aggregator-watcher.php @@ -8,9 +8,9 @@ use Yoast\WP\SEO\Integrations\Integration_Interface; /** - * Watcher for the enable_schema_aggregator option. + * Watcher for the enable_schema_aggregation_endpoint option. * - * Monitors the enable_schema_aggregator option and sets a timestamp when first enabled. + * Monitors the enable_schema_aggregation_endpoint option and sets a timestamp when first enabled. */ class Schema_Aggregator_Watcher implements Integration_Interface { @@ -46,7 +46,7 @@ public function register_hooks() { // phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification -- They can really be anything. /** - * Checks if the enable_schema_aggregator option has been enabled for the first time. + * Checks if the enable_schema_aggregation_endpoint option has been enabled for the first time. * * @param array $old_value The old value of the option. * @param array $new_value The new value of the option. @@ -62,8 +62,8 @@ public function check_schema_aggregator_enabled( $old_value, $new_value ): bool return false; } - $option_key = 'enable_schema_aggregator'; - $timestamp_key = 'schema_aggregator_enabled_on'; + $option_key = 'enable_schema_aggregation_endpoint'; + $timestamp_key = 'schema_aggregation_endpoint_enabled_on'; $old_enabled = isset( $old_value[ $option_key ] ) && (bool) $old_value[ $option_key ]; $new_enabled = isset( $new_value[ $option_key ] ) && (bool) $new_value[ $option_key ]; From 12d28b2e79915ef93cafe96e2cd0a26d68719aa2 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 18 Nov 2025 15:27:23 +0100 Subject: [PATCH 100/319] Add the WP-based indexable-fetching --- .../indexable-repository-interface.php | 21 ++++++ .../native-indexable-repository.php | 45 +++++++++++++ .../wordpress-indexable-repository.php | 65 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/indexable-repository-interface.php create mode 100644 src/schema-aggregator/infrastructure/native-indexable-repository.php create mode 100644 src/schema-aggregator/infrastructure/wordpress-indexable-repository.php diff --git a/src/schema-aggregator/infrastructure/indexable-repository-interface.php b/src/schema-aggregator/infrastructure/indexable-repository-interface.php new file mode 100644 index 00000000000..0cc5e81f3bc --- /dev/null +++ b/src/schema-aggregator/infrastructure/indexable-repository-interface.php @@ -0,0 +1,21 @@ + The indexables. + */ + public function get( int $page, int $page_size, string $post_type ): array; +} diff --git a/src/schema-aggregator/infrastructure/native-indexable-repository.php b/src/schema-aggregator/infrastructure/native-indexable-repository.php new file mode 100644 index 00000000000..3aefa34ed63 --- /dev/null +++ b/src/schema-aggregator/infrastructure/native-indexable-repository.php @@ -0,0 +1,45 @@ +indexable_repository = $indexable_repository; + } + + /** + * Retrieves existing public indexables in a paginated manner. + * + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. + * + * @return array The array of public indexables. + */ + public function get( int $page, int $page_size, string $post_type ): array { + return $this->indexable_repository->find_all_public_paginated( + $page, + $page_size, + $post_type + ); + } +} diff --git a/src/schema-aggregator/infrastructure/wordpress-indexable-repository.php b/src/schema-aggregator/infrastructure/wordpress-indexable-repository.php new file mode 100644 index 00000000000..5554fd7efee --- /dev/null +++ b/src/schema-aggregator/infrastructure/wordpress-indexable-repository.php @@ -0,0 +1,65 @@ +indexable_builder = $indexable_builder; + } + + /** + * Builds on-the-fly public indexables in a paginated manner. + * + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. + * + * @return array The array of public indexables. + */ + public function get( int $page, int $page_size, string $post_type ): array { + $query = new WP_Query( + [ + 'post_type' => $post_type, + 'post_status' => 'publish', + 'posts_per_page' => $page_size, + 'paged' => $page, + 'fields' => 'ids', + 'no_found_rows' => false, + ] + ); + + if ( ! $query instanceof WP_Query ) { + return []; + } + + $post_ids = isset( $query->posts ) && \is_array( $query->posts ) ? $query->posts : []; + $public_indexables = []; + foreach ( $post_ids as $post_id ) { + $indexable = $this->indexable_builder->build_for_id_and_type( $post_id, $post_type ); + if ( $indexable !== null && $indexable->is_public ) { + $public_indexables[] = $indexable; + } + } + return $public_indexables; + } +} From 22251e57ef7eaa8d44146e4279793b89fcfdf76d Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 18 Nov 2025 15:27:40 +0100 Subject: [PATCH 101/319] Add the indexable repository factory --- .../indexable-repository-factory.php | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/indexable-repository-factory.php diff --git a/src/schema-aggregator/infrastructure/indexable-repository-factory.php b/src/schema-aggregator/infrastructure/indexable-repository-factory.php new file mode 100644 index 00000000000..34c23e64b2d --- /dev/null +++ b/src/schema-aggregator/infrastructure/indexable-repository-factory.php @@ -0,0 +1,52 @@ +native_repository = $native_repository; + $this->wordpress_repository = $wordpress_repository; + } + + /** + * Gets the appropriate indexable repository based on availability. + * + * @param bool $indexables_available Whether native indexables are available. + * + * @return Indexable_Repository_Interface The selected indexable repository. + */ + public function get_repository( bool $indexables_available ): Indexable_Repository_Interface { + if ( $indexables_available ) { + return $this->native_repository; + } + + return $this->wordpress_repository; + } +} From b70e7eddd6f4e7190f41674163d8f18d66b71b79 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 18 Nov 2025 15:27:50 +0100 Subject: [PATCH 102/319] Use the factory --- .../schema-piece-repository.php | 62 ++++++++----------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 0ee2e9dbccb..61672472399 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -1,19 +1,16 @@ memoizer = $memoizer; - $this->indexable_helper = $indexable_helper; - $this->indexable_repository = $indexable_repository; - $this->adapter = $adapter; - $this->config = $config; - $this->enhancement_factory = $enhancement_factory; + $this->memoizer = $memoizer; + $this->indexable_helper = $indexable_helper; + $this->adapter = $adapter; + $this->config = $config; + $this->enhancement_factory = $enhancement_factory; + $this->indexable_repository_factory = $indexable_repository_factory; } /** @@ -93,14 +90,10 @@ public function __construct( * @return array The aggregated schema. */ public function get( int $page, int $page_size, string $post_type ): array { - $public_indexables = $this->indexable_repository->find_all_public_paginated( - $page, - $page_size, - $post_type - ); - $schema_pieces = []; - - foreach ( $public_indexables as $indexable ) { + $indexable_repository = $this->indexable_repository_factory->get_repository( $this->indexable_helper->should_index_indexables() ); + $indexables = $indexable_repository->get( $page, $page_size, $post_type ); + $schema_pieces = []; + foreach ( $indexables as $indexable ) { if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { continue; } @@ -117,7 +110,6 @@ public function get( int $page, int $page_size, string $post_type ): array { $schema_pieces[] = $schema_piece; } } - return $schema_pieces; } From db8ea716794c2ca66d23fe9c1e5d8bce23bb6fd3 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 19 Nov 2025 08:15:39 +0100 Subject: [PATCH 103/319] Fix comment --- .../infrastructure/schema-piece-repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 61672472399..5347f1a8976 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -8,7 +8,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; /** - * Schema_Piece repository base class. + * The Schema_Piece repository. */ class Schema_Piece_Repository { From 80fc76f28d0f95ffab9b46f600a852eb5b1ccf04 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 19 Nov 2025 13:41:21 +0100 Subject: [PATCH 104/319] fix query --- .../schema_map/schema-map-indexable-repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index bc5a996d6ac..49bed6c0220 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -46,7 +46,7 @@ public function get_indexable_count_per_post_type( array $post_types ): Indexabl ->where_in( 'object_type', [ 'post', 'page' ] ) ->where_raw( '( is_public IS NULL OR is_public = 1 )' ) ->group_by( [ 'object_type', 'object_sub_type' ] ) - ->get_sql(); + ->find_array(); if ( empty( $indexable_raw_value ) ) { return $post_type_counts; From f192a62fd9c98cdc65c1aaf1612b59da0df30af1 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 19 Nov 2025 14:41:47 +0100 Subject: [PATCH 105/319] Fetch only published posts --- src/repositories/indexable-repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repositories/indexable-repository.php b/src/repositories/indexable-repository.php index f3c0eb6d554..45b50fbc83a 100644 --- a/src/repositories/indexable-repository.php +++ b/src/repositories/indexable-repository.php @@ -229,7 +229,7 @@ public function find_all_with_type_and_sub_type( $object_type, $object_sub_type public function find_all_public_paginated( int $page, int $page_size, string $post_type ): array { $offset = ( ( $page - 1 ) * $page_size ); - $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 ) AND ( post_status = "publish" ) ' ); $query->where( 'object_sub_type', $post_type ); $indexables = $query->order_by_asc( 'id' )->limit( $page_size )->offset( $offset )->find_many(); From a258e55229be9d3875c2070b2c98e63db6f3dd0e Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 19 Nov 2025 14:48:20 +0100 Subject: [PATCH 106/319] Move and rename stuff --- .../indexable-repository-factory.php | 16 +++++------ .../indexable-repository-interface.php | 4 +-- .../indexable-repository.php} | 6 ++--- .../wordpress-query-repository.php} | 27 +++++++++++++------ .../schema-piece-repository.php | 1 + 5 files changed, 33 insertions(+), 21 deletions(-) rename src/schema-aggregator/infrastructure/{ => indexable-repository}/indexable-repository-factory.php (63%) rename src/schema-aggregator/infrastructure/{ => indexable-repository}/indexable-repository-interface.php (73%) rename src/schema-aggregator/infrastructure/{native-indexable-repository.php => indexable-repository/indexable-repository.php} (81%) rename src/schema-aggregator/infrastructure/{wordpress-indexable-repository.php => indexable-repository/wordpress-query-repository.php} (57%) diff --git a/src/schema-aggregator/infrastructure/indexable-repository-factory.php b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository-factory.php similarity index 63% rename from src/schema-aggregator/infrastructure/indexable-repository-factory.php rename to src/schema-aggregator/infrastructure/indexable-repository/indexable-repository-factory.php index 34c23e64b2d..cf100163556 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository-factory.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository-factory.php @@ -1,6 +1,6 @@ native_repository = $native_repository; $this->wordpress_repository = $wordpress_repository; diff --git a/src/schema-aggregator/infrastructure/indexable-repository-interface.php b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository-interface.php similarity index 73% rename from src/schema-aggregator/infrastructure/indexable-repository-interface.php rename to src/schema-aggregator/infrastructure/indexable-repository/indexable-repository-interface.php index 0cc5e81f3bc..58c072104a0 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository-interface.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository-interface.php @@ -1,6 +1,6 @@ indexable_builder = $indexable_builder; + public function __construct( Indexable_Builder $indexable_builder, Pure_Indexable_Repository $indexable_repository ) { + $this->indexable_builder = $indexable_builder; + $this->indexable_repository = $indexable_repository; } /** @@ -55,8 +65,9 @@ public function get( int $page, int $page_size, string $post_type ): array { $post_ids = isset( $query->posts ) && \is_array( $query->posts ) ? $query->posts : []; $public_indexables = []; foreach ( $post_ids as $post_id ) { - $indexable = $this->indexable_builder->build_for_id_and_type( $post_id, $post_type ); - if ( $indexable !== null && $indexable->is_public ) { + $indexable = $this->indexable_repository->find_by_id_and_type( $post_id, $post_type, false ); + $indexable = $this->indexable_builder->build_for_id_and_type( $post_id, $post_type, $indexable ); + if ( $indexable !== null && ( $indexable->is_public === true || $indexable->is_public === null ) ) { $public_indexables[] = $indexable; } } diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php index 5347f1a8976..6d3ed585acd 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -6,6 +6,7 @@ use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Schema_Enhancement_Factory; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\Indexable_Repository_Factory; /** * The Schema_Piece repository. From a038eca9f0e0aea0381275d77a8b3e5516f4ec9d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 19 Nov 2025 15:09:37 +0100 Subject: [PATCH 107/319] Add caching --- .../application/cache/manager.php | 4 +-- .../site-schema-json-conditional.php | 0 .../to-aggregate-indexable-collector.php | 0 ...indexables-update-listener-integration.php | 27 +++++++++------ .../site-schema-aggregator-route.php | 3 +- .../site-schema-aggregator-xml-route.php | 33 +++++++++++++++---- 6 files changed, 48 insertions(+), 19 deletions(-) delete mode 100644 src/schema-aggregator/infrastructure/site-schema-json-conditional.php delete mode 100644 src/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php diff --git a/src/schema-aggregator/application/cache/manager.php b/src/schema-aggregator/application/cache/manager.php index f6ef3d61c83..7851ebdde32 100644 --- a/src/schema-aggregator/application/cache/manager.php +++ b/src/schema-aggregator/application/cache/manager.php @@ -18,7 +18,7 @@ class Manager { * * @var string */ - private const CACHE_PREFIX = 'yoast_nlweb_schema'; + private const CACHE_PREFIX = 'yoast_schema_aggregator'; /** * Cache version for invalidation @@ -159,7 +159,7 @@ public function invalidate_all(): bool { return false; } - // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version}. + // Pattern matches: yoast_schema__aggregator_page_{n}_per_{m}_v{version}. $pattern = '_transient_' . self::CACHE_PREFIX . '_page_%'; $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_%'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery diff --git a/src/schema-aggregator/infrastructure/site-schema-json-conditional.php b/src/schema-aggregator/infrastructure/site-schema-json-conditional.php deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php b/src/schema-aggregator/infrastructure/to-aggregate-indexable-collector.php deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php index 5c3ba60d79f..82a20ae8ce4 100644 --- a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -7,8 +7,9 @@ use Yoast\WP\SEO\Models\Indexable; use Yoast\WP\SEO\Repositories\Indexable_Repository; use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Manager; +use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Xml_Manager; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Site_Schema_Json_Conditional; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; /** * This class listens to changes in the indexables and resets the cache. @@ -36,17 +37,26 @@ class Indexables_Update_Listener_Integration implements Integration_Interface { */ private $manager; + /** + * The XML cache manager. + * + * @var Xml_Manager + */ + private $xml_manager; + /** * The constructor. * * @param Indexable_Repository $indexable_repository The indexable repository. * @param Config $config The config object. * @param Manager $manager The manager object. + * @param Xml_Manager $xml_manager The XML cache manager. */ - public function __construct( Indexable_Repository $indexable_repository, Config $config, Manager $manager ) { + public function __construct( Indexable_Repository $indexable_repository, Config $config, Manager $manager, Xml_Manager $xml_manager ) { $this->indexable_repository = $indexable_repository; $this->config = $config; $this->manager = $manager; + $this->xml_manager = $xml_manager; } /** @@ -64,7 +74,7 @@ public function register_hooks() { * @return array */ public static function get_conditionals() { - return [ Site_Schema_Json_Conditional::class ]; + return [ Schema_Aggregator_Conditional::class ]; } /** @@ -78,10 +88,12 @@ public static function get_conditionals() { public function reset_cache( $indexable, $indexable_before ) { if ( $indexable_before->permalink === null ) { $this->manager->invalidate_all(); + $this->xml_manager->invalidate(); return false; } $page = $this->get_page_number( $indexable ); $this->manager->invalidate( $page ); + $this->xml_manager->invalidate(); return true; } @@ -92,18 +104,13 @@ public function reset_cache( $indexable, $indexable_before ) { * This method accounts for deletions by counting the actual position in the result set, * not just using the ID directly. * - * @param Indexable $indexable The indexable to find the page for. - * @param array $post_type_exclude_list The list of excluded post types. + * @param Indexable $indexable The indexable to find the page for. * * @return int The page number (1-indexed) where this indexable appears. */ - public function get_page_number( $indexable, $post_type_exclude_list = [] ) { + public function get_page_number( $indexable ) { $query = $this->indexable_repository->query(); - $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); - if ( $post_type_exclude_list ) { - $query->where_not_in( 'object_sub_type', $post_type_exclude_list ); - } // Count how many records come before this indexable (have a smaller ID). $count_before = $query diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 2251c98d0eb..dfdda8e17c2 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -1,6 +1,6 @@ config = $config; $this->capability_helper = $capability_helper; $this->aggregate_site_schema_map_command_handler = $aggregate_site_schema_map_command_handler; $this->post_type_helper = $post_type_helper; + $this->xml_cache_manager = $xml_cache_manager; } /** @@ -120,12 +134,19 @@ public function get_permission_callback(): bool { * @return WP_REST_Response|WP_Error The success or failure response. */ public function render_schema_xml() { + $cached_xml = $this->xml_cache_manager->get(); + if ( $cached_xml !== null ) { + $xml = $cached_xml; + } + else { - $post_types = $this->post_type_helper->get_indexable_post_types(); + $post_types = $this->post_type_helper->get_indexable_post_types(); - $command = new Aggregate_Site_Schema_Map_Command( $post_types, $this->config->get_per_page() ); - $xml = $this->aggregate_site_schema_map_command_handler->handle( $command ); + $command = new Aggregate_Site_Schema_Map_Command( $post_types, $this->config->get_per_page() ); + $xml = $this->aggregate_site_schema_map_command_handler->handle( $command ); + $this->xml_cache_manager->set( $xml ); + } $response = new WP_REST_Response( $xml, 200 ); $response->header( 'Content-Type', 'application/xml; charset=UTF-8' ); $response->header( 'Cache-Control', 'public, max-age=300' ); From c9562fe0f37704e36db28b927631a892a43ab06d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 19 Nov 2025 15:16:39 +0100 Subject: [PATCH 108/319] Add caching --- .../application/cache/xml-manager.php | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/schema-aggregator/application/cache/xml-manager.php diff --git a/src/schema-aggregator/application/cache/xml-manager.php b/src/schema-aggregator/application/cache/xml-manager.php new file mode 100644 index 00000000000..8cbda64afd8 --- /dev/null +++ b/src/schema-aggregator/application/cache/xml-manager.php @@ -0,0 +1,117 @@ +config = $config; + } + + /** + * Get cached data for a page. + * + * @return array|null Cached data or null. + */ + public function get(): ?array { + try { + if ( ! $this->config->cache_enabled() ) { + return null; + } + + $key = $this->get_cache_key(); + + $data = \get_transient( $key ); + + if ( $data === false ) { + return null; + } + if ( ! \is_array( $data ) ) { + \delete_transient( $key ); + + return null; + } + + return $data; + + } catch ( Exception $e ) { + return null; + } + } + + /** + * Set cache data for a page. + * + * @param string $data Data to cache. + * + * @return bool Success. + */ + public function set( string $data ): bool { + try { + $key = $this->get_cache_key(); + $expiration = $this->config->get_expiration( [ $data ] ); + + return \set_transient( $key, $data, $expiration ); + + } catch ( Exception $e ) { + return false; + } + } + + /** + * Invalidate cache for the xml sitemap. + * + * @return bool Success. + */ + public function invalidate(): bool { + return \delete_transient( $this->get_cache_key() ); + } + + /** + * Generate cache key for page. + * + * @return string Cache key. + */ + private function get_cache_key(): string { + return \sprintf( + '%s_xml_sitemap_v%d', + self::CACHE_PREFIX, + self::CACHE_VERSION + ); + } +} From 43240a9b602b28e9b82d3393a2cac134f51fb381 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 20 Nov 2025 11:08:13 +0100 Subject: [PATCH 109/319] Fix cache manager. --- .../application/cache/xml-manager.php | 6 +++--- ...ite-schema-aggregator-cache-cli-command.php | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/schema-aggregator/application/cache/xml-manager.php b/src/schema-aggregator/application/cache/xml-manager.php index 8cbda64afd8..3e0f72b0f2c 100644 --- a/src/schema-aggregator/application/cache/xml-manager.php +++ b/src/schema-aggregator/application/cache/xml-manager.php @@ -46,9 +46,9 @@ public function __construct( Config $config ) { /** * Get cached data for a page. * - * @return array|null Cached data or null. + * @return string|null Cached data or null. */ - public function get(): ?array { + public function get(): ?string { try { if ( ! $this->config->cache_enabled() ) { return null; @@ -61,7 +61,7 @@ public function get(): ?array { if ( $data === false ) { return null; } - if ( ! \is_array( $data ) ) { + if ( ! \is_string( $data ) ) { \delete_transient( $key ); return null; diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php index a150588cbf6..90a9ebe0b4b 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php @@ -7,6 +7,7 @@ use Yoast\WP\SEO\Commands\Command_Interface; use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Manager; +use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Xml_Manager; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; /** @@ -30,15 +31,24 @@ class Site_Schema_Aggregator_Cache_Cli_Command implements Command_Interface { */ private $cache_manager; + /** + * The XML cache manager instance. + * + * @var Xml_Manager + */ + private $xml_manager; + /** * Site_Schema_Aggregator_Cache_Cli_Command constructor. * - * @param Config $config The config object. - * @param Manager $cache_manager The cache manager. + * @param Config $config The config object. + * @param Manager $cache_manager The cache manager. + * @param Xml_Manager $xml_manager The XML cache manager. */ - public function __construct( Config $config, Manager $cache_manager ) { + public function __construct( Config $config, Manager $cache_manager, Xml_Manager $xml_manager ) { $this->config = $config; $this->cache_manager = $cache_manager; + $this->xml_manager = $xml_manager; } /** @@ -73,12 +83,14 @@ public static function get_namespace() { public function aggregate_site_schema_clear_cache( $args = null, $assoc_args = null ) { if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] >= 1 ) { $this->cache_manager->invalidate( $assoc_args['page'] ); + $this->xml_manager->invalidate(); WP_CLI::log( \__( 'The site schema cache has been cleared successfully.', 'wordpress-seo' ) ); return; } $this->cache_manager->invalidate_all(); + $this->xml_manager->invalidate(); WP_CLI::log( \__( 'All site schema cache has been cleared successfully.', 'wordpress-seo' ) From 9de23a2169b6452bd61db89bc8ce48b5db1337d8 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 20 Nov 2025 11:23:58 +0100 Subject: [PATCH 110/319] CS. --- .../schema_map/schema-map-indexable-repository.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index 49bed6c0220..dc6e8ec69cb 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -101,6 +101,9 @@ public function get_lastmod_for_post_type( string $post_type, int $page, int $pe $indexable_table = Model::get_table_name( 'Indexable' ); // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching + // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery + $lastmod = $wpdb->get_var( $wpdb->prepare( " From c1d5a420d93af1abf6048b45396478dac7ec91f3 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 20 Nov 2025 12:10:19 +0100 Subject: [PATCH 111/319] Tiny indexable change. --- .../indexable-repository/wordpress-query-repository.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php index e635b31eaf0..51449590c18 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php @@ -65,8 +65,7 @@ public function get( int $page, int $page_size, string $post_type ): array { $post_ids = isset( $query->posts ) && \is_array( $query->posts ) ? $query->posts : []; $public_indexables = []; foreach ( $post_ids as $post_id ) { - $indexable = $this->indexable_repository->find_by_id_and_type( $post_id, $post_type, false ); - $indexable = $this->indexable_builder->build_for_id_and_type( $post_id, $post_type, $indexable ); + $indexable = $this->indexable_repository->find_by_id_and_type( $post_id, $post_type ); if ( $indexable !== null && ( $indexable->is_public === true || $indexable->is_public === null ) ) { $public_indexables[] = $indexable; } From 9d28c7055040e103b5899df13bd57d65e0b830fe Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Thu, 20 Nov 2025 12:16:28 +0100 Subject: [PATCH 112/319] Apply suggestion from @pls78 --- .../schema_map/schema-map-indexable-repository.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index dc6e8ec69cb..e01c5d74609 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -44,6 +44,7 @@ public function get_indexable_count_per_post_type( array $post_types ): Indexabl ->select_expr( 'object_sub_type,count(object_sub_type) as count' ) ->where_in( 'object_sub_type', $post_types ) ->where_in( 'object_type', [ 'post', 'page' ] ) + ->where( 'post_status', 'publish' ) ->where_raw( '( is_public IS NULL OR is_public = 1 )' ) ->group_by( [ 'object_type', 'object_sub_type' ] ) ->find_array(); From 7514c14cb6b8854b8a9da022a707d0724fa94b1c Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Thu, 20 Nov 2025 12:16:38 +0100 Subject: [PATCH 113/319] Apply suggestion from @pls78 --- .../schema_map/schema-map-indexable-repository.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index e01c5d74609..5583672dc42 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -71,6 +71,7 @@ public function get_indexable_count_for_post_type( string $post_type ): Indexabl $indexable_raw_value = $this->indexable_repository->query() ->select_expr( 'object_sub_type,count(object_sub_type) as count' ) ->where( 'object_sub_type', $post_type ) + ->where( 'post_status', 'publish' ) ->where_in( 'object_type', [ 'post', 'page' ] ) ->where_raw( '( is_public IS NULL OR is_public = 1 )' ) ->find_one(); From 795615718725999cf585a69f46dc8041b5108656 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 20 Nov 2025 12:17:29 +0100 Subject: [PATCH 114/319] Tiny query change. --- src/repositories/indexable-repository.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/repositories/indexable-repository.php b/src/repositories/indexable-repository.php index 45b50fbc83a..4b151a31800 100644 --- a/src/repositories/indexable-repository.php +++ b/src/repositories/indexable-repository.php @@ -229,8 +229,9 @@ public function find_all_with_type_and_sub_type( $object_type, $object_sub_type public function find_all_public_paginated( int $page, int $page_size, string $post_type ): array { $offset = ( ( $page - 1 ) * $page_size ); - $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 ) AND ( post_status = "publish" ) ' ); + $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 )' ); $query->where( 'object_sub_type', $post_type ); + $query->where( 'post_status', 'publish' ); $indexables = $query->order_by_asc( 'id' )->limit( $page_size )->offset( $offset )->find_many(); From 123017c83ddae6b85b57815b74896a52983ed0c0 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 20 Nov 2025 13:02:18 +0100 Subject: [PATCH 115/319] Move the feature card into the AI tools section --- .../js/src/settings/routes/site-features.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/js/src/settings/routes/site-features.js b/packages/js/src/settings/routes/site-features.js index f414b4124b7..26e9886558c 100644 --- a/packages/js/src/settings/routes/site-features.js +++ b/packages/js/src/settings/routes/site-features.js @@ -243,6 +243,16 @@ const SiteFeatures = () => { + +

{ __( "Provides a single JSON endpoint with all your site’s structured data, enabling NLWeb to power natural language AI queries on your content.", "wordpress-seo" ) }

+ +

@@ -462,16 +472,6 @@ const SiteFeatures = () => {

{ __( "Automatically ping search engines like Bing and Yandex whenever you publish, update or delete a post.", "wordpress-seo" ) }

- -

{ __( "Provides a single JSON endpoint with all your site’s structured data, enabling NLWeb to power natural language AI queries on your content.", "wordpress-seo" ) }

- -
From 130f1448f984aefe3f3062af75c99b0ad36df598 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 20 Nov 2025 13:12:00 +0100 Subject: [PATCH 116/319] Make sure we get just the published posts --- .../schema_map/schema-map-indexable-repository.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index 5583672dc42..adc036bd105 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -115,6 +115,7 @@ public function get_lastmod_for_post_type( string $post_type, int $page, int $pe SELECT indexable_table.object_last_modified FROM {$indexable_table} indexable_table WHERE object_sub_type = %s + AND post_status = 'publish' AND ( is_public IS NULL OR is_public = 1 ) ORDER BY ID LIMIT %d OFFSET %d From a21781f4a9e5a8448ad466c05a314e061228ca34 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 25 Nov 2025 10:50:21 +0100 Subject: [PATCH 117/319] Get rid of not needed meta information. --- .../aggregate-site-schema-command-handler.php | 3 +-- .../schema-aggregator-response-composer.php | 25 +------------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index e5457ac8cf3..4279caded52 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -64,7 +64,6 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { ); $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); - $schema = $this->schema_response_composer->compose( $aggregated_schema_pieces, $command->get_page_controls()->get_post_type(), $command->get_page_controls()->get_page(), $command->get_page_controls()->get_page_size() ); - return $schema; + return $this->schema_response_composer->compose( $aggregated_schema_pieces ); } } diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php index fe9d9c8a347..7fcdbab3169 100644 --- a/src/schema-aggregator/application/schema-aggregator-response-composer.php +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -2,7 +2,6 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; -use Yoast\WP\SEO\Schema_Aggregator\Application\Meta\Response_Meta_Provider; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; /** @@ -12,35 +11,14 @@ */ class Schema_Aggregator_Response_Composer { - /** - * The meta provider. - * - * @var Response_Meta_Provider - */ - private $meta_provider; - - /** - * Schema_Aggregator_Response_Composer constructor. - * - * @param Response_Meta_Provider $meta_provider The meta provider. - */ - public function __construct( Response_Meta_Provider $meta_provider ) { - $this->meta_provider = $meta_provider; - } - /** * Composes the final schema response. * * @param array $schema_pieces The schema pieces to include in the response. - * @param string $post_type The post type being queried. - * @param int $page The page number (1-based). - * @param int $page_size The number of items per page. * * @return array The composed schema response. */ - public function compose( array $schema_pieces, string $post_type, int $page, int $page_size ): array { - - $meta = $this->meta_provider->get_metadata( $post_type, $page, $page_size ); + public function compose( array $schema_pieces ): array { return [ '@context' => 'https://schema.org', '@graph' => \array_map( @@ -49,7 +27,6 @@ static function ( $piece ) { }, \array_values( $schema_pieces ) ), - 'meta' => $meta, ]; } } From 0ed827f8a2c50ef21943283841ac7b6f3df93062 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 25 Nov 2025 10:52:49 +0100 Subject: [PATCH 118/319] Implement wordpress fallback for non indexable sites --- ...regate-site-schema-map-command-handler.php | 37 ++++-- .../schema_map/schema-map-builder.php | 32 ++--- .../domain/indexable-count-collection.php | 7 ++ .../schema-map-indexable-repository.php | 4 +- .../schema-map-repository-factory.php | 52 ++++++++ .../schema-map-repository-interface.php | 43 +++++++ .../schema-map-wordpress-repository.php | 112 ++++++++++++++++++ 7 files changed, 251 insertions(+), 36 deletions(-) create mode 100644 src/schema-aggregator/infrastructure/schema_map/schema-map-repository-factory.php create mode 100644 src/schema-aggregator/infrastructure/schema_map/schema-map-repository-interface.php create mode 100644 src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php index 34462f39496..5aa0a5f6e3f 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php @@ -2,9 +2,10 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; +use Yoast\WP\SEO\Helpers\Indexable_Helper; use Yoast\WP\SEO\Schema_Aggregator\Application\Schema_Map\Schema_Map_Builder; use Yoast\WP\SEO\Schema_Aggregator\Application\Schema_Map\Schema_Map_Xml_Renderer; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Indexable_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Repository_Factory; /** * Class that handles the command to aggregate site schema map. @@ -14,11 +15,11 @@ class Aggregate_Site_Schema_Map_Command_Handler { /** - * The schema map indexable repository. + * The schema map factory. * - * @var Schema_Map_Indexable_Repository + * @var Schema_Map_Repository_Factory */ - private $schema_map_indexable_repository; + private $schema_map_repository_factory; /** * The schema map builder. @@ -34,17 +35,26 @@ class Aggregate_Site_Schema_Map_Command_Handler { */ private $schema_map_xml_renderer; + /** + * The indexable helper. + * + * @var Indexable_Helper + */ + private $indexable_helper; + /** * Aggregate_Site_Schema_Map_Command_Handler constructor. * - * @param Schema_Map_Indexable_Repository $schema_map_indexable_repository The schema map indexable repository. - * @param Schema_Map_Builder $schema_map_builder The schema map builder. - * @param Schema_Map_Xml_Renderer $schema_map_xml_renderer The schema map XML renderer. + * @param Schema_Map_Repository_Factory $schema_map_repository_factory The schema map factory. + * @param Schema_Map_Builder $schema_map_builder The schema map builder. + * @param Schema_Map_Xml_Renderer $schema_map_xml_renderer The schema map XML renderer. + * @param Indexable_Helper $indexable_helper The indexable helper. */ - public function __construct( Schema_Map_Indexable_Repository $schema_map_indexable_repository, Schema_Map_Builder $schema_map_builder, Schema_Map_Xml_Renderer $schema_map_xml_renderer ) { - $this->schema_map_indexable_repository = $schema_map_indexable_repository; - $this->schema_map_builder = $schema_map_builder; - $this->schema_map_xml_renderer = $schema_map_xml_renderer; + public function __construct( Schema_Map_Repository_Factory $schema_map_repository_factory, Schema_Map_Builder $schema_map_builder, Schema_Map_Xml_Renderer $schema_map_xml_renderer, Indexable_Helper $indexable_helper ) { + $this->schema_map_repository_factory = $schema_map_repository_factory; + $this->schema_map_builder = $schema_map_builder; + $this->schema_map_xml_renderer = $schema_map_xml_renderer; + $this->indexable_helper = $indexable_helper; } /** @@ -56,11 +66,12 @@ public function __construct( Schema_Map_Indexable_Repository $schema_map_indexab */ public function handle( Aggregate_Site_Schema_Map_Command $command ): string { - $indexable_counts = $this->schema_map_indexable_repository->get_indexable_count_per_post_type( $command->get_post_types() ); + $schema_map_indexable_repository = $this->schema_map_repository_factory->get_repository( $this->indexable_helper->should_index_indexables() ); + $indexable_counts = $schema_map_indexable_repository->get_indexable_count_per_post_type( $command->get_post_types() ); $threshold = $command->get_schema_map_threshold(); - $schema_map = $this->schema_map_builder->build( $indexable_counts, $threshold ); + $schema_map = $this->schema_map_builder->build( $schema_map_indexable_repository, $indexable_counts, $threshold ); return $this->schema_map_xml_renderer->render( $schema_map ); } diff --git a/src/schema-aggregator/application/schema_map/schema-map-builder.php b/src/schema-aggregator/application/schema_map/schema-map-builder.php index 4dce60a9ace..c828181f1d3 100644 --- a/src/schema-aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema-aggregator/application/schema_map/schema-map-builder.php @@ -4,38 +4,28 @@ use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Indexable_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\Schema_Map_Repository_Interface; /** * Builds the schema map. */ class Schema_Map_Builder { - /** - * The indexable repository. - * - * @var Schema_Map_Indexable_Repository - */ - private $indexable_repository; - - /** - * Schema_Map_Builder constructor. - * - * @param Schema_Map_Indexable_Repository $indexable_repository The indexable repository. - */ - public function __construct( Schema_Map_Indexable_Repository $indexable_repository ) { - $this->indexable_repository = $indexable_repository; - } - /** * Builds the schema map based on indexable counts and threshold. * - * @param Indexable_Count_Collection $indexable_counts The indexable counts per post type. - * @param int $threshold The threshold for items per page. + * @param Schema_Map_Repository_Interface $schema_map_repository The schema map repository. + * @param Indexable_Count_Collection $indexable_counts The indexable counts per post type. + * @param int $threshold The threshold for items per page. * * @return array> The schema map. */ - public function build( Indexable_Count_Collection $indexable_counts, int $threshold ): array { + public function build( + Schema_Map_Repository_Interface $schema_map_repository, + Indexable_Count_Collection $indexable_counts, + int $threshold + ): array { + $schema_map = []; foreach ( $indexable_counts->get_indexable_counts() as $indexable_count ) { $post_type = $indexable_count->get_post_type(); @@ -54,7 +44,7 @@ public function build( Indexable_Count_Collection $indexable_counts, int $thresh $url = $this->get_rest_route( $post_type, $page ); } - $lastmod = $this->indexable_repository->get_lastmod_for_post_type( $post_type, $page, $threshold ); + $lastmod = $schema_map_repository->get_lastmod_for_post_type( $post_type, $page, $threshold ); $page_count = ( $page === $total_pages ) ? ( $count - ( ( $page - 1 ) * $threshold ) ) : $threshold; diff --git a/src/schema-aggregator/domain/indexable-count-collection.php b/src/schema-aggregator/domain/indexable-count-collection.php index 49bf27eb894..aa03d10f045 100644 --- a/src/schema-aggregator/domain/indexable-count-collection.php +++ b/src/schema-aggregator/domain/indexable-count-collection.php @@ -14,6 +14,13 @@ class Indexable_Count_Collection { */ private array $indexable_counts; + /** + * Constructor. + */ + public function __construct() { + $this->indexable_counts = []; + } + /** * Adds an Indexable_Count object to the collection. * diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index adc036bd105..d27550f2ef8 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -13,7 +13,7 @@ * * Maps indexable repository queries for schema map needs. */ -class Schema_Map_Indexable_Repository { +class Schema_Map_Indexable_Repository implements Schema_Map_Repository_Interface { /** * The indexable repository. @@ -128,7 +128,7 @@ public function get_lastmod_for_post_type( string $post_type, int $page, int $pe ); // Convert to ISO 8601 format or use current time if no posts. if ( $lastmod && ! empty( $lastmod ) ) { - return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod->object_last_modified ) ); + return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod ) ); } return $fallback; diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-repository-factory.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-repository-factory.php new file mode 100644 index 00000000000..0822cd7e03a --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-repository-factory.php @@ -0,0 +1,52 @@ +native_repository = $native_repository; + $this->wordpress_repository = $wordpress_repository; + } + + /** + * Gets the appropriate indexable repository based on availability. + * + * @param bool $indexables_available Whether native indexables are available. + * + * @return Schema_Map_Repository_Interface The selected indexable repository. + */ + public function get_repository( bool $indexables_available ): Schema_Map_Repository_Interface { + if ( $indexables_available ) { + return $this->native_repository; + } + + return $this->wordpress_repository; + } +} diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-repository-interface.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-repository-interface.php new file mode 100644 index 00000000000..15e1c831954 --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-repository-interface.php @@ -0,0 +1,43 @@ + $post_types The post types to get the indexable count for. + * + * @return Indexable_Count_Collection The indexable count per post type. + */ + public function get_indexable_count_per_post_type( array $post_types ): Indexable_Count_Collection; + + /** + * Gets the indexable count for a single post type. + * + * @param string $post_type The post type to get the indexable count for. + * + * @return Indexable_Count The indexable count for the post type. + */ + public function get_indexable_count_for_post_type( string $post_type ): Indexable_Count; + + /** + * Get lastmod timestamp for a post type and page range + * + * Returns the latest post_modified_gmt timestamp for posts in the given range. + * Used for schemamap index to enable selective updates. + * + * @param string $post_type Post type slug. + * @param int $page Page number (1-indexed). + * @param int $per_page Items per page. + * @return string ISO 8601 timestamp (e.g., "2025-10-21T14:23:17Z"). + */ + public function get_lastmod_for_post_type( string $post_type, int $page, int $per_page ): string; +} diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php new file mode 100644 index 00000000000..e62afdb9c78 --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php @@ -0,0 +1,112 @@ +indexable_repository = $indexable_repository; + } + + /** + * Gets the indexable count per post type. + * + * @param array $post_types The post types to get the indexable count for. + * + * @return Indexable_Count_Collection The indexable count per post type. + */ + public function get_indexable_count_per_post_type( array $post_types ): Indexable_Count_Collection { + $post_type_counts = new Indexable_Count_Collection(); + foreach ( $post_types as $post_type ) { + $count = (int) \wp_count_posts( $post_type )->publish; + $post_type_counts->add_indexable_count( new Indexable_Count( $post_type, $count ) ); + } + + return $post_type_counts; + } + + /** + * Gets the indexable count for a single post type. + * + * @param string $post_type The post type to get the indexable count for. + * + * @return Indexable_Count The indexable count for the post type. + */ + public function get_indexable_count_for_post_type( string $post_type ): Indexable_Count { + + $count = (int) \wp_count_posts( $post_type )->publish; + if ( empty( $count ) ) { + return new Indexable_Count( $post_type, 0 ); + } + + return new Indexable_Count( $post_type, $count ); + } + + /** + * Get lastmod timestamp for a post type and page range + * + * Returns the latest post_modified_gmt timestamp for posts in the given range. + * Used for schemamap index to enable selective updates. + * + * @param string $post_type Post type slug. + * @param int $page Page number (1-indexed). + * @param int $per_page Items per page. + * @return string ISO 8601 timestamp (e.g., "2025-10-21T14:23:17Z"). + */ + public function get_lastmod_for_post_type( string $post_type, int $page, int $per_page ): string { + global $wpdb; + $fallback = \gmdate( 'Y-m-d\TH:i:s\Z' ); + + try { + $offset = ( ( $page - 1 ) * $per_page ); + // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches. + // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: Most performant way. + $lastmod = $wpdb->get_var( + $wpdb->prepare( + "SELECT MAX(post_modified_gmt) + FROM ( + SELECT post_modified_gmt + FROM {$wpdb->posts} + WHERE post_type = %s + AND post_status = 'publish' + ORDER BY ID + LIMIT %d OFFSET %d + ) AS posts_range", + $post_type, + $per_page, + $offset + ) + ); + // phpcs:enable + // Convert to ISO 8601 format or use current time if no posts. + if ( $lastmod && ! empty( $lastmod ) ) { + return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( $lastmod ) ); + } + return $fallback; + } catch ( Exception $e ) { + return $fallback; + } + } +} From b03ff5b95630e4623ceaec175863727f97562236 Mon Sep 17 00:00:00 2001 From: Thijs van der Heijden Date: Tue, 25 Nov 2025 14:51:39 +0100 Subject: [PATCH 119/319] Update src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php Co-authored-by: Paolo L. Scala <68744851+pls78@users.noreply.github.com> --- .../cache/indexables-update-listener-integration.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php index 82a20ae8ce4..b7883c1a372 100644 --- a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -111,6 +111,7 @@ public function reset_cache( $indexable, $indexable_before ) { public function get_page_number( $indexable ) { $query = $this->indexable_repository->query(); $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + $query->where( 'post_status', 'publish' ); // Count how many records come before this indexable (have a smaller ID). $count_before = $query From 301076176c84f460ae1218a5a2a817365a2e6c5e Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 27 Nov 2025 12:11:24 +0100 Subject: [PATCH 120/319] Allow for woo schema to be added to our graph. --- .../aggregate-site-schema-command-handler.php | 2 +- .../infrastructure/aggregator-config.php | 2 +- .../schema-piece-repository.php | 26 +++++- .../woo-schema-piece-repository.php | 82 +++++++++++++++++++ 4 files changed, 107 insertions(+), 5 deletions(-) rename src/schema-aggregator/infrastructure/{ => schema-pieces}/schema-piece-repository.php (81%) create mode 100644 src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index e5457ac8cf3..f2c00247fca 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -3,7 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Piece_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Schema_Piece_Repository; /** * Class that handles the Aggregate_Site_Schema_Command. diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index 9c6be78f979..c07e7255f9d 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -27,6 +27,7 @@ class Aggregator_Config { 'Recipe', 'Article', 'Product', + 'ProductGroup', 'Event', 'Person', 'Organization', @@ -70,7 +71,6 @@ public function get_allowed_post_types(): array { $default_post_types = self::DEFAULT_POST_TYPES; // Only include 'product' if Yoast WooCommerce SEO extension is active. - if ( $this->woocommerce_conditional->is_met() ) { $default_post_types[] = 'product'; } diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php similarity index 81% rename from src/schema-aggregator/infrastructure/schema-piece-repository.php rename to src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index 6d3ed585acd..4238e563ac4 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -1,12 +1,14 @@ memoizer = $memoizer; $this->indexable_helper = $indexable_helper; @@ -79,6 +90,7 @@ public function __construct( $this->config = $config; $this->enhancement_factory = $enhancement_factory; $this->indexable_repository_factory = $indexable_repository_factory; + $this->woo_schema_piece_repository = $woo_schema_piece_repository; } /** @@ -102,6 +114,14 @@ public function get( int $page, int $page_size, string $post_type ): array { $context = $this->memoizer->get( $indexable, $page_type ); $context_array = $this->adapter->meta_tags_context_to_array( $context ); $pieces_data = $context_array['@graph']; + + if ( $post_type === 'product' ) { + $product_schema = $this->woo_schema_piece_repository->collect_product_schema( $indexable->object_id ); + if ( $product_schema !== null ) { + $pieces_data[] = $product_schema; + } + } + foreach ( $pieces_data as $piece_data ) { $schema_piece = new Schema_Piece( $piece_data, $piece_data['@type'] ); $enhancer = $this->enhancement_factory->get_enhancer( $this->get_all_schema_types( $context_array['@graph'] ) ); diff --git a/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php new file mode 100644 index 00000000000..ccf049bc199 --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php @@ -0,0 +1,82 @@ +woocommerce_conditional = $woocommerce_conditional; + } + + /** + * Collect Product schema for WooCommerce products. + * + * ## How it Works + * + * Hooks into 'wpseo_schema_product' filter to capture enriched Product schema + * Triggers WooCommerce's schema generation via WC_Structured_Data + * Returns the captured Product entity + * + * @param int $post_id Product post ID. + * + * @return array>|null Product schema entity or null if unavailable. + */ + public function collect_product_schema( int $post_id ): ?array { + + if ( ! $this->woocommerce_conditional->is_met() ) { + return null; + } + + try { + $product = \wc_get_product( $post_id ); + + if ( ! $product || ! \is_a( $product, 'WC_Product' ) ) { + return null; + } + + $captured_schema = null; + + $capture_filter = static function ( $schema_data ) use ( &$captured_schema ) { + $captured_schema = $schema_data; + + return $schema_data; + }; + + \add_filter( 'wpseo_schema_product', $capture_filter, 999 ); + + // This will trigger the woocommerce_structured_data_product filter. + // which Yoast WooCommerce SEO hooks into to enrich the schema. + // which then triggers our wpseo_schema_product filter above. + $structured_data = new WC_Structured_Data(); + $structured_data->generate_product_data( $product ); + + \remove_filter( 'wpseo_schema_product', $capture_filter, 999 ); + + if ( ! \is_array( $captured_schema ) ) { + return null; + } + + return $captured_schema; + } catch ( Exception $e ) { + return null; + } + } +} From ad1d2b7708f9aaa3b67d2f61fbabff021be1c66d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 27 Nov 2025 12:15:10 +0100 Subject: [PATCH 121/319] Revert "Allow for woo schema to be added to our graph." This reverts commit 301076176c84f460ae1218a5a2a817365a2e6c5e. --- .../aggregate-site-schema-command-handler.php | 2 +- .../infrastructure/aggregator-config.php | 2 +- .../schema-piece-repository.php | 26 +----- .../woo-schema-piece-repository.php | 82 ------------------- 4 files changed, 5 insertions(+), 107 deletions(-) rename src/schema-aggregator/infrastructure/{schema-pieces => }/schema-piece-repository.php (81%) delete mode 100644 src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index f2c00247fca..e5457ac8cf3 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -3,7 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Schema_Piece_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Piece_Repository; /** * Class that handles the Aggregate_Site_Schema_Command. diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index c07e7255f9d..9c6be78f979 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -27,7 +27,6 @@ class Aggregator_Config { 'Recipe', 'Article', 'Product', - 'ProductGroup', 'Event', 'Person', 'Organization', @@ -71,6 +70,7 @@ public function get_allowed_post_types(): array { $default_post_types = self::DEFAULT_POST_TYPES; // Only include 'product' if Yoast WooCommerce SEO extension is active. + if ( $this->woocommerce_conditional->is_met() ) { $default_post_types[] = 'product'; } diff --git a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-piece-repository.php similarity index 81% rename from src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php rename to src/schema-aggregator/infrastructure/schema-piece-repository.php index 4238e563ac4..6d3ed585acd 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-piece-repository.php @@ -1,14 +1,12 @@ memoizer = $memoizer; $this->indexable_helper = $indexable_helper; @@ -90,7 +79,6 @@ public function __construct( $this->config = $config; $this->enhancement_factory = $enhancement_factory; $this->indexable_repository_factory = $indexable_repository_factory; - $this->woo_schema_piece_repository = $woo_schema_piece_repository; } /** @@ -114,14 +102,6 @@ public function get( int $page, int $page_size, string $post_type ): array { $context = $this->memoizer->get( $indexable, $page_type ); $context_array = $this->adapter->meta_tags_context_to_array( $context ); $pieces_data = $context_array['@graph']; - - if ( $post_type === 'product' ) { - $product_schema = $this->woo_schema_piece_repository->collect_product_schema( $indexable->object_id ); - if ( $product_schema !== null ) { - $pieces_data[] = $product_schema; - } - } - foreach ( $pieces_data as $piece_data ) { $schema_piece = new Schema_Piece( $piece_data, $piece_data['@type'] ); $enhancer = $this->enhancement_factory->get_enhancer( $this->get_all_schema_types( $context_array['@graph'] ) ); diff --git a/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php deleted file mode 100644 index ccf049bc199..00000000000 --- a/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php +++ /dev/null @@ -1,82 +0,0 @@ -woocommerce_conditional = $woocommerce_conditional; - } - - /** - * Collect Product schema for WooCommerce products. - * - * ## How it Works - * - * Hooks into 'wpseo_schema_product' filter to capture enriched Product schema - * Triggers WooCommerce's schema generation via WC_Structured_Data - * Returns the captured Product entity - * - * @param int $post_id Product post ID. - * - * @return array>|null Product schema entity or null if unavailable. - */ - public function collect_product_schema( int $post_id ): ?array { - - if ( ! $this->woocommerce_conditional->is_met() ) { - return null; - } - - try { - $product = \wc_get_product( $post_id ); - - if ( ! $product || ! \is_a( $product, 'WC_Product' ) ) { - return null; - } - - $captured_schema = null; - - $capture_filter = static function ( $schema_data ) use ( &$captured_schema ) { - $captured_schema = $schema_data; - - return $schema_data; - }; - - \add_filter( 'wpseo_schema_product', $capture_filter, 999 ); - - // This will trigger the woocommerce_structured_data_product filter. - // which Yoast WooCommerce SEO hooks into to enrich the schema. - // which then triggers our wpseo_schema_product filter above. - $structured_data = new WC_Structured_Data(); - $structured_data->generate_product_data( $product ); - - \remove_filter( 'wpseo_schema_product', $capture_filter, 999 ); - - if ( ! \is_array( $captured_schema ) ) { - return null; - } - - return $captured_schema; - } catch ( Exception $e ) { - return null; - } - } -} From ed212d660a5592e22eb3cd50a5cb00563d91112d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 27 Nov 2025 12:11:24 +0100 Subject: [PATCH 122/319] Allow for woo schema to be added to our graph. --- .../aggregate-site-schema-command-handler.php | 2 +- .../infrastructure/aggregator-config.php | 2 +- .../schema-piece-repository.php | 26 +++++- .../woo-schema-piece-repository.php | 82 +++++++++++++++++++ 4 files changed, 107 insertions(+), 5 deletions(-) rename src/schema-aggregator/infrastructure/{ => schema-pieces}/schema-piece-repository.php (81%) create mode 100644 src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index e5457ac8cf3..f2c00247fca 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -3,7 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Piece_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Schema_Piece_Repository; /** * Class that handles the Aggregate_Site_Schema_Command. diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index 9c6be78f979..c07e7255f9d 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -27,6 +27,7 @@ class Aggregator_Config { 'Recipe', 'Article', 'Product', + 'ProductGroup', 'Event', 'Person', 'Organization', @@ -70,7 +71,6 @@ public function get_allowed_post_types(): array { $default_post_types = self::DEFAULT_POST_TYPES; // Only include 'product' if Yoast WooCommerce SEO extension is active. - if ( $this->woocommerce_conditional->is_met() ) { $default_post_types[] = 'product'; } diff --git a/src/schema-aggregator/infrastructure/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php similarity index 81% rename from src/schema-aggregator/infrastructure/schema-piece-repository.php rename to src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index 6d3ed585acd..4238e563ac4 100644 --- a/src/schema-aggregator/infrastructure/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -1,12 +1,14 @@ memoizer = $memoizer; $this->indexable_helper = $indexable_helper; @@ -79,6 +90,7 @@ public function __construct( $this->config = $config; $this->enhancement_factory = $enhancement_factory; $this->indexable_repository_factory = $indexable_repository_factory; + $this->woo_schema_piece_repository = $woo_schema_piece_repository; } /** @@ -102,6 +114,14 @@ public function get( int $page, int $page_size, string $post_type ): array { $context = $this->memoizer->get( $indexable, $page_type ); $context_array = $this->adapter->meta_tags_context_to_array( $context ); $pieces_data = $context_array['@graph']; + + if ( $post_type === 'product' ) { + $product_schema = $this->woo_schema_piece_repository->collect_product_schema( $indexable->object_id ); + if ( $product_schema !== null ) { + $pieces_data[] = $product_schema; + } + } + foreach ( $pieces_data as $piece_data ) { $schema_piece = new Schema_Piece( $piece_data, $piece_data['@type'] ); $enhancer = $this->enhancement_factory->get_enhancer( $this->get_all_schema_types( $context_array['@graph'] ) ); diff --git a/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php new file mode 100644 index 00000000000..ccf049bc199 --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php @@ -0,0 +1,82 @@ +woocommerce_conditional = $woocommerce_conditional; + } + + /** + * Collect Product schema for WooCommerce products. + * + * ## How it Works + * + * Hooks into 'wpseo_schema_product' filter to capture enriched Product schema + * Triggers WooCommerce's schema generation via WC_Structured_Data + * Returns the captured Product entity + * + * @param int $post_id Product post ID. + * + * @return array>|null Product schema entity or null if unavailable. + */ + public function collect_product_schema( int $post_id ): ?array { + + if ( ! $this->woocommerce_conditional->is_met() ) { + return null; + } + + try { + $product = \wc_get_product( $post_id ); + + if ( ! $product || ! \is_a( $product, 'WC_Product' ) ) { + return null; + } + + $captured_schema = null; + + $capture_filter = static function ( $schema_data ) use ( &$captured_schema ) { + $captured_schema = $schema_data; + + return $schema_data; + }; + + \add_filter( 'wpseo_schema_product', $capture_filter, 999 ); + + // This will trigger the woocommerce_structured_data_product filter. + // which Yoast WooCommerce SEO hooks into to enrich the schema. + // which then triggers our wpseo_schema_product filter above. + $structured_data = new WC_Structured_Data(); + $structured_data->generate_product_data( $product ); + + \remove_filter( 'wpseo_schema_product', $capture_filter, 999 ); + + if ( ! \is_array( $captured_schema ) ) { + return null; + } + + return $captured_schema; + } catch ( Exception $e ) { + return null; + } + } +} From 26d091976a3f93bbec7bc119d399aa1f47bd5bbc Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:35:39 +0100 Subject: [PATCH 123/319] The interface for the map loader strategy --- .../map-loader-interface.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/elements-context-map/map-loader-interface.php diff --git a/src/schema-aggregator/infrastructure/elements-context-map/map-loader-interface.php b/src/schema-aggregator/infrastructure/elements-context-map/map-loader-interface.php new file mode 100644 index 00000000000..ed5bb725bb0 --- /dev/null +++ b/src/schema-aggregator/infrastructure/elements-context-map/map-loader-interface.php @@ -0,0 +1,16 @@ +> The elements context map. + */ + public function load(): array; +} From 1dab6eadd42a19119350e1297faa0ad8a4e479d9 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:35:56 +0100 Subject: [PATCH 124/319] The default elements-context map array --- .../default-elements-context-map.php | 1362 +++++++++++++++++ 1 file changed, 1362 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php diff --git a/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php b/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php new file mode 100644 index 00000000000..6e3e7cbee6e --- /dev/null +++ b/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php @@ -0,0 +1,1362 @@ + [ + 'Action', + 'AcceptAction', + 'AchieveAction', + 'ActivateAction', + 'AddAction', + 'AgreeAction', + 'AllocateAction', + 'AppendAction', + 'ApplyAction', + 'ArriveAction', + 'AskAction', + 'AssessAction', + 'AssignAction', + 'AuthorizeAction', + 'BefriendAction', + 'BookmarkAction', + 'BorrowAction', + 'BuyAction', + 'CancelAction', + 'CheckAction', + 'CheckInAction', + 'CheckOutAction', + 'ChooseAction', + 'ClaimAction', + 'CommentAction', + 'CommunicateAction', + 'ConfirmAction', + 'ConsumeAction', + 'ControlAction', + 'CookAction', + 'CreateAction', + 'DeactivateAction', + 'DeleteAction', + 'DepartAction', + 'DisagreeAction', + 'DiscoverAction', + 'DislikeAction', + 'DonateAction', + 'DownloadAction', + 'DrawAction', + 'DrinkAction', + 'EatAction', + 'EditAction', + 'EndorseAction', + 'ExerciseAction', + 'FilmAction', + 'FindAction', + 'FollowAction', + 'GiveAction', + 'IgnoreAction', + 'InformAction', + 'InsertAction', + 'InstallAction', + 'InteractAction', + 'InviteAction', + 'JoinAction', + 'LeaveAction', + 'LendAction', + 'LikeAction', + 'ListenAction', + 'LoseAction', + 'MarryAction', + 'MoneyTransfer', + 'MoveAction', + 'OrderAction', + 'OrganizeAction', + 'PaintAction', + 'PayAction', + 'PerformAction', + 'PhotographAction', + 'PlanAction', + 'PlayAction', + 'PreOrderAction', + 'PrependAction', + 'QuoteAction', + 'ReactAction', + 'ReadAction', + 'ReceiveAction', + 'RegisterAction', + 'RejectAction', + 'RentAction', + 'ReplaceAction', + 'ReplyAction', + 'ReportAction', + 'ReserveAction', + 'ResumeAction', + 'ReturnAction', + 'ReviewAction', + 'RsvpAction', + 'ScheduleAction', + 'SearchAction', + 'SeekToAction', + 'SellAction', + 'SendAction', + 'ShareAction', + 'SubscribeAction', + 'SuspendAction', + 'TakeAction', + 'TieAction', + 'TipAction', + 'TrackAction', + 'TradeAction', + 'TransferAction', + 'TravelAction', + 'UnRegisterAction', + 'UpdateAction', + 'UseAction', + 'ViewAction', + 'VoteAction', + 'WantAction', + 'WatchAction', + 'WearAction', + 'WinAction', + 'WriteAction', + ], + 'commerce' => [ + 'Product', + 'Car', + 'Drug', + 'DietarySupplement', + 'IndividualProduct', + 'Motorcycle', + 'ProductGroup', + 'ProductModel', + 'SomeProducts', + 'Vehicle', + 'BusOrCoach', + 'MotorizedBicycle', + 'Offer', + 'AggregateOffer', + 'Demand', + 'Order', + 'OrderItem', + 'Invoice', + 'PriceSpecification', + 'CompoundPriceSpecification', + 'DeliveryChargeSpecification', + 'PaymentChargeSpecification', + 'UnitPriceSpecification', + 'ShippingConditions', + 'ShippingDeliveryTime', + 'ShippingRateSettings', + 'ShippingService', + 'MerchantReturnPolicy', + 'MerchantReturnPolicySeasonalOverride', + 'OfferShippingDetails', + 'OfferCatalog', + 'ParcelDelivery', + 'FinancialProduct', + 'BankAccount', + 'CurrencyConversionService', + 'DepositAccount', + 'InvestmentFund', + 'InvestmentOrDeposit', + 'LoanOrCredit', + 'MortgageLoan', + 'PaymentCard', + 'CreditCard', + 'PaymentService', + ], + 'content' => [ + 'CreativeWork', + 'AmpStory', + 'AnalysisNewsArticle', + 'Answer', + 'ArchiveComponent', + 'Article', + 'AskPublicNewsArticle', + 'Atlas', + 'Audiobook', + 'BackgroundNewsArticle', + 'Blog', + 'BlogPosting', + 'Book', + 'BookSeries', + 'Certification', + 'Chapter', + 'Claim', + 'Clip', + 'Code', + 'Collection', + 'ComicCoverArt', + 'ComicIssue', + 'ComicSeries', + 'ComicStory', + 'Comment', + 'Conversation', + 'CorrectionComment', + 'Course', + 'CoverArt', + 'CreativeWorkSeason', + 'CreativeWorkSeries', + 'CriticReview', + 'DataCatalog', + 'DataDownload', + 'Dataset', + 'DefinedTermSet', + 'Diet', + 'DigitalDocument', + 'DiscussionForumPosting', + 'Drawing', + 'EducationalOccupationalCredential', + 'EmailMessage', + 'Episode', + 'ExercisePlan', + 'FAQPage', + 'Game', + 'Guide', + 'HowTo', + 'HowToDirection', + 'HowToSection', + 'HowToStep', + 'HowToTip', + 'HyperToc', + 'HyperTocEntry', + 'ImageGallery', + 'Legislation', + 'LegislationObject', + 'LiveBlogPosting', + 'Manuscript', + 'Map', + 'MathSolver', + 'MediaGallery', + 'MediaObject', + 'MediaReview', + 'MediaReviewItem', + 'Menu', + 'MenuSection', + 'Message', + 'Movie', + 'MovieClip', + 'MovieSeries', + 'MusicAlbum', + 'MusicComposition', + 'MusicPlaylist', + 'MusicRecording', + 'MusicRelease', + 'MusicVideoObject', + 'NewsArticle', + 'Newspaper', + 'NoteDigitalDocument', + 'OpinionNewsArticle', + 'Painting', + 'Periodical', + 'Photograph', + 'Play', + 'Poster', + 'PresentationDigitalDocument', + 'ProductCollection', + 'PublicationIssue', + 'PublicationVolume', + 'Question', + 'Quiz', + 'Quotation', + 'RadioClip', + 'RadioEpisode', + 'RadioSeason', + 'RadioSeries', + 'Recipe', + 'Recommendation', + 'Report', + 'ReportageNewsArticle', + 'Review', + 'ReviewNewsArticle', + 'SatiricalArticle', + 'ScholarlyArticle', + 'Sculpture', + 'Season', + 'SheetMusic', + 'ShortStory', + 'SocialMediaPosting', + 'SoftwareApplication', + 'SoftwareSourceCode', + 'SpecialAnnouncement', + 'SpreadsheetDigitalDocument', + 'Statement', + 'TechArticle', + 'TextDigitalDocument', + 'Thesis', + 'TVClip', + 'TVEpisode', + 'TVSeason', + 'TVSeries', + 'UserBlocks', + 'UserCheckins', + 'UserComments', + 'UserDownloads', + 'UserInteraction', + 'UserLikes', + 'UserPageVisits', + 'UserPlays', + 'UserPlusOnes', + 'UserTweets', + 'VideoClip', + 'VideoGallery', + 'VideoGame', + 'VideoGameClip', + 'VideoGameSeries', + 'VideoObject', + 'VideoObjectSnapshot', + 'VisualArtwork', + 'WebContent', + '3DModel', + 'AudioObject', + 'AudioObjectSnapshot', + 'ImageObject', + 'ImageObjectSnapshot', + 'JobPosting', + 'HowToItem', + 'HowToSupply', + 'HowToTool', + 'MenuItem', + 'Trip', + 'BoatTrip', + 'BusTrip', + 'Flight', + 'TouristTrip', + 'TrainTrip', + ], + 'data' => [ + 'Intangible', + 'ActionAccessSpecification', + 'AlignmentObject', + 'Audience', + 'BedDetails', + 'Brand', + 'BroadcastChannel', + 'BroadcastFrequencySpecification', + 'ComputerLanguage', + 'DataFeedItem', + 'DefinedTerm', + 'CategoryCode', + 'DefinedRegion', + 'DigitalDocumentPermission', + 'EnergyConsumptionDetails', + 'EntryPoint', + 'FinancialIncentive', + 'FloorPlan', + 'GameServer', + 'GeospatialGeometry', + 'Grant', + 'MonetaryGrant', + 'HealthInsurancePlan', + 'HealthPlanCostSharingSpecification', + 'HealthPlanFormulary', + 'HealthPlanNetwork', + 'Language', + 'MediaSubscription', + 'MemberProgram', + 'Observation', + 'Occupation', + 'OccupationalExperienceRequirements', + 'Permit', + 'GovernmentPermit', + 'ProgramMembership', + 'PropertyValueSpecification', + 'Quantity', + 'Distance', + 'Duration', + 'Energy', + 'Mass', + 'Rating', + 'AggregateRating', + 'EndorsementRating', + 'EmployerAggregateRating', + 'Reservation', + 'BoatReservation', + 'BusReservation', + 'EventReservation', + 'FlightReservation', + 'FoodEstablishmentReservation', + 'LodgingReservation', + 'RentalCarReservation', + 'ReservationPackage', + 'TaxiReservation', + 'TrainReservation', + 'Role', + 'LinkRole', + 'OrganizationRole', + 'EmployeeRole', + 'PerformanceRole', + 'Schedule', + 'Seat', + 'Service', + 'BroadcastService', + 'CableOrSatelliteService', + 'FoodService', + 'GovernmentService', + 'TaxiService', + 'WebAPI', + 'ServiceChannel', + 'SpeakableSpecification', + 'StatisticalPopulation', + 'StructuredValue', + 'CDCPMDRecord', + 'ContactPoint', + 'PostalAddress', + 'DatedMoneySpecification', + 'DeliveryTimeSettings', + 'EngineSpecification', + 'ExchangeRateSpecification', + 'GeoCircle', + 'GeoCoordinates', + 'GeoShape', + 'InteractionCounter', + 'MonetaryAmount', + 'MonetaryAmountDistribution', + 'NutritionInformation', + 'OpeningHoursSpecification', + 'OwnershipInfo', + 'PostalCodeRangeSpecification', + 'PropertyValue', + 'LocationFeatureSpecification', + 'QuantitativeValue', + 'QuantitativeValueDistribution', + 'RepaymentSpecification', + 'ServicePeriod', + 'TypeAndQuantityNode', + 'WarrantyPromise', + 'Ticket', + 'VirtualLocation', + 'DataType', + 'Boolean', + 'False', + 'True', + 'Date', + 'DateTime', + 'Number', + 'Float', + 'Integer', + 'Text', + 'CssSelectorType', + 'PronounceableText', + 'URL', + 'XPathType', + 'Time', + ], + 'entity' => [ + 'Thing', + 'Person', + 'Patient', + 'Organization', + 'Airline', + 'Consortium', + 'Cooperative', + 'Corporation', + 'EducationalOrganization', + 'CollegeOrUniversity', + 'ElementarySchool', + 'HighSchool', + 'MiddleSchool', + 'Preschool', + 'School', + 'FundingScheme', + 'GovernmentOrganization', + 'LibrarySystem', + 'LocalBusiness', + 'MedicalOrganization', + 'DiagnosticLab', + 'Hospital', + 'MedicalClinic', + 'Pharmacy', + 'Physician', + 'VeterinaryCare', + 'MemberProgramTier', + 'NGO', + 'NewsMediaOrganization', + 'OnlineBusiness', + 'OnlineStore', + 'PerformingGroup', + 'DanceGroup', + 'MusicGroup', + 'TheaterGroup', + 'PoliticalParty', + 'Project', + 'FundingAgency', + 'ResearchProject', + 'ResearchOrganization', + 'SearchRescueOrganization', + 'SportsOrganization', + 'SportsTeam', + 'WorkersUnion', + 'AccountingService', + 'AnimalShelter', + 'ArchiveOrganization', + 'AutoBodyShop', + 'AutoDealer', + 'AutoPartsStore', + 'AutoRental', + 'AutoRepair', + 'AutoWash', + 'AutomatedTeller', + 'AutomotiveBusiness', + 'Bakery', + 'BankOrCreditUnion', + 'BarOrPub', + 'BeautySalon', + 'BedAndBreakfast', + 'BikeStore', + 'BookStore', + 'BowlingAlley', + 'Brewery', + 'CafeOrCoffeeShop', + 'Campground', + 'Casino', + 'ChildCare', + 'ClothingStore', + 'ComputerStore', + 'ConvenienceStore', + 'DaySpa', + 'Dentist', + 'DepartmentStore', + 'DistilleryOrganization', + 'Distillery', + 'DryCleaningOrLaundry', + 'ElectronicsStore', + 'EmploymentAgency', + 'EntertainmentBusiness', + 'AdultEntertainment', + 'AmusementPark', + 'ArtGallery', + 'ComedyClub', + 'MovieTheater', + 'NightClub', + 'ExerciseGym', + 'FinancialService', + 'Florist', + 'FoodEstablishment', + 'FurnitureStore', + 'GardenStore', + 'GasStation', + 'GeneralContractor', + 'GolfCourse', + 'GovernmentOffice', + 'PostOffice', + 'GroceryStore', + 'HairSalon', + 'HardwareStore', + 'HealthAndBeautyBusiness', + 'HealthClub', + 'HobbyShop', + 'HomeAndConstructionBusiness', + 'Electrician', + 'HVACBusiness', + 'HousePainter', + 'Locksmith', + 'MovingCompany', + 'Plumber', + 'RoofingContractor', + 'HomeGoodsStore', + 'Hostel', + 'Hotel', + 'IceCreamShop', + 'InsuranceAgency', + 'InternetCafe', + 'JewelryStore', + 'LegalService', + 'Attorney', + 'Notary', + 'Library', + 'LiquorStore', + 'LodgingBusiness', + 'MedicalBusiness', + 'MensClothingStore', + 'MobilePhoneStore', + 'Motel', + 'MotorcycleDealer', + 'MotorcycleRepair', + 'MovieRentalStore', + 'MusicStore', + 'NailSalon', + 'OfficeEquipmentStore', + 'Optician', + 'OutletStore', + 'PawnShop', + 'PetStore', + 'ProfessionalService', + 'RadioStation', + 'RealEstateAgent', + 'RecyclingCenter', + 'Resort', + 'Restaurant', + 'FastFoodRestaurant', + 'SelfStorage', + 'ShoeStore', + 'ShoppingCenter', + 'SkiResort', + 'SportingGoodsStore', + 'SportsActivityLocation', + 'StadiumOrArena', + 'Store', + 'TattooParlor', + 'TelevisionStation', + 'TennisComplex', + 'TireShop', + 'TouristInformationCenter', + 'ToyStore', + 'TravelAgency', + 'WholesaleStore', + 'Winery', + 'Place', + 'Accommodation', + 'Apartment', + 'CampingPitch', + 'House', + 'SingleFamilyResidence', + 'Room', + 'HotelRoom', + 'MeetingRoom', + 'Suite', + 'AdministrativeArea', + 'City', + 'Country', + 'SchoolDistrict', + 'State', + 'CivicStructure', + 'Airport', + 'Aquarium', + 'Beach', + 'BoatTerminal', + 'Bridge', + 'BusStation', + 'BusStop', + 'Cemetery', + 'Crematorium', + 'EventVenue', + 'FireStation', + 'GovernmentBuilding', + 'CityHall', + 'Courthouse', + 'DefenceEstablishment', + 'Embassy', + 'LegislativeBuilding', + 'Museum', + 'MusicVenue', + 'Park', + 'ParkingFacility', + 'PerformingArtsTheater', + 'PlaceOfWorship', + 'BuddhistTemple', + 'Church', + 'CatholicChurch', + 'HinduTemple', + 'Mosque', + 'Synagogue', + 'Playground', + 'PoliceStation', + 'PublicToilet', + 'RVPark', + 'SubwayStation', + 'TaxiStand', + 'TrainStation', + 'Zoo', + 'Landform', + 'BodyOfWater', + 'Canal', + 'LakeBodyOfWater', + 'OceanBodyOfWater', + 'Pond', + 'Reservoir', + 'RiverBodyOfWater', + 'SeaBodyOfWater', + 'Waterfall', + 'Continent', + 'Mountain', + 'Volcano', + 'LandmarksOrHistoricalBuildings', + 'Residence', + 'ApartmentComplex', + 'GatedResidenceCommunity', + 'TouristAttraction', + 'TouristDestination', + 'Taxon', + ], + 'enumeration' => [ + 'RespiratoryTherapy', + 'Enumeration', + 'ActionStatusType', + 'ActiveActionStatus', + 'CompletedActionStatus', + 'FailedActionStatus', + 'PotentialActionStatus', + 'AdultOrientedEnumeration', + 'AlcoholConsideration', + 'DangerousGoodConsideration', + 'HealthcareConsideration', + 'NarcoticConsideration', + 'ReducedRelevanceForChildrenConsideration', + 'SexualContentConsideration', + 'TobaccoNicotineConsideration', + 'UnclassifiedAdultConsideration', + 'ViolenceConsideration', + 'WeaponConsideration', + 'BoardingPolicyType', + 'GroupBoardingPolicy', + 'ZoneBoardingPolicy', + 'BodyMeasurementTypeEnumeration', + 'BodyMeasurementArm', + 'BodyMeasurementBust', + 'BodyMeasurementChest', + 'BodyMeasurementFoot', + 'BodyMeasurementHand', + 'BodyMeasurementHead', + 'BodyMeasurementHeight', + 'BodyMeasurementHips', + 'BodyMeasurementInsideLeg', + 'BodyMeasurementNeck', + 'BodyMeasurementUnderbust', + 'BodyMeasurementWaist', + 'BodyMeasurementWeight', + 'BookFormatType', + 'AudiobookFormat', + 'EBook', + 'GraphicNovel', + 'Hardcover', + 'Paperback', + 'BusinessEntityType', + 'BusinessFunction', + 'CarUsageType', + 'ContactPointOption', + 'HearingImpairedSupported', + 'TollFree', + 'DayOfWeek', + 'Friday', + 'Monday', + 'PublicHolidays', + 'Saturday', + 'Sunday', + 'Thursday', + 'Tuesday', + 'Wednesday', + 'DeliveryMethod', + 'LockerDelivery', + 'OnSitePickup', + 'ParcelService', + 'DigitalDocumentPermissionType', + 'CommentPermission', + 'ReadPermission', + 'WritePermission', + 'DigitalPlatformEnumeration', + 'AndroidPlatform', + 'DesktopWebPlatform', + 'GenericWebPlatform', + 'IOSPlatform', + 'MobileWebPlatform', + 'DigitalSourceType', + 'AlgorithmicMediaDigitalSource', + 'AlgorithmicallyEnhancedDigitalSource', + 'CompositeCaptureDigitalSource', + 'CompositeDigitalSource', + 'CompositeSyntheticDigitalSource', + 'CompositeWithTrainedAlgorithmicMediaDigitalSource', + 'DataDrivenMediaDigitalSource', + 'DigitalArtDigitalSource', + 'DigitalCaptureDigitalSource', + 'MinorHumanEditsDigitalSource', + 'MultiFrameComputationalCaptureDigitalSource', + 'NegativeFilmDigitalSource', + 'PositiveFilmDigitalSource', + 'PrintDigitalSource', + 'ScreenCaptureDigitalSource', + 'TrainedAlgorithmicMediaDigitalSource', + 'VirtualRecordingDigitalSource', + 'DriveWheelConfigurationValue', + 'AllWheelDriveConfiguration', + 'FourWheelDriveConfiguration', + 'FrontWheelDriveConfiguration', + 'RearWheelDriveConfiguration', + 'DrugCostCategory', + 'ReimbursementCap', + 'Retail', + 'Wholesale', + 'DrugPregnancyCategory', + 'FDAcategoryA', + 'FDAcategoryB', + 'FDAcategoryC', + 'FDAcategoryD', + 'FDAcategoryX', + 'FDAnotEvaluated', + 'DrugPrescriptionStatus', + 'OTC', + 'PrescriptionOnly', + 'EUEnergyEfficiencyEnumeration', + 'EUEnergyEfficiencyCategoryA', + 'EUEnergyEfficiencyCategoryA1Plus', + 'EUEnergyEfficiencyCategoryA2Plus', + 'EUEnergyEfficiencyCategoryA3Plus', + 'EUEnergyEfficiencyCategoryB', + 'EUEnergyEfficiencyCategoryC', + 'EUEnergyEfficiencyCategoryD', + 'EUEnergyEfficiencyCategoryE', + 'EUEnergyEfficiencyCategoryF', + 'EUEnergyEfficiencyCategoryG', + 'EnergyStarEnergyEfficiencyEnumeration', + 'EventAttendanceModeEnumeration', + 'MixedEventAttendanceMode', + 'OfflineEventAttendanceMode', + 'OnlineEventAttendanceMode', + 'EventStatusType', + 'EventCancelled', + 'EventMovedOnline', + 'EventPostponed', + 'EventRescheduled', + 'EventScheduled', + 'FulfillmentTypeEnumeration', + 'FulfillmentTypeDelivery', + 'FulfillmentTypePickup', + 'GameAvailabilityEnumeration', + 'DemoGameAvailability', + 'FullGameAvailability', + 'GamePlayMode', + 'CoOp', + 'MultiPlayer', + 'SinglePlayer', + 'GameServerStatus', + 'OfflinePermanently', + 'OfflineTemporarily', + 'Online', + 'OnlineFull', + 'GenderType', + 'Female', + 'Male', + 'GovernmentBenefitsType', + 'BasicIncome', + 'BusinessSupport', + 'DisabilitySupport', + 'HealthCare', + 'OneTimePayments', + 'PaidLeave', + 'ParentalSupport', + 'UnemploymentSupport', + 'HealthAspectEnumeration', + 'AllergiesHealthAspect', + 'BenefitsHealthAspect', + 'CausesHealthAspect', + 'ContagiousnessHealthAspect', + 'EffectivenessHealthAspect', + 'GettingAccessHealthAspect', + 'HowItWorksHealthAspect', + 'HowOrWhereHealthAspect', + 'IngredientsHealthAspect', + 'LivingWithHealthAspect', + 'MayTreatHealthAspect', + 'MisconceptionsHealthAspect', + 'OverviewHealthAspect', + 'PatientExperienceHealthAspect', + 'PregnancyHealthAspect', + 'PreventionHealthAspect', + 'PrognosisHealthAspect', + 'RelatedTopicsHealthAspect', + 'RisksOrComplicationsHealthAspect', + 'SafetyHealthAspect', + 'ScreeningHealthAspect', + 'SeeDoctorHealthAspect', + 'SelfCareHealthAspect', + 'SideEffectsHealthAspect', + 'StagesHealthAspect', + 'SymptomsHealthAspect', + 'TreatmentsHealthAspect', + 'TypesHealthAspect', + 'UsageOrScheduleHealthAspect', + 'IncentiveEligibility', + 'IncentiveStatus', + 'IncentiveType', + 'ItemAvailability', + 'BackOrder', + 'Discontinued', + 'InStock', + 'InStoreOnly', + 'LimitedAvailability', + 'MadeToOrder', + 'OnlineOnly', + 'OutOfStock', + 'PreOrder', + 'PreSale', + 'Reserved', + 'SoldOut', + 'ItemListOrderType', + 'ItemListOrderAscending', + 'ItemListOrderDescending', + 'ItemListUnordered', + 'LegalForceStatus', + 'InForce', + 'NotInForce', + 'PartiallyInForce', + 'LegalValueLevel', + 'AuthoritativeLegalValue', + 'DefinitiveLegalValue', + 'OfficialLegalValue', + 'UnofficialLegalValue', + 'MapCategoryType', + 'ParkingMap', + 'SeatingMap', + 'TransitMap', + 'VenueMap', + 'MeasurementMethodEnum', + 'ExhaustEmissionsMeasurementMethod', + 'MeasurementTypeEnumeration', + 'WearableMeasurementBack', + 'WearableMeasurementChestOrBust', + 'WearableMeasurementCollar', + 'WearableMeasurementCup', + 'WearableMeasurementHeight', + 'WearableMeasurementHips', + 'WearableMeasurementInseam', + 'WearableMeasurementLength', + 'WearableMeasurementOutsideLeg', + 'WearableMeasurementSleeve', + 'WearableMeasurementWaist', + 'WearableMeasurementWidth', + 'MediaManipulationRatingEnumeration', + 'DecontextualizedContent', + 'EditedOrCroppedContent', + 'OriginalMediaContent', + 'SatireOrParodyContent', + 'StagedContent', + 'TransformedContent', + 'MedicalAudienceType', + 'Clinician', + 'MedicalResearcher', + 'MedicalDevicePurpose', + 'Diagnostic', + 'Therapeutic', + 'MedicalEnumeration', + 'MedicalEvidenceLevel', + 'EvidenceLevelA', + 'EvidenceLevelB', + 'EvidenceLevelC', + 'MedicalImagingTechnique', + 'CT', + 'MRI', + 'PET', + 'Radiography', + 'Ultrasound', + 'XRay', + 'MedicalObservationalStudyDesign', + 'CaseSeries', + 'CohortStudy', + 'CrossSectional', + 'Longitudinal', + 'Observational', + 'Registry', + 'MedicalProcedureType', + 'NoninvasiveProcedure', + 'PercutaneousProcedure', + 'MedicalSpecialty', + 'Anesthesia', + 'Cardiovascular', + 'CommunityHealth', + 'Dentistry', + 'Dermatologic', + 'Dermatology', + 'DietNutrition', + 'Emergency', + 'Endocrine', + 'Gastroenterologic', + 'Genetic', + 'Geriatric', + 'Gynecologic', + 'Hematologic', + 'Infectious', + 'LaboratoryScience', + 'Midwifery', + 'Musculoskeletal', + 'Neurologic', + 'Nursing', + 'Obstetric', + 'Oncologic', + 'Optometric', + 'Otolaryngologic', + 'Pathology', + 'Pediatric', + 'PharmacySpecialty', + 'Physiotherapy', + 'PlasticSurgery', + 'Podiatric', + 'PrimaryCare', + 'Psychiatric', + 'PublicHealth', + 'Pulmonary', + 'Renal', + 'Rheumatologic', + 'SpeechPathology', + 'Surgical', + 'Toxicologic', + 'Urologic', + 'MedicalStudyStatus', + 'ActiveNotRecruiting', + 'Completed', + 'EnrollingByInvitation', + 'NotYetRecruiting', + 'Recruiting', + 'ResultsAvailable', + 'ResultsNotAvailable', + 'Suspended', + 'Terminated', + 'Withdrawn', + 'MedicalTrialDesign', + 'DoubleBlindedTrial', + 'InternationalTrial', + 'MultiCenterTrial', + 'OpenTrial', + 'PlaceboControlledTrial', + 'RandomizedTrial', + 'SingleBlindedTrial', + 'SingleCenterTrial', + 'TripleBlindedTrial', + 'MedicineSystem', + 'Ayurvedic', + 'Chiropractic', + 'Homeopathic', + 'Osteopathic', + 'TraditionalChinese', + 'WesternConventional', + 'MerchantReturnEnumeration', + 'MerchantReturnFiniteReturnWindow', + 'MerchantReturnNotPermitted', + 'MerchantReturnUnlimitedWindow', + 'MerchantReturnUnspecified', + 'MusicAlbumProductionType', + 'CompilationAlbum', + 'DJMixAlbum', + 'DemoAlbum', + 'LiveAlbum', + 'MixtapeAlbum', + 'RemixAlbum', + 'SoundtrackAlbum', + 'SpokenWordAlbum', + 'StudioAlbum', + 'MusicAlbumReleaseType', + 'AlbumRelease', + 'BroadcastRelease', + 'EPRelease', + 'SingleRelease', + 'MusicReleaseFormatType', + 'CDFormat', + 'CassetteFormat', + 'DVDFormat', + 'DigitalAudioTapeFormat', + 'DigitalFormat', + 'LaserDiscFormat', + 'VinylFormat', + 'NLNonprofitType', + 'NonprofitANBI', + 'NonprofitSBBI', + 'NonprofitType', + 'OfferItemCondition', + 'DamagedCondition', + 'NewCondition', + 'RefurbishedCondition', + 'UsedCondition', + 'OrderStatus', + 'OrderCancelled', + 'OrderDelivered', + 'OrderInTransit', + 'OrderPaymentDue', + 'OrderPickupAvailable', + 'OrderProblem', + 'OrderProcessing', + 'OrderReturned', + 'PaymentMethod', + 'ByBankTransferInAdvance', + 'ByInvoice', + 'COD', + 'Cash', + 'CheckInAdvance', + 'DirectDebit', + 'InStorePrepay', + 'PhoneCarrierPayment', + 'PaymentStatusType', + 'PaymentAutomaticallyApplied', + 'PaymentComplete', + 'PaymentDeclined', + 'PaymentDue', + 'PaymentPastDue', + 'PhysicalActivityCategory', + 'AerobicActivity', + 'AnaerobicActivity', + 'Balance', + 'Flexibility', + 'LeisureTimeActivity', + 'OccupationalActivity', + 'StrengthTraining', + 'PhysicalExamEnumeration', + 'Abdomen', + 'Appearance', + 'CardiovascularExam', + 'Ear', + 'Eye', + 'Genitourinary', + 'Head', + 'Lung', + 'MusculoskeletalExam', + 'Neck', + 'Neuro', + 'Nose', + 'Skin', + 'Throat', + 'PriceComponentTypeEnumeration', + 'ActivationFee', + 'CleaningFee', + 'DistanceFee', + 'Downpayment', + 'Installment', + 'Subscription', + 'PriceTypeEnumeration', + 'InvoicePrice', + 'ListPrice', + 'MSRP', + 'MinimumAdvertisedPrice', + 'RegularPrice', + 'SRP', + 'SalePrice', + 'StrikethroughPrice', + 'QualitativeValue', + 'RefundTypeEnumeration', + 'ExchangeRefund', + 'FullRefund', + 'StoreCreditRefund', + 'ReservationStatusType', + 'ReservationCancelled', + 'ReservationConfirmed', + 'ReservationHold', + 'ReservationPending', + 'RestrictedDiet', + 'DiabeticDiet', + 'GlutenFreeDiet', + 'HalalDiet', + 'HinduDiet', + 'KosherDiet', + 'LowCalorieDiet', + 'LowFatDiet', + 'LowLactoseDiet', + 'LowSaltDiet', + 'VeganDiet', + 'VegetarianDiet', + 'ReturnFeesEnumeration', + 'FreeReturn', + 'OriginalShippingFees', + 'RestockingFees', + 'ReturnFeesCustomerResponsibility', + 'ReturnShippingFees', + 'ReturnLabelSourceEnumeration', + 'ReturnLabelCustomerResponsibility', + 'ReturnLabelDownloadAndPrint', + 'ReturnLabelInBox', + 'ReturnMethodEnumeration', + 'KeepProduct', + 'ReturnAtKiosk', + 'ReturnByMail', + 'ReturnInStore', + 'RsvpResponseType', + 'RsvpResponseMaybe', + 'RsvpResponseNo', + 'RsvpResponseYes', + 'SizeGroupEnumeration', + 'WearableSizeGroupBig', + 'WearableSizeGroupBoys', + 'WearableSizeGroupExtraShort', + 'WearableSizeGroupExtraTall', + 'WearableSizeGroupGirls', + 'WearableSizeGroupHusky', + 'WearableSizeGroupInfants', + 'WearableSizeGroupJuniors', + 'WearableSizeGroupMaternity', + 'WearableSizeGroupMens', + 'WearableSizeGroupMisses', + 'WearableSizeGroupPetite', + 'WearableSizeGroupPlus', + 'WearableSizeGroupRegular', + 'WearableSizeGroupShort', + 'WearableSizeGroupTall', + 'WearableSizeGroupWomens', + 'SizeSpecification', + 'SizeSystemEnumeration', + 'SizeSystemImperial', + 'SizeSystemMetric', + 'WearableSizeSystemAU', + 'WearableSizeSystemBR', + 'WearableSizeSystemCN', + 'WearableSizeSystemContinental', + 'WearableSizeSystemDE', + 'WearableSizeSystemEN13402', + 'WearableSizeSystemEurope', + 'WearableSizeSystemFR', + 'WearableSizeSystemGS1', + 'WearableSizeSystemIT', + 'WearableSizeSystemJP', + 'WearableSizeSystemMX', + 'WearableSizeSystemUK', + 'WearableSizeSystemUS', + 'Specialty', + 'StatusEnumeration', + 'SteeringPositionValue', + 'LeftHandDriving', + 'RightHandDriving', + 'USNonprofitType', + 'Nonprofit501a', + 'Nonprofit501c1', + 'Nonprofit501c10', + 'Nonprofit501c11', + 'Nonprofit501c12', + 'Nonprofit501c13', + 'Nonprofit501c14', + 'Nonprofit501c15', + 'Nonprofit501c16', + 'Nonprofit501c17', + 'Nonprofit501c18', + 'Nonprofit501c19', + 'Nonprofit501c2', + 'Nonprofit501c20', + 'Nonprofit501c21', + 'Nonprofit501c22', + 'Nonprofit501c23', + 'Nonprofit501c24', + 'Nonprofit501c25', + 'Nonprofit501c26', + 'Nonprofit501c27', + 'Nonprofit501c28', + 'Nonprofit501c3', + 'Nonprofit501c4', + 'Nonprofit501c5', + 'Nonprofit501c6', + 'Nonprofit501c7', + 'Nonprofit501c8', + 'Nonprofit501c9', + 'Nonprofit501d', + 'Nonprofit501e', + 'Nonprofit501f', + 'Nonprofit501k', + 'Nonprofit501n', + 'Nonprofit501q', + 'Nonprofit527', + 'WarrantyScope', + ], + 'event' => [ + 'Event', + 'BusinessEvent', + 'ChildrensEvent', + 'ComedyEvent', + 'CourseInstance', + 'DanceEvent', + 'DeliveryEvent', + 'EducationEvent', + 'EventSeries', + 'ExhibitionEvent', + 'Festival', + 'FoodEvent', + 'Hackathon', + 'LiteraryEvent', + 'MusicEvent', + 'OnDemandEvent', + 'PublicationEvent', + 'BroadcastEvent', + 'SaleEvent', + 'ScreeningEvent', + 'SocialEvent', + 'SportsEvent', + 'TheaterEvent', + 'VisualArtsEvent', + ], + 'medical' => [ + 'MedicalEntity', + 'AnatomicalStructure', + 'Artery', + 'Bone', + 'BrainStructure', + 'Joint', + 'Ligament', + 'Muscle', + 'Nerve', + 'Vein', + 'AnatomicalSystem', + 'DrugClass', + 'DrugCost', + 'DrugStrength', + 'DoseSchedule', + 'MaximumDoseSchedule', + 'RecommendedDoseSchedule', + 'ReportedDoseSchedule', + 'LifestyleModification', + 'PhysicalActivity', + 'MedicalCause', + 'MedicalCondition', + 'InfectiousDisease', + 'MedicalSignOrSymptom', + 'MedicalSign', + 'VitalSign', + 'MedicalSymptom', + 'MedicalContraindication', + 'MedicalDevice', + 'MedicalGuideline', + 'MedicalGuidelineContraindication', + 'MedicalGuidelineRecommendation', + 'MedicalIndication', + 'ApprovedIndication', + 'PreventionIndication', + 'TreatmentIndication', + 'MedicalIntangible', + 'DDxElement', + 'MedicalCode', + 'MedicalConditionStage', + 'MedicalProcedure', + 'DiagnosticProcedure', + 'PalliativeProcedure', + 'PhysicalExam', + 'SurgicalProcedure', + 'TherapeuticProcedure', + 'MedicalRiskCalculator', + 'MedicalRiskEstimator', + 'MedicalRiskFactor', + 'MedicalRiskScore', + 'MedicalStudy', + 'MedicalObservationalStudy', + 'MedicalTrial', + 'MedicalTest', + 'BloodTest', + 'ImagingTest', + 'MedicalTestPanel', + 'PathologyTest', + 'MedicalTherapy', + 'OccupationalTherapy', + 'PhysicalTherapy', + 'RadiationTherapy', + 'Substance', + 'SuperficialAnatomy', + ], + 'meta' => [ 'Class', 'Property' ], + 'website' => [ + 'WebSite', + 'WebPage', + 'WebPageElement', + 'SiteNavigationElement', + 'BreadcrumbList', + 'ItemList', + 'ListItem', + 'AboutPage', + 'CheckoutPage', + 'CollectionPage', + 'ContactPage', + 'ItemPage', + 'MedicalWebPage', + 'ProfilePage', + 'QAPage', + 'RealEstateListing', + 'SearchResultsPage', + 'WPAdBlock', + 'WPFooter', + 'WPHeader', + 'WPSideBar', + 'Table', + ], +]; From e115e7749b51413351d038037b15055cf92c3236 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:36:08 +0100 Subject: [PATCH 125/319] Basic map loader strategy --- .../elements-context-map/base-map-loader.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php diff --git a/src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php new file mode 100644 index 00000000000..6b15edddd88 --- /dev/null +++ b/src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php @@ -0,0 +1,18 @@ +> The elements context map. + */ + public function load(): array { + return include __DIR__ . '/default-elements-context-map.php'; + } +} From 77b8c3c2a183af7b227c8dcb3d5f7857e0d3b174 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:36:38 +0100 Subject: [PATCH 126/319] Filtered map loader strategy --- .../filtered-map-loader.php | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php diff --git a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php new file mode 100644 index 00000000000..b9f3b74ed8c --- /dev/null +++ b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php @@ -0,0 +1,42 @@ +base_loader = $base_loader; + } + + /** + * Loads a filtered elements-context map. + * + * @return array> The filtered elements-context map. + */ + public function load(): array { + $map = $this->base_loader->load(); + + $map = \apply_filters( 'wpseo_schema_aggregator_elements_context_map', $map ); + + foreach ( $map as $context => $elements ) { + $map[ $context ] = \apply_filters( "wpseo_schema_aggregator_elements_context_map_{$context}", $elements ); + } + + return $map; + } +} From 7ae2ec77453e1943cd375a38dde96c647cd950f8 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:36:53 +0100 Subject: [PATCH 127/319] The elements-context map repository --- ...ments-context-map-repository-interface.php | 25 +++++++++ .../elements-context-map-repository.php | 55 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository-interface.php create mode 100644 src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php diff --git a/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository-interface.php b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository-interface.php new file mode 100644 index 00000000000..2c1ca8d5f81 --- /dev/null +++ b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository-interface.php @@ -0,0 +1,25 @@ +> The elements context map. + */ + public function get_map(): array; + + /** + * Saves the elements-context map. + * + * @param array> $map The elements-context map to be saved. + * + * @return void + */ + public function save_map( array $map ): void; +} diff --git a/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php new file mode 100644 index 00000000000..3874124468a --- /dev/null +++ b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php @@ -0,0 +1,55 @@ +>|null + */ + private $map = null; + + /** + * The map loader strategy. + * + * @var Map_Loader_Interface + */ + private $map_loader; + + /** + * Constructor. + * + * @param Map_Loader_Interface $map_loader The map loader strategy. + */ + public function __construct( Map_Loader_Interface $map_loader ) { + $this->map_loader = $map_loader; + } + + /** + * Retrieves the elements-context map. + * + * @return array> The elements context-map. + */ + public function get_map(): array { + if ( $this->map === null ) { + $this->map = $this->map_loader->load(); + } + return $this->map; + } + + /** + * Saves the elements-context map. + * + * @param array> $map The elements-context map to besaved. + * + * @return void + */ + public function save_map( array $map ): void { + $this->map = $map; + } +} From 118816da9a0acf177f01742bc3f7b1ca21ebcc42 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:37:20 +0100 Subject: [PATCH 128/319] Filtering strategy definition --- .../application/filtering/default-filter.php | 41 +++++++++++++++++++ .../filtering-strategy-interface.php | 20 +++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/schema-aggregator/application/filtering/default-filter.php create mode 100644 src/schema-aggregator/application/filtering/filtering-strategy-interface.php diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php new file mode 100644 index 00000000000..f112f46d3ff --- /dev/null +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -0,0 +1,41 @@ +elements_context_map_repository = $elements_context_map_repository; + } + + /** + * Applies filtering to the given schema. + * + * @param array $schema The schema to be filtered. + * + * @return array The filtered schema. + */ + public function filter( array $schema ): array { + $elements_context_map = $this->elements_context_map_repository->get_map(); + // Use the map. + return $schema; + } +} diff --git a/src/schema-aggregator/application/filtering/filtering-strategy-interface.php b/src/schema-aggregator/application/filtering/filtering-strategy-interface.php new file mode 100644 index 00000000000..c764c5d5004 --- /dev/null +++ b/src/schema-aggregator/application/filtering/filtering-strategy-interface.php @@ -0,0 +1,20 @@ + $schema The schema to be filtered. + * + * @return array The filtered schema. + */ + public function filter( array $schema ): array; +} From 3491c2ca3be6e7545dc92530332cb575af1669c7 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:37:40 +0100 Subject: [PATCH 129/319] Not used anymore, as we now have the filtering strategy in place --- .../application/schema-pieces-filter.php | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 src/schema-aggregator/application/schema-pieces-filter.php diff --git a/src/schema-aggregator/application/schema-pieces-filter.php b/src/schema-aggregator/application/schema-pieces-filter.php deleted file mode 100644 index c742b8c1e95..00000000000 --- a/src/schema-aggregator/application/schema-pieces-filter.php +++ /dev/null @@ -1,79 +0,0 @@ -config = $config; - } - - /** - * Check if type is allowed. - * - * @param string $type Schema type. - * @return bool True if allowed. - */ - public function is_allowed_type( string $type ): bool { - return \in_array( $type, $this->get_allowed_types(), true ); - } - - /** - * Get allowed types from config. - * - * @return array - */ - public function get_allowed_types(): array { - return $this->config->get_allowed_schema_types(); - } - - /** - * Check if entity has at least one allowed type. - * - * Handles @type as both string and array (per JSON-LD spec). - * Returns true if the entity's @type contains at least one allowed type. - * - * @param Schema_Piece $piece The schema piece. - * @return bool True if at least one type is allowed. - */ - public function has_allowed_type( Schema_Piece $piece ): bool { - $type = $piece->get_type(); - - if ( \is_string( $type ) ) { - return $this->is_allowed_type( $type ); - } - - if ( \is_array( $type ) ) { - foreach ( $type as $single_type ) { - if ( $this->is_allowed_type( (string) $single_type ) ) { - return true; - } - } - - return false; - } - - return false; - } -} From 95e2d0d144f2afebfbbea5cd230baca03af2c51a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:39:00 +0100 Subject: [PATCH 130/319] Factory for the filtering strategy to allow the loading of a custom filter --- .../filtering-strategy-factory.php | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/schema-aggregator/infrastructure/filtering-strategy-factory.php diff --git a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php new file mode 100644 index 00000000000..002ede2953f --- /dev/null +++ b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php @@ -0,0 +1,27 @@ + Date: Fri, 28 Nov 2025 16:39:34 +0100 Subject: [PATCH 131/319] Add the post_type required arg --- .../site-schema-aggregator-cli-command.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php index 68c7c8980e7..f923a7b0219 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php @@ -67,7 +67,14 @@ public static function get_namespace() { * : How many items to process per page. * --- * default: 100 - + * --- + * + * [--post_type=] + * : The post type to aggregate schema for. + * --- + * default: 'post' + * --- + * * ## EXAMPLES * * wp yoast aggregate_site_schema @@ -77,9 +84,8 @@ public static function get_namespace() { * @param array|null $args The arguments. * @param array|null $assoc_args The associative arguments. * - * @return void - * * @throws ExitException When the input args are invalid. + * @return void */ public function aggregate_site_schema( $args = null, $assoc_args = null ) { if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] < 1 ) { @@ -88,10 +94,11 @@ public function aggregate_site_schema( $args = null, $assoc_args = null ) { if ( isset( $assoc_args['per_page'] ) && (int) $assoc_args['per_page'] < 1 ) { WP_CLI::error( \__( 'The value for \'per_page\' must be a positive integer higher than equal to 1.', 'wordpress-seo' ) ); } - $page = (int) $assoc_args['page']; - $per_page = (int) $assoc_args['per_page']; + $page = (int) $assoc_args['page']; + $per_page = (int) $assoc_args['per_page']; + $post_type = $assoc_args['post_type']; try { - $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page ) ); + $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); } catch ( Exception $exception ) { WP_CLI::error( \__( 'An error occurred while aggregating the site schema.', 'wordpress-seo' ) ); } From 8574d53f5e10bda267d5e01aad65a1ad58cdd192 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:39:49 +0100 Subject: [PATCH 132/319] Remove unused structure --- .../infrastructure/aggregator-config.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index 9c6be78f979..b98aa028654 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -85,21 +85,6 @@ public function get_allowed_post_types(): array { return \array_intersect( $post_types, $this->post_type_helper->get_indexable_post_types() ); } - /** - * Get configured schema types (whitelist) - * - * @return array - */ - public function get_allowed_schema_types(): array { - $schema_types = \apply_filters( 'wpseo_schema_aggregator_schema_types', self::DEFAULT_SCHEMA_TYPES ); - - if ( ! \is_array( $schema_types ) ) { - return self::DEFAULT_SCHEMA_TYPES; - } - - return $schema_types; - } - /** * Get list of properties to remove from a schema piece. * From 99ac088375cfb7092d4657952fe3211a988d561c Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:40:14 +0100 Subject: [PATCH 133/319] WebPage is now filtered out by default --- src/schema-aggregator/infrastructure/aggregator-config.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index b98aa028654..c8dcd2b9b55 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -30,7 +30,6 @@ class Aggregator_Config { 'Event', 'Person', 'Organization', - 'WebPage', 'WebSite', ]; From 9cc2b9df808f825563bc0934f8233701e423891d Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:40:26 +0100 Subject: [PATCH 134/319] Add docbloc --- src/schema-aggregator/infrastructure/aggregator-config.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index c8dcd2b9b55..34826ef45b9 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -33,6 +33,11 @@ class Aggregator_Config { 'WebSite', ]; + /** + * The default properties to avoid in schema pieces. + * + * @var array + */ private const PROPERTIES_AVOID_LIST = [ 'breadcrumb', 'potentialAction' ]; /** From 42d8174e5b40de343d7461c06a43c82f94b4d447 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 28 Nov 2025 16:40:49 +0100 Subject: [PATCH 135/319] WIP: adopt the new filtering logic --- .../application/schema-pieces-aggregator.php | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 141d51ceec7..7f0137e7622 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Filtering_Strategy_Factory; /** * This class is responsible for taking an array of Schema_Pieces and return another array of Schema_Pieces where: @@ -23,30 +24,30 @@ class Schema_Pieces_Aggregator { private $properties_filter; /** - * The schema filter instance. + * The properties merger object * - * @var Schema_Pieces_Filter + * @var Properties_Merger */ - private $schema_pieces_filter; + private $properties_merger; /** - * The properties merger object + * The filtering strategy factory. * - * @var Properties_Merger + * @var Filtering_Strategy_Factory */ - private $properties_merger; + private $filtering_strategy_factory; /** * Class constructor * - * @param Properties_Filter $properties_filter The properties filter object. - * @param Schema_Pieces_Filter $schema_pieces_filter The schema pieces filter object. - * @param Properties_Merger $properties_merger The properties merger object. + * @param Properties_Filter $properties_filter The properties filter object. + * @param Properties_Merger $properties_merger The properties merger object. + * @param Filtering_Strategy_Factory $filtering_strategy_factory The filtering strategy factory. */ - public function __construct( Properties_Filter $properties_filter, Schema_Pieces_Filter $schema_pieces_filter, Properties_Merger $properties_merger ) { - $this->properties_filter = $properties_filter; - $this->schema_pieces_filter = $schema_pieces_filter; - $this->properties_merger = $properties_merger; + public function __construct( Properties_Filter $properties_filter, Properties_Merger $properties_merger, Filtering_Strategy_Factory $filtering_strategy_factory ) { + $this->properties_filter = $properties_filter; + $this->properties_merger = $properties_merger; + $this->filtering_strategy_factory = $filtering_strategy_factory; } /** @@ -59,10 +60,10 @@ public function __construct( Properties_Filter $properties_filter, Schema_Pieces public function aggregate( array $schema_pieces ): array { $aggregated_schema = []; - foreach ( $schema_pieces as $piece ) { - if ( ! $this->schema_pieces_filter->has_allowed_type( $piece ) ) { - continue; - } + $filtering_strategy = $this->filtering_strategy_factory->create(); + $filtered_schema_pieces = $filtering_strategy->filter( $schema_pieces ); + + foreach ( $filtered_schema_pieces as $piece ) { $id = $piece->get_id(); if ( \is_null( $id ) ) { From b790854fba72a63661146d633614ac90aa558b92 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 1 Dec 2025 09:31:52 +0100 Subject: [PATCH 136/319] fix post types --- .../infrastructure/aggregator-config.php | 20 ++------------- .../site-schema-aggregator-xml-route.php | 25 ++++++++++--------- 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index c07e7255f9d..946e513e20d 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -8,16 +8,6 @@ * Configuration for the Schema Aggregator. */ class Aggregator_Config { - /** - * Default post types to include in schema aggregation - * - * Note: 'product' is only included if Yoast WooCommerce SEO extension is active - * because without it, WooCommerce products don't generate Product schema in Yoast's graph - * - * @var array - */ - private const DEFAULT_POST_TYPES = [ 'post', 'page' ]; - /** * Default schema types to include (whitelist) * @@ -68,21 +58,15 @@ public function __construct( WooCommerce_Conditional $woocommerce_conditional, P * @return array */ public function get_allowed_post_types(): array { - $default_post_types = self::DEFAULT_POST_TYPES; - - // Only include 'product' if Yoast WooCommerce SEO extension is active. - if ( $this->woocommerce_conditional->is_met() ) { - $default_post_types[] = 'product'; - } + $default_post_types = $this->post_type_helper->get_indexable_post_types(); $post_types = \apply_filters( 'wpseo_schema_aggregator_post_types', $default_post_types ); - // Ensure it's an array. if ( ! \is_array( $post_types ) ) { return $default_post_types; } - return \array_intersect( $post_types, $this->post_type_helper->get_indexable_post_types() ); + return $post_types; } /** diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php index 2a57ec40467..29a0a009c65 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -12,6 +12,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Xml_Manager; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; /** @@ -56,18 +57,18 @@ class Site_Schema_Aggregator_Xml_Route implements Route_Interface { private $aggregate_site_schema_map_command_handler; /** - * The post type helper instance. + * The XML cache manager instance. * - * @var Post_Type_Helper + * @var Xml_Manager */ - private $post_type_helper; + private $xml_cache_manager; /** - * The XML cache manager instance. + * The aggregator configuration instance. * - * @var Xml_Manager + * @var Aggregator_Config */ - private $xml_cache_manager; + private $aggregator_config; /** * Returns the conditional for this route. @@ -85,23 +86,23 @@ public static function get_conditionals() { * @param Capability_Helper $capability_helper The capability * helper. * @param Aggregate_Site_Schema_Map_Command_Handler $aggregate_site_schema_map_command_handler The command handler. - * @param Post_type_Helper $post_type_helper The post type - * helper. * @param Xml_Manager $xml_cache_manager The XML cache * manager. + * @param Aggregator_Config $aggregator_config The aggregator + * configuration. */ public function __construct( Config $config, Capability_Helper $capability_helper, Aggregate_Site_Schema_Map_Command_Handler $aggregate_site_schema_map_command_handler, - Post_type_Helper $post_type_helper, - Xml_Manager $xml_cache_manager + Xml_Manager $xml_cache_manager, + Aggregator_Config $aggregator_config ) { $this->config = $config; $this->capability_helper = $capability_helper; $this->aggregate_site_schema_map_command_handler = $aggregate_site_schema_map_command_handler; - $this->post_type_helper = $post_type_helper; $this->xml_cache_manager = $xml_cache_manager; + $this->aggregator_config = $aggregator_config; } /** @@ -140,7 +141,7 @@ public function render_schema_xml() { } else { - $post_types = $this->post_type_helper->get_indexable_post_types(); + $post_types = $this->aggregator_config->get_allowed_post_types(); $command = new Aggregate_Site_Schema_Map_Command( $post_types, $this->config->get_per_page() ); $xml = $this->aggregate_site_schema_map_command_handler->handle( $command ); From be327ba32fb80803c571bb2094b54e56de6ef4be Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 1 Dec 2025 11:40:12 +0100 Subject: [PATCH 137/319] Make the max amount per page based on the post type. --- ...regate-site-schema-map-command-handler.php | 5 +--- .../aggregate-site-schema-map-command.php | 24 +++---------------- .../schema_map/schema-map-builder.php | 18 +++++++++++--- .../infrastructure/config.php | 23 ++++++++++++++---- ...indexables-update-listener-integration.php | 10 ++++++-- .../site-schema-aggregator-route.php | 2 +- .../site-schema-aggregator-xml-route.php | 2 +- 7 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php index 34462f39496..d0c304052be 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php @@ -57,10 +57,7 @@ public function __construct( Schema_Map_Indexable_Repository $schema_map_indexab public function handle( Aggregate_Site_Schema_Map_Command $command ): string { $indexable_counts = $this->schema_map_indexable_repository->get_indexable_count_per_post_type( $command->get_post_types() ); - - $threshold = $command->get_schema_map_threshold(); - - $schema_map = $this->schema_map_builder->build( $indexable_counts, $threshold ); + $schema_map = $this->schema_map_builder->build( $indexable_counts ); return $this->schema_map_xml_renderer->render( $schema_map ); } diff --git a/src/schema-aggregator/application/aggregate-site-schema-map-command.php b/src/schema-aggregator/application/aggregate-site-schema-map-command.php index 9cb9d62aa17..3c66fdbc3f8 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-map-command.php +++ b/src/schema-aggregator/application/aggregate-site-schema-map-command.php @@ -14,22 +14,13 @@ class Aggregate_Site_Schema_Map_Command { */ private $post_types; - /** - * The schema map threshold. - * - * @var int - */ - private $schema_map_threshold; - /** * The constructor. * - * @param array $post_types The post types to include in the schema map. - * @param int $schema_map_threshold The schema map threshold. + * @param array $post_types The post types to include in the schema map. */ - public function __construct( array $post_types, int $schema_map_threshold ) { - $this->post_types = $post_types; - $this->schema_map_threshold = $schema_map_threshold; + public function __construct( array $post_types ) { + $this->post_types = $post_types; } /** @@ -40,13 +31,4 @@ public function __construct( array $post_types, int $schema_map_threshold ) { public function get_post_types(): array { return $this->post_types; } - - /** - * Gets the schema map threshold. - * - * @return int The schema map threshold. - */ - public function get_schema_map_threshold(): int { - return $this->schema_map_threshold; - } } diff --git a/src/schema-aggregator/application/schema_map/schema-map-builder.php b/src/schema-aggregator/application/schema_map/schema-map-builder.php index 4dce60a9ace..88dc01129dc 100644 --- a/src/schema-aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema-aggregator/application/schema_map/schema-map-builder.php @@ -4,6 +4,7 @@ use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Indexable_Repository; /** @@ -18,29 +19,40 @@ class Schema_Map_Builder { */ private $indexable_repository; + /** + * The configuration. + * + * @var Config + */ + private $config; + /** * Schema_Map_Builder constructor. * * @param Schema_Map_Indexable_Repository $indexable_repository The indexable repository. + * @param Config $config The configuration. */ - public function __construct( Schema_Map_Indexable_Repository $indexable_repository ) { + public function __construct( Schema_Map_Indexable_Repository $indexable_repository, Config $config ) { $this->indexable_repository = $indexable_repository; + $this->config = $config; } /** * Builds the schema map based on indexable counts and threshold. * * @param Indexable_Count_Collection $indexable_counts The indexable counts per post type. - * @param int $threshold The threshold for items per page. * * @return array> The schema map. */ - public function build( Indexable_Count_Collection $indexable_counts, int $threshold ): array { + public function build( Indexable_Count_Collection $indexable_counts ): array { $schema_map = []; foreach ( $indexable_counts->get_indexable_counts() as $indexable_count ) { + $post_type = $indexable_count->get_post_type(); $count = $indexable_count->get_count(); + $threshold = $this->config->get_per_page( $post_type ); + $total_pages = (int) \ceil( $count / $threshold ); for ( $page = 1; $page <= $total_pages; $page++ ) { diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 6266627f33a..5f5e4e97c3d 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -14,14 +14,24 @@ class Config { * * @var int */ - private const DEFAULT_PER_PAGE = 100; + private const DEFAULT_PER_PAGE = 1000; + /** + * Default items per page for post types that come with lots of schema pieces. + * + * @var int + */ + private const DEFAULT_PER_PAGE_BIG_SCHEMA = 100; + + private const BIG_SCHEMA_POST_TYPES = [ + 'product', + ]; /** * Maximum items per page * * @var int */ - private const MAX_PER_PAGE = 100; + private const MAX_PER_PAGE = 1000; /** * Default cache TTL in seconds * @@ -32,10 +42,15 @@ class Config { /** * Get default items per page * + * @param string $post_type The post type to determine the max page size for. + * * @return int */ - public function get_per_page(): int { - $per_page = (int) \apply_filters( 'wpseo_schema_aggregator_per_page', self::DEFAULT_PER_PAGE ); + public function get_per_page( string $post_type ): int { + + $per_page = \in_array( $post_type, self::BIG_SCHEMA_POST_TYPES, true ) ? self::DEFAULT_PER_PAGE_BIG_SCHEMA : self::DEFAULT_PER_PAGE; + + $per_page = (int) \apply_filters( 'wpseo_schema_aggregator_per_page', $per_page ); if ( $per_page > self::MAX_PER_PAGE ) { $per_page = self::MAX_PER_PAGE; diff --git a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php index b7883c1a372..ffbdf4e0ddd 100644 --- a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -52,7 +52,12 @@ class Indexables_Update_Listener_Integration implements Integration_Interface { * @param Manager $manager The manager object. * @param Xml_Manager $xml_manager The XML cache manager. */ - public function __construct( Indexable_Repository $indexable_repository, Config $config, Manager $manager, Xml_Manager $xml_manager ) { + public function __construct( + Indexable_Repository $indexable_repository, + Config $config, + Manager $manager, + Xml_Manager $xml_manager + ) { $this->indexable_repository = $indexable_repository; $this->config = $config; $this->manager = $manager; @@ -89,6 +94,7 @@ public function reset_cache( $indexable, $indexable_before ) { if ( $indexable_before->permalink === null ) { $this->manager->invalidate_all(); $this->xml_manager->invalidate(); + return false; } $page = $this->get_page_number( $indexable ); @@ -118,6 +124,6 @@ public function get_page_number( $indexable ) { ->where_lt( 'id', $indexable->id ) ->count(); - return ( (int) \floor( $count_before / $this->config->get_per_page() ) + 1 ); + return ( (int) \floor( $count_before / $this->config->get_per_page( $indexable->object_sub_type ) ) + 1 ); } } diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index dfdda8e17c2..02dfe3a9e54 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -144,7 +144,7 @@ public function get_permission_callback(): bool { public function aggregate_site_schema( WP_REST_Request $request ) { $post_type = $request->get_param( 'post_type' ); $page = ( $request->get_param( 'page' ) ?? 1 ); - $per_page = $this->config->get_per_page(); + $per_page = $this->config->get_per_page( $post_type ); $output = $this->cache_manager->get( $page, $per_page ); if ( $output === null ) { diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php index 2a57ec40467..eb8cee0b1e2 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -142,7 +142,7 @@ public function render_schema_xml() { $post_types = $this->post_type_helper->get_indexable_post_types(); - $command = new Aggregate_Site_Schema_Map_Command( $post_types, $this->config->get_per_page() ); + $command = new Aggregate_Site_Schema_Map_Command( $post_types ); $xml = $this->aggregate_site_schema_map_command_handler->handle( $command ); $this->xml_cache_manager->set( $xml ); From 914114da9c7d7d93138fc280982e6ba8b2e9209f Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 1 Dec 2025 15:46:25 +0100 Subject: [PATCH 138/319] Implement a with construction so we don't pass the repo into the build method --- ...regate-site-schema-map-command-handler.php | 8 +++-- .../schema_map/schema-map-builder.php | 34 +++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php index 5aa0a5f6e3f..f28dc835173 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-map-command-handler.php @@ -66,12 +66,14 @@ public function __construct( Schema_Map_Repository_Factory $schema_map_repositor */ public function handle( Aggregate_Site_Schema_Map_Command $command ): string { - $schema_map_indexable_repository = $this->schema_map_repository_factory->get_repository( $this->indexable_helper->should_index_indexables() ); - $indexable_counts = $schema_map_indexable_repository->get_indexable_count_per_post_type( $command->get_post_types() ); + $schema_map_repository = $this->schema_map_repository_factory->get_repository( $this->indexable_helper->should_index_indexables() ); + $indexable_counts = $schema_map_repository->get_indexable_count_per_post_type( $command->get_post_types() ); $threshold = $command->get_schema_map_threshold(); - $schema_map = $this->schema_map_builder->build( $schema_map_indexable_repository, $indexable_counts, $threshold ); + $schema_map = $this->schema_map_builder + ->with_repository( $schema_map_repository ) + ->build( $indexable_counts, $threshold ); return $this->schema_map_xml_renderer->render( $schema_map ); } diff --git a/src/schema-aggregator/application/schema_map/schema-map-builder.php b/src/schema-aggregator/application/schema_map/schema-map-builder.php index c828181f1d3..b3dd86ee94c 100644 --- a/src/schema-aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema-aggregator/application/schema_map/schema-map-builder.php @@ -4,7 +4,7 @@ use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\Schema_Map_Repository_Interface; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Repository_Interface; /** * Builds the schema map. @@ -12,19 +12,33 @@ class Schema_Map_Builder { /** - * Builds the schema map based on indexable counts and threshold. + * The schema map repository. + * + * @var Schema_Map_Repository_Interface + */ + private $schema_map_repository; + + /** + * Sets the schema map repository. * * @param Schema_Map_Repository_Interface $schema_map_repository The schema map repository. - * @param Indexable_Count_Collection $indexable_counts The indexable counts per post type. - * @param int $threshold The threshold for items per page. + * + * @return self + */ + public function with_repository( Schema_Map_Repository_Interface $schema_map_repository ): self { + $this->schema_map_repository = $schema_map_repository; + return $this; + } + + /** + * Builds the schema map based on indexable counts and threshold. + * + * @param Indexable_Count_Collection $indexable_counts The indexable counts per post type. + * @param int $threshold The threshold for items per page. * * @return array> The schema map. */ - public function build( - Schema_Map_Repository_Interface $schema_map_repository, - Indexable_Count_Collection $indexable_counts, - int $threshold - ): array { + public function build( Indexable_Count_Collection $indexable_counts, int $threshold ): array { $schema_map = []; foreach ( $indexable_counts->get_indexable_counts() as $indexable_count ) { @@ -44,7 +58,7 @@ public function build( $url = $this->get_rest_route( $post_type, $page ); } - $lastmod = $schema_map_repository->get_lastmod_for_post_type( $post_type, $page, $threshold ); + $lastmod = $this->schema_map_repository->get_lastmod_for_post_type( $post_type, $page, $threshold ); $page_count = ( $page === $total_pages ) ? ( $count - ( ( $page - 1 ) * $threshold ) ) : $threshold; From d0411dceb3d0fd8b266e7f3813c1983d9ecb4e35 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 2 Dec 2025 09:42:23 +0100 Subject: [PATCH 139/319] Update feature card text. --- packages/js/src/settings/routes/site-features.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/settings/routes/site-features.js b/packages/js/src/settings/routes/site-features.js index 26e9886558c..71cf211dbfa 100644 --- a/packages/js/src/settings/routes/site-features.js +++ b/packages/js/src/settings/routes/site-features.js @@ -250,7 +250,7 @@ const SiteFeatures = () => { imageSrc="/images/icon-schema-aggregation-endpoint.svg" title={ __( "Schema aggregation endpoint", "wordpress-seo" ) } > -

{ __( "Provides a single JSON endpoint with all your site’s structured data, enabling NLWeb to power natural language AI queries on your content.", "wordpress-seo" ) }

+

{ __( "Provides everything required to connect with your site's public structured data. This enables conversational interfaces like NLWeb to power natural language queries on your content.", "wordpress-seo" ) }

From d7db46dfe2eb4bb4d71953e7b89bbaa0e2946aaa Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 2 Dec 2025 10:11:06 +0100 Subject: [PATCH 140/319] Fix cs --- .../user-interface/site-schema-aggregator-xml-route.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php index 29a0a009c65..bdd348ca01d 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -5,14 +5,13 @@ use WP_Error; use WP_REST_Response; use Yoast\WP\SEO\Helpers\Capability_Helper; -use Yoast\WP\SEO\Helpers\Post_Type_Helper; use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Routes\Route_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Xml_Manager; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; /** From 06a943102e323751bb7660440ffbb3ac1913594a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 2 Dec 2025 15:55:29 +0100 Subject: [PATCH 141/319] Fix cs --- .../application/schema_map/schema-map-builder.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/application/schema_map/schema-map-builder.php b/src/schema-aggregator/application/schema_map/schema-map-builder.php index b2855a2dccd..5d880363084 100644 --- a/src/schema-aggregator/application/schema_map/schema-map-builder.php +++ b/src/schema-aggregator/application/schema_map/schema-map-builder.php @@ -4,8 +4,8 @@ use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Schema_Aggregator\Domain\Indexable_Count_Collection; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Repository_Interface; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map\Schema_Map_Repository_Interface; /** * Builds the schema map. @@ -29,10 +29,10 @@ class Schema_Map_Builder { /** * Schema_Map_Builder constructor. * - * @param Config $config The configuration. + * @param Config $config The configuration. */ public function __construct( Config $config ) { - $this->config = $config; + $this->config = $config; } /** From 072a0b60b322c850e74245155fb968ba999763fd Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 2 Dec 2025 16:34:06 +0100 Subject: [PATCH 142/319] Adds filters for the per page count. --- .../infrastructure/config.php | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 5f5e4e97c3d..c6199d89597 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -47,10 +47,17 @@ class Config { * @return int */ public function get_per_page( string $post_type ): int { + /** + * Filter: 'wpseo_schema_aggregator_big_schema_post_types' Determines the list of post types we want to have a smaller per page count. + * + * @param bool $default_schema_post_types Determines the default list of big schema post types. + */ + $big_schema_post_types = \apply_filters( 'wpseo_schema_aggregator_big_schema_post_types', self::BIG_SCHEMA_POST_TYPES ); + if ( ! \is_array( $big_schema_post_types ) ) { + $big_schema_post_types = self::BIG_SCHEMA_POST_TYPES; + } - $per_page = \in_array( $post_type, self::BIG_SCHEMA_POST_TYPES, true ) ? self::DEFAULT_PER_PAGE_BIG_SCHEMA : self::DEFAULT_PER_PAGE; - - $per_page = (int) \apply_filters( 'wpseo_schema_aggregator_per_page', $per_page ); + $per_page = \in_array( $post_type, $big_schema_post_types, true ) ? $this->get_big_per_post_type() : $this->get_default_per_post_type(); if ( $per_page > self::MAX_PER_PAGE ) { $per_page = self::MAX_PER_PAGE; @@ -124,4 +131,44 @@ public function cache_enabled(): bool { return true; } } + + /** + * Gets the per post type for post types with lots of schema nodes. + * + * @return int + */ + public function get_big_per_post_type(): int { + /** + * Filter: 'wpseo_schema_aggregator_per_page_big' Determines the page count for post types with lots of schema nodes. + * + * @param bool $default_count The default amount of posts per page. + */ + $per_page = (int) \apply_filters( 'wpseo_schema_aggregator_per_page_big', self::DEFAULT_PER_PAGE_BIG_SCHEMA ); + + if ( $per_page > 0 ) { + return $per_page; + } + + return self::DEFAULT_PER_PAGE_BIG_SCHEMA; + } + + /** + * Gets the per page for smaller post types. + * + * @return int + */ + public function get_default_per_post_type(): int { + /** + * Filter: 'wpseo_schema_aggregator_per_page' Determines the page count for post types. + * + * @param bool $default_count The default amount of posts per page. + */ + $per_page = (int) \apply_filters( 'wpseo_schema_aggregator_per_page', self::DEFAULT_PER_PAGE ); + + if ( $per_page > 0 ) { + return $per_page; + } + + return self::DEFAULT_PER_PAGE; + } } From 2224e26447cbcd361705135275a2e953fad8e16a Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 3 Dec 2025 10:14:28 +0100 Subject: [PATCH 143/319] Adds a specific woo cache buster --- ...oduct-type-change-listener-integration.php | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php diff --git a/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php b/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php new file mode 100644 index 00000000000..90235acf26b --- /dev/null +++ b/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php @@ -0,0 +1,151 @@ +indexable_repository = $indexable_repository; + $this->config = $config; + $this->manager = $manager; + $this->xml_manager = $xml_manager; + } + + /** + * Registers the hooks with WordPress. + * + * @return void + */ + public function register_hooks() { + \add_action( 'woocommerce_product_type_changed', [ $this, 'reset_cache' ], \PHP_INT_MAX, 3 ); + } + + /** + * Returns the needed conditionals. + * + * @return array + */ + public static function get_conditionals() { + return [ + Schema_Aggregator_Conditional::class, + WooCommerce_Conditional::class, + ]; + } + + /** + * This method resets the cache for the cached page where the product is located. + * + * @param \WC_Product $product The product whose type was changed. + * @param string $old_type The previous product type. + * @param string $new_type The new product type. + * + * @return bool + */ + public function reset_cache( $product, $old_type, $new_type ) { + // Get the product ID. + $product_id = $product->get_id(); + + if ( ! $product_id ) { + return false; + } + + // Find the indexable for this product. + $indexable = $this->indexable_repository->find_by_id_and_type( $product_id, 'post' ); + + if ( ! $indexable ) { + // If no indexable exists, invalidate all to be safe. + $this->manager->invalidate_all(); + $this->xml_manager->invalidate(); + + return false; + } + + // Calculate which page this product appears on and invalidate that page. + $page = $this->get_page_number( $indexable ); + $this->manager->invalidate( $page ); + $this->xml_manager->invalidate(); + + return true; + } + + /** + * Calculates which page an indexable appears on in a filtered, paginated list. + * + * This method accounts for deletions by counting the actual position in the result set, + * not just using the ID directly. + * + * @param Indexable $indexable The indexable to find the page for. + * + * @return int The page number (1-indexed) where this indexable appears. + */ + public function get_page_number( $indexable ) { + $query = $this->indexable_repository->query(); + $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + $query->where( 'post_status', 'publish' ); + + // Count how many records come before this indexable (have a smaller ID). + $count_before = $query + ->where_lt( 'id', $indexable->id ) + ->count(); + + return ( (int) \floor( $count_before / $this->config->get_per_page( $indexable->object_sub_type ) ) + 1 ); + } +} From 6fc244ab8c9486fa7415d6455813330822d7236d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 3 Dec 2025 11:42:40 +0100 Subject: [PATCH 144/319] Abstracts some parts of the cache busting --- .../abstract-cache-listener-integration.php | 106 ++++++++++++++++++ ...indexables-update-listener-integration.php | 78 +------------ ...oduct-type-change-listener-integration.php | 95 ++-------------- 3 files changed, 114 insertions(+), 165 deletions(-) create mode 100644 src/schema-aggregator/user-interface/cache/abstract-cache-listener-integration.php diff --git a/src/schema-aggregator/user-interface/cache/abstract-cache-listener-integration.php b/src/schema-aggregator/user-interface/cache/abstract-cache-listener-integration.php new file mode 100644 index 00000000000..40a5687d963 --- /dev/null +++ b/src/schema-aggregator/user-interface/cache/abstract-cache-listener-integration.php @@ -0,0 +1,106 @@ +indexable_repository = $indexable_repository; + $this->config = $config; + $this->manager = $manager; + $this->xml_manager = $xml_manager; + } + + /** + * Registers the hooks with WordPress. + * + * @return void + */ + abstract public function register_hooks(); + + /** + * Returns the needed conditionals. + * + * @return array + */ + abstract public static function get_conditionals(); + + /** + * Calculates which page an indexable appears on in a filtered, paginated list. + * + * This method accounts for deletions by counting the actual position in the result set, + * not just using the ID directly. + * + * @param Indexable $indexable The indexable to find the page for. + * + * @return int The page number (1-indexed) where this indexable appears. + */ + protected function get_page_number( $indexable ) { + $query = $this->indexable_repository->query(); + $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + $query->where( 'object_sub_type', $indexable->object_sub_type ); + $query->where( 'post_status', 'publish' ); + + // Count how many records come before this indexable (have a smaller ID). + $count_before = $query + ->where_lt( 'id', $indexable->id ) + ->count(); + + return ( (int) \floor( $count_before / $this->config->get_per_page( $indexable->object_sub_type ) ) + 1 ); + } +} diff --git a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php index ffbdf4e0ddd..ec3659b4f43 100644 --- a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -3,66 +3,13 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache; -use Yoast\WP\SEO\Integrations\Integration_Interface; use Yoast\WP\SEO\Models\Indexable; -use Yoast\WP\SEO\Repositories\Indexable_Repository; -use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Manager; -use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Xml_Manager; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; /** * This class listens to changes in the indexables and resets the cache. */ -class Indexables_Update_Listener_Integration implements Integration_Interface { - - /** - * The indexable repository. - * - * @var Indexable_Repository $indexable_repository - */ - private $indexable_repository; - - /** - * The configuration object. - * - * @var Config - */ - private $config; - - /** - * The Manager object. - * - * @var Manager - */ - private $manager; - - /** - * The XML cache manager. - * - * @var Xml_Manager - */ - private $xml_manager; - - /** - * The constructor. - * - * @param Indexable_Repository $indexable_repository The indexable repository. - * @param Config $config The config object. - * @param Manager $manager The manager object. - * @param Xml_Manager $xml_manager The XML cache manager. - */ - public function __construct( - Indexable_Repository $indexable_repository, - Config $config, - Manager $manager, - Xml_Manager $xml_manager - ) { - $this->indexable_repository = $indexable_repository; - $this->config = $config; - $this->manager = $manager; - $this->xml_manager = $xml_manager; - } +class Indexables_Update_Listener_Integration extends Abstract_Cache_Listener_Integration { /** * Registers the hooks with WordPress. @@ -103,27 +50,4 @@ public function reset_cache( $indexable, $indexable_before ) { return true; } - - /** - * Calculates which page an indexable appears on in a filtered, paginated list. - * - * This method accounts for deletions by counting the actual position in the result set, - * not just using the ID directly. - * - * @param Indexable $indexable The indexable to find the page for. - * - * @return int The page number (1-indexed) where this indexable appears. - */ - public function get_page_number( $indexable ) { - $query = $this->indexable_repository->query(); - $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); - $query->where( 'post_status', 'publish' ); - - // Count how many records come before this indexable (have a smaller ID). - $count_before = $query - ->where_lt( 'id', $indexable->id ) - ->count(); - - return ( (int) \floor( $count_before / $this->config->get_per_page( $indexable->object_sub_type ) ) + 1 ); - } } diff --git a/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php b/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php index 90235acf26b..7248d461d02 100644 --- a/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php @@ -3,13 +3,8 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache; +use WC_Product; use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional; -use Yoast\WP\SEO\Integrations\Integration_Interface; -use Yoast\WP\SEO\Models\Indexable; -use Yoast\WP\SEO\Repositories\Indexable_Repository; -use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Manager; -use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Xml_Manager; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Aggregator_Conditional; /** @@ -18,56 +13,10 @@ * When a product type changes (e.g., from simple to variable or vice versa), * this integration invalidates the relevant schema aggregator cache to ensure * the cached schema reflects the new product structure. + * + * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded */ -class WooCommerce_Product_Type_Change_Listener_Integration implements Integration_Interface { - - /** - * The indexable repository. - * - * @var Indexable_Repository $indexable_repository - */ - private $indexable_repository; - - /** - * The configuration object. - * - * @var Config - */ - private $config; - - /** - * The Manager object. - * - * @var Manager - */ - private $manager; - - /** - * The XML cache manager. - * - * @var Xml_Manager - */ - private $xml_manager; - - /** - * The constructor. - * - * @param Indexable_Repository $indexable_repository The indexable repository. - * @param Config $config The config object. - * @param Manager $manager The manager object. - * @param Xml_Manager $xml_manager The XML cache manager. - */ - public function __construct( - Indexable_Repository $indexable_repository, - Config $config, - Manager $manager, - Xml_Manager $xml_manager - ) { - $this->indexable_repository = $indexable_repository; - $this->config = $config; - $this->manager = $manager; - $this->xml_manager = $xml_manager; - } +class WooCommerce_Product_Type_Change_Listener_Integration extends Abstract_Cache_Listener_Integration { /** * Registers the hooks with WordPress. @@ -75,7 +24,7 @@ public function __construct( * @return void */ public function register_hooks() { - \add_action( 'woocommerce_product_type_changed', [ $this, 'reset_cache' ], \PHP_INT_MAX, 3 ); + \add_action( 'woocommerce_product_type_changed', [ $this, 'reset_cache' ], \PHP_INT_MAX, 1 ); } /** @@ -93,59 +42,29 @@ public static function get_conditionals() { /** * This method resets the cache for the cached page where the product is located. * - * @param \WC_Product $product The product whose type was changed. - * @param string $old_type The previous product type. - * @param string $new_type The new product type. + * @param WC_Product $product The product whose type was changed. * * @return bool */ - public function reset_cache( $product, $old_type, $new_type ) { - // Get the product ID. + public function reset_cache( $product ) { $product_id = $product->get_id(); if ( ! $product_id ) { return false; } - - // Find the indexable for this product. $indexable = $this->indexable_repository->find_by_id_and_type( $product_id, 'post' ); if ( ! $indexable ) { - // If no indexable exists, invalidate all to be safe. $this->manager->invalidate_all(); $this->xml_manager->invalidate(); return false; } - // Calculate which page this product appears on and invalidate that page. $page = $this->get_page_number( $indexable ); $this->manager->invalidate( $page ); $this->xml_manager->invalidate(); return true; } - - /** - * Calculates which page an indexable appears on in a filtered, paginated list. - * - * This method accounts for deletions by counting the actual position in the result set, - * not just using the ID directly. - * - * @param Indexable $indexable The indexable to find the page for. - * - * @return int The page number (1-indexed) where this indexable appears. - */ - public function get_page_number( $indexable ) { - $query = $this->indexable_repository->query(); - $query->where_raw( '( is_public IS NULL OR is_public = 1 )' ); - $query->where( 'post_status', 'publish' ); - - // Count how many records come before this indexable (have a smaller ID). - $count_before = $query - ->where_lt( 'id', $indexable->id ) - ->count(); - - return ( (int) \floor( $count_before / $this->config->get_per_page( $indexable->object_sub_type ) ) + 1 ); - } } From 5aae7db84c762ac648207d7542407c2682390ad9 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 11:58:14 +0100 Subject: [PATCH 145/319] Add post type to cache layer. --- .../application/cache/manager.php | 39 +++++++++++-------- ...indexables-update-listener-integration.php | 2 +- ...oduct-type-change-listener-integration.php | 2 +- ...te-schema-aggregator-cache-cli-command.php | 7 +++- .../site-schema-aggregator-route.php | 4 +- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/schema-aggregator/application/cache/manager.php b/src/schema-aggregator/application/cache/manager.php index 7851ebdde32..5a9b25db8b8 100644 --- a/src/schema-aggregator/application/cache/manager.php +++ b/src/schema-aggregator/application/cache/manager.php @@ -46,12 +46,13 @@ public function __construct( Config $config ) { /** * Get cached data for a page * - * @param int $page Page number. - * @param int $per_page Items per page. + * @param string $post_type The post type that the cache is for. + * @param int $page Page number. + * @param int $per_page Items per page. * * @return array|null Cached data or null. */ - public function get( int $page, int $per_page ): ?array { + public function get( string $post_type, int $page, int $per_page ): ?array { try { if ( ! $this->config->cache_enabled() ) { return null; @@ -60,7 +61,7 @@ public function get( int $page, int $per_page ): ?array { return null; } - $key = $this->get_cache_key( $page, $per_page ); + $key = $this->get_cache_key( $post_type, $page, $per_page ); $data = \get_transient( $key ); @@ -83,19 +84,20 @@ public function get( int $page, int $per_page ): ?array { /** * Set cache data for a page * - * @param int $page Page number. - * @param int $per_page Items per page. - * @param array $data Data to cache. + * @param string $post_type The post type that the cache is for. + * @param int $page Page number. + * @param int $per_page Items per page. + * @param array $data Data to cache. * * @return bool Success. */ - public function set( int $page, int $per_page, array $data ): bool { + public function set( string $post_type, int $page, int $per_page, array $data ): bool { try { if ( $page < 1 || $per_page < 1 || ! \is_array( $data ) ) { return false; } - $key = $this->get_cache_key( $page, $per_page ); + $key = $this->get_cache_key( $post_type, $page, $per_page ); $expiration = $this->config->get_expiration( $data ); return \set_transient( $key, $data, $expiration ); @@ -111,15 +113,16 @@ public function set( int $page, int $per_page, array $data ): bool { * Note: When invalidating a specific page without per_page, this clears * ALL per_page variations for that page using a wildcard pattern. * - * @param int|null $page Page number or null for all. - * @param int|null $per_page Items per page or null to clear all per_page variations. + * @param string $post_type The post type that the cache is for. + * @param int|null $page Page number or null for all. + * @param int|null $per_page Items per page or null to clear all per_page variations. * * @return bool Success. */ - public function invalidate( ?int $page = null, ?int $per_page = null ): bool { + public function invalidate( string $post_type, ?int $page = null, ?int $per_page = null ): bool { if ( $page !== null && $per_page !== null ) { // Clear specific page/per_page combination. - return \delete_transient( $this->get_cache_key( $page, $per_page ) ); + return \delete_transient( $this->get_cache_key( $post_type, $page, $per_page ) ); } if ( $page !== null && $per_page === null ) { @@ -186,17 +189,19 @@ public function invalidate_all(): bool { /** * Generate cache key for page. * - * @param int $page Page number. - * @param int $per_page Items per page. + * @param string $post_type The post type that the cache is for. + * @param int $page Page number. + * @param int $per_page Items per page. * * @return string Cache key. */ - private function get_cache_key( int $page, int $per_page ): string { + private function get_cache_key( string $post_type, int $page, int $per_page ): string { return \sprintf( - '%s_page_%d_per_%d_v%d', + '%s_page_%d_per_%d_type_%s_v%d', self::CACHE_PREFIX, $page, $per_page, + $post_type, self::CACHE_VERSION ); } diff --git a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php index ec3659b4f43..82f120f3698 100644 --- a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -45,7 +45,7 @@ public function reset_cache( $indexable, $indexable_before ) { return false; } $page = $this->get_page_number( $indexable ); - $this->manager->invalidate( $page ); + $this->manager->invalidate( $indexable->object_sub_type, $page ); $this->xml_manager->invalidate(); return true; diff --git a/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php b/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php index 7248d461d02..c1e0bbd11be 100644 --- a/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/woocommerce-product-type-change-listener-integration.php @@ -62,7 +62,7 @@ public function reset_cache( $product ) { } $page = $this->get_page_number( $indexable ); - $this->manager->invalidate( $page ); + $this->manager->invalidate( 'product', $page ); $this->xml_manager->invalidate(); return true; diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php index 90a9ebe0b4b..52a740c41cc 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php @@ -65,6 +65,8 @@ public static function get_namespace() { * * ## OPTIONS * + * [--post_type=] + * : The current page to process. * [--page=] * : The current page to process. * --- @@ -81,12 +83,13 @@ public static function get_namespace() { * @return void */ public function aggregate_site_schema_clear_cache( $args = null, $assoc_args = null ) { - if ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] >= 1 ) { - $this->cache_manager->invalidate( $assoc_args['page'] ); + if ( ( isset( $assoc_args['page'] ) && (int) $assoc_args['page'] >= 1 ) && isset( $assoc_args['post_type'] ) ) { + $this->cache_manager->invalidate( $assoc_args['post_type'], $assoc_args['page'] ); $this->xml_manager->invalidate(); WP_CLI::log( \__( 'The site schema cache has been cleared successfully.', 'wordpress-seo' ) ); + return; } $this->cache_manager->invalidate_all(); diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 02dfe3a9e54..383ca52cafa 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -146,12 +146,12 @@ public function aggregate_site_schema( WP_REST_Request $request ) { $page = ( $request->get_param( 'page' ) ?? 1 ); $per_page = $this->config->get_per_page( $post_type ); - $output = $this->cache_manager->get( $page, $per_page ); + $output = $this->cache_manager->get( $post_type, $page, $per_page ); if ( $output === null ) { try { $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); - $this->cache_manager->set( $page, $per_page, $result ); + $this->cache_manager->set( $post_type, $page, $per_page, $result ); } catch ( Exception $exception ) { return new WP_Error( From 84ab45a0cffe3d772a6fb60f1027a3dd8ed32c33 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 15:09:17 +0100 Subject: [PATCH 146/319] Add unit tests for Indexable_Count domain object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive test coverage for the Indexable_Count value object including: - Constructor property initialization - get_count() with various count values (zero, positive, negative, large) - get_post_type() with different post type formats - Integration tests verifying getters return constructor values 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Domain/Indexable_Count_Test.php | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php diff --git a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php new file mode 100644 index 00000000000..85bbe73d51d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php @@ -0,0 +1,178 @@ +assertSame( + 'post', + $this->getPropertyValue( $instance, 'post_type' ) + ); + $this->assertSame( + 42, + $this->getPropertyValue( $instance, 'count' ) + ); + } + + /** + * Tests the get_count method with various count values. + * + * @param int $count The count value to test. + * @param int $expected The expected count value. + * + * @dataProvider count_data_provider + * + * @return void + */ + public function test_get_count( $count, $expected ) { + $instance = new Indexable_Count( 'post', $count ); + + $this->assertSame( $expected, $instance->get_count() ); + } + + /** + * Data provider for test_get_count. + * + * @return Generator + */ + public static function count_data_provider() { + yield 'Normal positive count' => [ + 'count' => 42, + 'expected' => 42, + ]; + yield 'Zero count' => [ + 'count' => 0, + 'expected' => 0, + ]; + yield 'Large count' => [ + 'count' => 999999, + 'expected' => 999999, + ]; + yield 'Small count' => [ + 'count' => 1, + 'expected' => 1, + ]; + yield 'Negative count' => [ + 'count' => -5, + 'expected' => -5, + ]; + } + + /** + * Tests the get_post_type method with various post type values. + * + * @param string $post_type The post type value to test. + * @param string $expected The expected post type value. + * + * @dataProvider post_type_data_provider + * + * @return void + */ + public function test_get_post_type( $post_type, $expected ) { + $instance = new Indexable_Count( $post_type, 10 ); + + $this->assertSame( $expected, $instance->get_post_type() ); + } + + /** + * Data provider for test_get_post_type. + * + * @return Generator + */ + public static function post_type_data_provider() { + yield 'Standard post type' => [ + 'post_type' => 'post', + 'expected' => 'post', + ]; + yield 'Custom post type' => [ + 'post_type' => 'product', + 'expected' => 'product', + ]; + yield 'Post type with underscore' => [ + 'post_type' => 'custom_type', + 'expected' => 'custom_type', + ]; + yield 'Post type with hyphen' => [ + 'post_type' => 'my-custom-type', + 'expected' => 'my-custom-type', + ]; + yield 'Short post type' => [ + 'post_type' => 'p', + 'expected' => 'p', + ]; + yield 'Longer post type name' => [ + 'post_type' => 'very_long_custom_post_type_name', + 'expected' => 'very_long_custom_post_type_name', + ]; + } + + /** + * Tests that getters return the exact values passed to the constructor. + * + * @param string $post_type The post type value. + * @param int $count The count value. + * + * @dataProvider constructor_values_data_provider + * + * @return void + */ + public function test_getters_return_constructor_values( $post_type, $count ) { + $instance = new Indexable_Count( $post_type, $count ); + + $this->assertSame( $post_type, $instance->get_post_type() ); + $this->assertSame( $count, $instance->get_count() ); + } + + /** + * Data provider for test_getters_return_constructor_values. + * + * @return Generator + */ + public static function constructor_values_data_provider() { + yield 'Standard post with count' => [ + 'post_type' => 'post', + 'count' => 42, + ]; + yield 'Page with zero count' => [ + 'post_type' => 'page', + 'count' => 0, + ]; + yield 'Custom post type with large count' => [ + 'post_type' => 'product', + 'count' => 500000, + ]; + yield 'Post type with underscore and count' => [ + 'post_type' => 'custom_type', + 'count' => 123, + ]; + yield 'Post type with hyphen and small count' => [ + 'post_type' => 'my-custom-type', + 'count' => 1, + ]; + yield 'Attachment post type' => [ + 'post_type' => 'attachment', + 'count' => 999, + ]; + } +} From d3174a90212a774f4daf7d6fef0eb132fccc6165 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 15:09:59 +0100 Subject: [PATCH 147/319] Add unit tests for Indexable_Count_Collection domain object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive test coverage for the Indexable_Count_Collection class including: - Constructor initializes empty collection - add_indexable_count() adds items correctly - get_indexable_counts() returns correct array - Collection maintains insertion order - Tests for empty, single, and multiple items 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Indexable_Count_Collection_Test.php | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php diff --git a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php new file mode 100644 index 00000000000..9116a830d50 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php @@ -0,0 +1,125 @@ +assertSame( + [], + $this->getPropertyValue( $instance, 'indexable_counts' ) + ); + } + + /** + * Tests that an empty collection returns an empty array. + * + * @return void + */ + public function test_get_indexable_counts_empty() { + $instance = new Indexable_Count_Collection(); + + $this->assertSame( [], $instance->get_indexable_counts() ); + } + + /** + * Tests adding a single Indexable_Count to the collection. + * + * @return void + */ + public function test_add_single_indexable_count() { + $instance = new Indexable_Count_Collection(); + $indexable_count = new Indexable_Count( 'post', 10 ); + + $instance->add_indexable_count( $indexable_count ); + + $result = $instance->get_indexable_counts(); + $this->assertCount( 1, $result ); + $this->assertSame( $indexable_count, $result[0] ); + } + + /** + * Tests adding multiple Indexable_Count objects to the collection. + * + * @return void + */ + public function test_add_multiple_indexable_counts() { + $instance = new Indexable_Count_Collection(); + + $count1 = new Indexable_Count( 'post', 10 ); + $count2 = new Indexable_Count( 'page', 5 ); + $count3 = new Indexable_Count( 'product', 20 ); + + $instance->add_indexable_count( $count1 ); + $instance->add_indexable_count( $count2 ); + $instance->add_indexable_count( $count3 ); + + $result = $instance->get_indexable_counts(); + $this->assertCount( 3, $result ); + $this->assertSame( $count1, $result[0] ); + $this->assertSame( $count2, $result[1] ); + $this->assertSame( $count3, $result[2] ); + } + + /** + * Tests that get_indexable_counts returns the correct type. + * + * @return void + */ + public function test_get_indexable_counts_returns_array() { + $instance = new Indexable_Count_Collection(); + $indexable_count = new Indexable_Count( 'post', 42 ); + + $instance->add_indexable_count( $indexable_count ); + + $result = $instance->get_indexable_counts(); + $this->assertIsArray( $result ); + $this->assertContainsOnlyInstancesOf( Indexable_Count::class, $result ); + } + + /** + * Tests that added items maintain their order. + * + * @return void + */ + public function test_collection_maintains_order() { + $instance = new Indexable_Count_Collection(); + + $count1 = new Indexable_Count( 'post', 1 ); + $count2 = new Indexable_Count( 'page', 2 ); + $count3 = new Indexable_Count( 'attachment', 3 ); + $count4 = new Indexable_Count( 'product', 4 ); + + $instance->add_indexable_count( $count1 ); + $instance->add_indexable_count( $count2 ); + $instance->add_indexable_count( $count3 ); + $instance->add_indexable_count( $count4 ); + + $result = $instance->get_indexable_counts(); + + $this->assertSame( 1, $result[0]->get_count() ); + $this->assertSame( 2, $result[1]->get_count() ); + $this->assertSame( 3, $result[2]->get_count() ); + $this->assertSame( 4, $result[3]->get_count() ); + } +} From 999e3744665fe2d76b0ff54384807b2ce0eaa206 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 15:10:17 +0100 Subject: [PATCH 148/319] Add unit tests for Page_Controls domain object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive test coverage for the Page_Controls value object including: - Constructor sets page, page_size, and post_type properties - get_page() with various page numbers - get_page_size() with different page size values - get_post_type() with various post type formats - Integration tests verifying all getters return constructor values 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Domain/Page_Controls_Test.php | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php diff --git a/tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php b/tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php new file mode 100644 index 00000000000..539d0ab9e32 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php @@ -0,0 +1,218 @@ +assertSame( + 1, + $this->getPropertyValue( $instance, 'page' ) + ); + $this->assertSame( + 20, + $this->getPropertyValue( $instance, 'page_size' ) + ); + $this->assertSame( + 'post', + $this->getPropertyValue( $instance, 'post_type' ) + ); + } + + /** + * Tests the get_page method with various page values. + * + * @param int $page The page value to test. + * @param int $expected The expected page value. + * + * @dataProvider page_data_provider + * + * @return void + */ + public function test_get_page( $page, $expected ) { + $instance = new Page_Controls( $page, 10, 'post' ); + + $this->assertSame( $expected, $instance->get_page() ); + } + + /** + * Data provider for test_get_page. + * + * @return Generator + */ + public static function page_data_provider() { + yield 'First page' => [ + 'page' => 1, + 'expected' => 1, + ]; + yield 'Second page' => [ + 'page' => 2, + 'expected' => 2, + ]; + yield 'Large page number' => [ + 'page' => 100, + 'expected' => 100, + ]; + yield 'Zero page' => [ + 'page' => 0, + 'expected' => 0, + ]; + } + + /** + * Tests the get_page_size method with various page size values. + * + * @param int $page_size The page size value to test. + * @param int $expected The expected page size value. + * + * @dataProvider page_size_data_provider + * + * @return void + */ + public function test_get_page_size( $page_size, $expected ) { + $instance = new Page_Controls( 1, $page_size, 'post' ); + + $this->assertSame( $expected, $instance->get_page_size() ); + } + + /** + * Data provider for test_get_page_size. + * + * @return Generator + */ + public static function page_size_data_provider() { + yield 'Standard page size' => [ + 'page_size' => 10, + 'expected' => 10, + ]; + yield 'Small page size' => [ + 'page_size' => 5, + 'expected' => 5, + ]; + yield 'Large page size' => [ + 'page_size' => 100, + 'expected' => 100, + ]; + yield 'Single item per page' => [ + 'page_size' => 1, + 'expected' => 1, + ]; + } + + /** + * Tests the get_post_type method with various post type values. + * + * @param string $post_type The post type value to test. + * @param string $expected The expected post type value. + * + * @dataProvider post_type_data_provider + * + * @return void + */ + public function test_get_post_type( $post_type, $expected ) { + $instance = new Page_Controls( 1, 10, $post_type ); + + $this->assertSame( $expected, $instance->get_post_type() ); + } + + /** + * Data provider for test_get_post_type. + * + * @return Generator + */ + public static function post_type_data_provider() { + yield 'Standard post type' => [ + 'post_type' => 'post', + 'expected' => 'post', + ]; + yield 'Page post type' => [ + 'post_type' => 'page', + 'expected' => 'page', + ]; + yield 'Custom post type' => [ + 'post_type' => 'product', + 'expected' => 'product', + ]; + yield 'Post type with underscore' => [ + 'post_type' => 'custom_type', + 'expected' => 'custom_type', + ]; + yield 'Post type with hyphen' => [ + 'post_type' => 'my-custom-type', + 'expected' => 'my-custom-type', + ]; + } + + /** + * Tests that all getters return the exact values passed to the constructor. + * + * @param int $page The page value. + * @param int $page_size The page size value. + * @param string $post_type The post type value. + * + * @dataProvider constructor_values_data_provider + * + * @return void + */ + public function test_getters_return_constructor_values( $page, $page_size, $post_type ) { + $instance = new Page_Controls( $page, $page_size, $post_type ); + + $this->assertSame( $page, $instance->get_page() ); + $this->assertSame( $page_size, $instance->get_page_size() ); + $this->assertSame( $post_type, $instance->get_post_type() ); + } + + /** + * Data provider for test_getters_return_constructor_values. + * + * @return Generator + */ + public static function constructor_values_data_provider() { + yield 'Standard pagination' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'post', + ]; + yield 'Second page with larger page size' => [ + 'page' => 2, + 'page_size' => 50, + 'post_type' => 'page', + ]; + yield 'Large page number' => [ + 'page' => 100, + 'page_size' => 25, + 'post_type' => 'product', + ]; + yield 'Custom post type with small page size' => [ + 'page' => 5, + 'page_size' => 5, + 'post_type' => 'custom_type', + ]; + yield 'First page with single item' => [ + 'page' => 1, + 'page_size' => 1, + 'post_type' => 'attachment', + ]; + } +} From 30172c736f9669b3c4f0d942ea6c3291c7f9556d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 15:10:25 +0100 Subject: [PATCH 149/319] Add unit tests for Schema_Piece domain object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive test coverage for the Schema_Piece class including: - Constructor with string and array types - get_type() returns correct type (string or array) - get_data() returns various data structures - get_id() handles presence/absence of @id in data - to_json_ld_graph() wraps data in @graph structure correctly - Integration tests with various data and type combinations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Domain/Schema_Piece_Test.php | 364 ++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php diff --git a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php new file mode 100644 index 00000000000..c105fe68734 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php @@ -0,0 +1,364 @@ + 'Test', 'value' => 123 ]; + $type = 'Article'; + $instance = new Schema_Piece( $data, $type ); + + $this->assertSame( + $data, + $this->getPropertyValue( $instance, 'data' ) + ); + $this->assertSame( + $type, + $this->getPropertyValue( $instance, 'type' ) + ); + } + + /** + * Tests if the constructor sets properties correctly with array type. + * + * @return void + */ + public function test_constructor_with_array_type() { + $data = [ 'name' => 'Test' ]; + $type = [ 'Article', 'NewsArticle' ]; + $instance = new Schema_Piece( $data, $type ); + + $this->assertSame( + $data, + $this->getPropertyValue( $instance, 'data' ) + ); + $this->assertSame( + $type, + $this->getPropertyValue( $instance, 'type' ) + ); + } + + /** + * Tests the get_type method with various type values. + * + * @param string|array $type The type value to test. + * @param string|array $expected The expected type value. + * + * @dataProvider type_data_provider + * + * @return void + */ + public function test_get_type( $type, $expected ) { + $instance = new Schema_Piece( [ 'name' => 'Test' ], $type ); + + $this->assertSame( $expected, $instance->get_type() ); + } + + /** + * Data provider for test_get_type. + * + * @return Generator + */ + public static function type_data_provider() { + yield 'Single type as string' => [ + 'type' => 'Article', + 'expected' => 'Article', + ]; + yield 'Organization type' => [ + 'type' => 'Organization', + 'expected' => 'Organization', + ]; + yield 'Multiple types as array' => [ + 'type' => [ 'Article', 'NewsArticle' ], + 'expected' => [ 'Article', 'NewsArticle' ], + ]; + yield 'Single type in array' => [ + 'type' => [ 'Person' ], + 'expected' => [ 'Person' ], + ]; + } + + /** + * Tests the get_data method with various data arrays. + * + * @param array $data The data to test. + * @param array $expected The expected data. + * + * @dataProvider data_data_provider + * + * @return void + */ + public function test_get_data( $data, $expected ) { + $instance = new Schema_Piece( $data, 'Article' ); + + $this->assertSame( $expected, $instance->get_data() ); + } + + /** + * Data provider for test_get_data. + * + * @return Generator + */ + public static function data_data_provider() { + yield 'Simple data' => [ + 'data' => [ 'name' => 'Test' ], + 'expected' => [ 'name' => 'Test' ], + ]; + yield 'Data with multiple properties' => [ + 'data' => [ + 'name' => 'Article Name', + 'description' => 'Article Description', + 'published' => true, + ], + 'expected' => [ + 'name' => 'Article Name', + 'description' => 'Article Description', + 'published' => true, + ], + ]; + yield 'Data with numeric values' => [ + 'data' => [ + 'count' => 42, + 'views' => 1000, + ], + 'expected' => [ + 'count' => 42, + 'views' => 1000, + ], + ]; + yield 'Data with boolean values' => [ + 'data' => [ + 'active' => true, + 'deleted' => false, + ], + 'expected' => [ + 'active' => true, + 'deleted' => false, + ], + ]; + yield 'Empty data array' => [ + 'data' => [], + 'expected' => [], + ]; + } + + /** + * Tests the get_id method when @id is present in data. + * + * @return void + */ + public function test_get_id_with_id_present() { + $data = [ + '@id' => 'https://example.com/#article', + 'name' => 'Test', + ]; + $instance = new Schema_Piece( $data, 'Article' ); + + $this->assertSame( 'https://example.com/#article', $instance->get_id() ); + } + + /** + * Tests the get_id method when @id is not present in data. + * + * @return void + */ + public function test_get_id_without_id_present() { + $data = [ 'name' => 'Test' ]; + $instance = new Schema_Piece( $data, 'Article' ); + + $this->assertNull( $instance->get_id() ); + } + + /** + * Tests the get_id method with various @id values. + * + * @param array $data The data containing @id. + * @param string|null $expected_id The expected ID value. + * + * @dataProvider id_data_provider + * + * @return void + */ + public function test_get_id_with_various_values( $data, $expected_id ) { + $instance = new Schema_Piece( $data, 'Article' ); + + $this->assertSame( $expected_id, $instance->get_id() ); + } + + /** + * Data provider for test_get_id_with_various_values. + * + * @return Generator + */ + public static function id_data_provider() { + yield 'ID with hash fragment' => [ + 'data' => [ '@id' => 'https://example.com/#article' ], + 'expected_id' => 'https://example.com/#article', + ]; + yield 'ID with simple path' => [ + 'data' => [ '@id' => 'https://example.com/article/1' ], + 'expected_id' => 'https://example.com/article/1', + ]; + yield 'No ID present' => [ + 'data' => [ 'name' => 'Test' ], + 'expected_id' => null, + ]; + yield 'Empty data' => [ + 'data' => [], + 'expected_id' => null, + ]; + yield 'ID with other properties' => [ + 'data' => [ + '@id' => 'https://example.com/#organization', + 'name' => 'Company', + ], + 'expected_id' => 'https://example.com/#organization', + ]; + } + + /** + * Tests the to_json_ld_graph method. + * + * @return void + */ + public function test_to_json_ld_graph() { + $data = [ + '@id' => 'https://example.com/#article', + 'name' => 'Test Article', + ]; + $instance = new Schema_Piece( $data, 'Article' ); + + $result = $instance->to_json_ld_graph(); + + $this->assertIsArray( $result ); + $this->assertArrayHasKey( '@graph', $result ); + $this->assertSame( $data, $result['@graph'] ); + } + + /** + * Tests the to_json_ld_graph method with various data. + * + * @param array $data The data to test. + * @param array $expected The expected graph structure. + * + * @dataProvider json_ld_graph_data_provider + * + * @return void + */ + public function test_to_json_ld_graph_with_various_data( $data, $expected ) { + $instance = new Schema_Piece( $data, 'Article' ); + + $this->assertSame( $expected, $instance->to_json_ld_graph() ); + } + + /** + * Data provider for test_to_json_ld_graph_with_various_data. + * + * @return Generator + */ + public static function json_ld_graph_data_provider() { + yield 'Simple data' => [ + 'data' => [ 'name' => 'Test' ], + 'expected' => [ '@graph' => [ 'name' => 'Test' ] ], + ]; + yield 'Data with @id' => [ + 'data' => [ + '@id' => 'https://example.com/#article', + 'name' => 'Article', + ], + 'expected' => [ + '@graph' => [ + '@id' => 'https://example.com/#article', + 'name' => 'Article', + ], + ], + ]; + yield 'Complex data' => [ + 'data' => [ + '@id' => 'https://example.com/#organization', + 'name' => 'Company', + 'description' => 'A great company', + 'employee_count' => 100, + ], + 'expected' => [ + '@graph' => [ + '@id' => 'https://example.com/#organization', + 'name' => 'Company', + 'description' => 'A great company', + 'employee_count' => 100, + ], + ], + ]; + yield 'Empty data' => [ + 'data' => [], + 'expected' => [ '@graph' => [] ], + ]; + } + + /** + * Tests that getters return the exact values passed to the constructor. + * + * @param array $data The data value. + * @param string|array $type The type value. + * + * @dataProvider constructor_values_data_provider + * + * @return void + */ + public function test_getters_return_constructor_values( $data, $type ) { + $instance = new Schema_Piece( $data, $type ); + + $this->assertSame( $data, $instance->get_data() ); + $this->assertSame( $type, $instance->get_type() ); + } + + /** + * Data provider for test_getters_return_constructor_values. + * + * @return Generator + */ + public static function constructor_values_data_provider() { + yield 'Article with string type' => [ + 'data' => [ 'name' => 'Article Name' ], + 'type' => 'Article', + ]; + yield 'Organization with array type' => [ + 'data' => [ 'name' => 'Company' ], + 'type' => [ 'Organization', 'LocalBusiness' ], + ]; + yield 'Complex data with single type' => [ + 'data' => [ + '@id' => 'https://example.com/#page', + 'name' => 'Page', + 'description' => 'A page description', + 'published' => true, + ], + 'type' => 'WebPage', + ]; + yield 'Empty data with type' => [ + 'data' => [], + 'type' => 'Thing', + ]; + } +} From dae61c0d74c7cf4d0d21033f924385f00163855d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 15:18:42 +0100 Subject: [PATCH 150/319] cs --- .../Indexable_Count_Collection_Test.php | 4 ++-- .../Domain/Schema_Piece_Test.php | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php index 9116a830d50..d67a1c15321 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php @@ -48,7 +48,7 @@ public function test_get_indexable_counts_empty() { * @return void */ public function test_add_single_indexable_count() { - $instance = new Indexable_Count_Collection(); + $instance = new Indexable_Count_Collection(); $indexable_count = new Indexable_Count( 'post', 10 ); $instance->add_indexable_count( $indexable_count ); @@ -87,7 +87,7 @@ public function test_add_multiple_indexable_counts() { * @return void */ public function test_get_indexable_counts_returns_array() { - $instance = new Indexable_Count_Collection(); + $instance = new Indexable_Count_Collection(); $indexable_count = new Indexable_Count( 'post', 42 ); $instance->add_indexable_count( $indexable_count ); diff --git a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php index c105fe68734..0fb94637179 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php @@ -25,7 +25,10 @@ final class Schema_Piece_Test extends TestCase { * @return void */ public function test_constructor_with_string_type() { - $data = [ 'name' => 'Test', 'value' => 123 ]; + $data = [ + 'name' => 'Test', + 'value' => 123, + ]; $type = 'Article'; $instance = new Schema_Piece( $data, $type ); @@ -169,7 +172,7 @@ public static function data_data_provider() { * @return void */ public function test_get_id_with_id_present() { - $data = [ + $data = [ '@id' => 'https://example.com/#article', 'name' => 'Test', ]; @@ -193,8 +196,8 @@ public function test_get_id_without_id_present() { /** * Tests the get_id method with various @id values. * - * @param array $data The data containing @id. - * @param string|null $expected_id The expected ID value. + * @param array $data The data containing @id. + * @param string|null $expected_id The expected ID value. * * @dataProvider id_data_provider * @@ -243,7 +246,7 @@ public static function id_data_provider() { * @return void */ public function test_to_json_ld_graph() { - $data = [ + $data = [ '@id' => 'https://example.com/#article', 'name' => 'Test Article', ]; @@ -259,8 +262,8 @@ public function test_to_json_ld_graph() { /** * Tests the to_json_ld_graph method with various data. * - * @param array $data The data to test. - * @param array $expected The expected graph structure. + * @param array $data The data to test. + * @param array $expected The expected graph structure. * * @dataProvider json_ld_graph_data_provider * @@ -296,9 +299,9 @@ public static function json_ld_graph_data_provider() { ]; yield 'Complex data' => [ 'data' => [ - '@id' => 'https://example.com/#organization', - 'name' => 'Company', - 'description' => 'A great company', + '@id' => 'https://example.com/#organization', + 'name' => 'Company', + 'description' => 'A great company', 'employee_count' => 100, ], 'expected' => [ From 5fe68cf99470e50e99edfeb0f7510c4fdc46e9b4 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 15:22:40 +0100 Subject: [PATCH 151/319] Add unit tests for Cache Manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive test coverage for the Cache Manager including: - Constructor initializes Config dependency - get() method with cache enabled/disabled scenarios - get() handles invalid parameters, cache misses, corrupted data - get() returns cached data correctly with various page/per_page combinations - set() validates parameters and caches data successfully - set() uses Config to determine expiration times - invalidate() deletes specific cache entries - invalidate() with page only clears all per_page variations using wpdb - invalidate() with no params calls invalidate_all() - invalidate_all() removes all cache entries via database query - Proper error handling when wpdb is unavailable Tests use Brain Monkey for WordPress function mocking and Mockery for object dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Application/Cache/Manager_Test.php | 501 ++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php new file mode 100644 index 00000000000..11d4eedb79d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php @@ -0,0 +1,501 @@ +config = Mockery::mock( Config::class ); + $this->instance = new Manager( $this->config ); + } + + /** + * Tests if the constructor sets properties correctly. + * + * @return void + */ + public function test_constructor() { + $this->assertInstanceOf( + Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + } + + /** + * Tests get() returns null when cache is disabled. + * + * @return void + */ + public function test_get_returns_null_when_cache_disabled() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( false ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns null with invalid page number. + * + * @param int $page The page number to test. + * @param int $per_page The per_page number to test. + * + * @dataProvider invalid_page_per_page_provider + * + * @return void + */ + public function test_get_returns_null_with_invalid_parameters( $page, $per_page ) { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + $result = $this->instance->get( $page, $per_page ); + + $this->assertNull( $result ); + } + + /** + * Data provider for invalid page and per_page values. + * + * @return Generator + */ + public static function invalid_page_per_page_provider() { + yield 'Zero page' => [ + 'page' => 0, + 'per_page' => 10, + ]; + yield 'Negative page' => [ + 'page' => -1, + 'per_page' => 10, + ]; + yield 'Zero per_page' => [ + 'page' => 1, + 'per_page' => 0, + ]; + yield 'Negative per_page' => [ + 'page' => 1, + 'per_page' => -5, + ]; + } + + /** + * Tests get() returns null when transient returns false (cache miss). + * + * @return void + */ + public function test_get_returns_null_on_cache_miss() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( false ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns null and deletes transient when data is not an array. + * + * @return void + */ + public function test_get_returns_null_and_deletes_corrupted_cache() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( 'invalid_data' ); + + Monkey\Functions\expect( 'delete_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( true ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns cached data successfully. + * + * @return void + */ + public function test_get_returns_cached_data() { + $cached_data = [ 'item1', 'item2', 'item3' ]; + + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( $cached_data ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertSame( $cached_data, $result ); + } + + /** + * Tests get() returns cached data with various page/per_page combinations. + * + * @param int $page The page number. + * @param int $per_page The items per page. + * @param string $expected_key The expected cache key. + * @param array $cached_data The cached data to return. + * + * @dataProvider get_cache_data_provider + * + * @return void + */ + public function test_get_with_various_parameters( $page, $per_page, $expected_key, $cached_data ) { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( $expected_key ) + ->andReturn( $cached_data ); + + $result = $this->instance->get( $page, $per_page ); + + $this->assertSame( $cached_data, $result ); + } + + /** + * Data provider for get() with various parameters. + * + * @return Generator + */ + public static function get_cache_data_provider() { + yield 'First page, 10 items' => [ + 'page' => 1, + 'per_page' => 10, + 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', + 'cached_data' => [ 'data1' ], + ]; + yield 'Second page, 20 items' => [ + 'page' => 2, + 'per_page' => 20, + 'expected_key' => 'yoast_schema_aggregator_page_2_per_20_v1', + 'cached_data' => [ 'data2', 'data3' ], + ]; + yield 'Large page number' => [ + 'page' => 100, + 'per_page' => 50, + 'expected_key' => 'yoast_schema_aggregator_page_100_per_50_v1', + 'cached_data' => [ 'data100' ], + ]; + } + + /** + * Tests set() returns false with invalid parameters. + * + * @param int $page The page number. + * @param int $per_page The items per page. + * @param array $data The data to cache. + * + * @dataProvider invalid_set_parameters_provider + * + * @return void + */ + public function test_set_returns_false_with_invalid_parameters( $page, $per_page, $data ) { + $result = $this->instance->set( $page, $per_page, $data ); + + $this->assertFalse( $result ); + } + + /** + * Data provider for invalid set() parameters. + * + * @return Generator + */ + public static function invalid_set_parameters_provider() { + yield 'Zero page' => [ + 'page' => 0, + 'per_page' => 10, + 'data' => [ 'test' ], + ]; + yield 'Negative page' => [ + 'page' => -1, + 'per_page' => 10, + 'data' => [ 'test' ], + ]; + yield 'Zero per_page' => [ + 'page' => 1, + 'per_page' => 0, + 'data' => [ 'test' ], + ]; + yield 'Negative per_page' => [ + 'page' => 1, + 'per_page' => -5, + 'data' => [ 'test' ], + ]; + } + + /** + * Tests set() caches data successfully. + * + * @return void + */ + public function test_set_caches_data_successfully() { + $data = [ 'item1', 'item2' ]; + $expiration = 3600; + + $this->config->expects( 'get_expiration' ) + ->once() + ->with( $data ) + ->andReturn( $expiration ); + + Monkey\Functions\expect( 'set_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1', $data, $expiration ) + ->andReturn( true ); + + $result = $this->instance->set( 1, 10, $data ); + + $this->assertTrue( $result ); + } + + /** + * Tests set() with various data and parameters. + * + * @param int $page The page number. + * @param int $per_page The items per page. + * @param array $data The data to cache. + * @param int $expiration The expiration time. + * @param string $expected_key The expected cache key. + * + * @dataProvider set_cache_data_provider + * + * @return void + */ + public function test_set_with_various_parameters( $page, $per_page, $data, $expiration, $expected_key ) { + $this->config->expects( 'get_expiration' ) + ->once() + ->with( $data ) + ->andReturn( $expiration ); + + Monkey\Functions\expect( 'set_transient' ) + ->once() + ->with( $expected_key, $data, $expiration ) + ->andReturn( true ); + + $result = $this->instance->set( $page, $per_page, $data ); + + $this->assertTrue( $result ); + } + + /** + * Data provider for set() with various parameters. + * + * @return Generator + */ + public static function set_cache_data_provider() { + yield 'Small data, short expiration' => [ + 'page' => 1, + 'per_page' => 10, + 'data' => [ 'small' ], + 'expiration' => 1800, + 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', + ]; + yield 'Large data, long expiration' => [ + 'page' => 2, + 'per_page' => 50, + 'data' => \array_fill( 0, 100, 'large_data' ), + 'expiration' => 21600, + 'expected_key' => 'yoast_schema_aggregator_page_2_per_50_v1', + ]; + } + + /** + * Tests invalidate() deletes specific cache entry. + * + * @return void + */ + public function test_invalidate_deletes_specific_entry() { + Monkey\Functions\expect( 'delete_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( true ); + + $result = $this->instance->invalidate( 1, 10 ); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate() with only page parameter clears all per_page variations. + * + * @return void + */ + public function test_invalidate_clears_all_per_page_variations_for_page() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->with( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + '_transient_yoast_schema_aggregator_page_1_per_%', + '_transient_timeout_yoast_schema_aggregator_page_1_per_%' + ) + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( 5 ); + + $result = $this->instance->invalidate( 1, null ); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate() returns false when wpdb is not available. + * + * @return void + */ + public function test_invalidate_returns_false_when_wpdb_not_available() { + global $wpdb; + $wpdb = null; + + $result = $this->instance->invalidate( 1, null ); + + $this->assertFalse( $result ); + } + + /** + * Tests invalidate() with no parameters calls invalidate_all(). + * + * @return void + */ + public function test_invalidate_with_no_parameters_calls_invalidate_all() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( 10 ); + + $result = $this->instance->invalidate( null, null ); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate_all() deletes all cache entries. + * + * @return void + */ + public function test_invalidate_all_deletes_all_entries() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->with( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + '_transient_yoast_schema_aggregator_page_%', + '_transient_timeout_yoast_schema_aggregator_page_%' + ) + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( 20 ); + + $result = $this->instance->invalidate_all(); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate_all() returns false when wpdb is not available. + * + * @return void + */ + public function test_invalidate_all_returns_false_when_wpdb_not_available() { + global $wpdb; + $wpdb = null; + + $result = $this->instance->invalidate_all(); + + $this->assertFalse( $result ); + } + + /** + * Tests invalidate_all() returns false when query fails. + * + * @return void + */ + public function test_invalidate_all_returns_false_when_query_fails() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( false ); + + $result = $this->instance->invalidate_all(); + + $this->assertFalse( $result ); + } +} From 4279d13b34c36ddf2985e6637dd3985f04252502 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 4 Dec 2025 15:48:41 +0100 Subject: [PATCH 152/319] Refactor Cache Manager tests into separate files per method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the monolithic Manager_Test.php into multiple test files following the Llms_Txt pattern: - Abstract_Manager_Test.php - Base class with shared setup (Config mock, instance) - Constructor_Test.php - Tests constructor initialization - Get_Test.php - Tests get() method with cache scenarios - Set_Test.php - Tests set() method with validation and caching - Invalidate_Test.php - Tests invalidate() with various parameters - Invalidate_All_Test.php - Tests invalidate_all() method This structure improves test organization and maintainability while maintaining full coverage (26 tests, 111 assertions). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Cache/Abstract_Manager_Test.php | 41 ++ .../Application/Cache/Constructor_Test.php | 28 + .../Application/Cache/Get_Test.php | 185 +++++++ .../Application/Cache/Invalidate_All_Test.php | 83 +++ .../Application/Cache/Invalidate_Test.php | 101 ++++ .../Application/Cache/Manager_Test.php | 501 ------------------ .../Application/Cache/Set_Test.php | 138 +++++ 7 files changed, 576 insertions(+), 501 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Abstract_Manager_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php delete mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Abstract_Manager_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Abstract_Manager_Test.php new file mode 100644 index 00000000000..eb55b585ef8 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Abstract_Manager_Test.php @@ -0,0 +1,41 @@ +config = Mockery::mock( Config::class ); + $this->instance = new Manager( $this->config ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php new file mode 100644 index 00000000000..7d7a767fe09 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php @@ -0,0 +1,28 @@ +assertInstanceOf( + Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php new file mode 100644 index 00000000000..5e7025c08f5 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php @@ -0,0 +1,185 @@ +config->expects( 'cache_enabled' )->once()->andReturn( false ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns null with invalid page number. + * + * @param int $page The page number to test. + * @param int $per_page The per_page number to test. + * + * @dataProvider invalid_page_per_page_provider + * + * @return void + */ + public function test_get_returns_null_with_invalid_parameters( $page, $per_page ) { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + $result = $this->instance->get( $page, $per_page ); + + $this->assertNull( $result ); + } + + /** + * Data provider for invalid page and per_page values. + * + * @return Generator + */ + public static function invalid_page_per_page_provider() { + yield 'Zero page' => [ + 'page' => 0, + 'per_page' => 10, + ]; + yield 'Negative page' => [ + 'page' => -1, + 'per_page' => 10, + ]; + yield 'Zero per_page' => [ + 'page' => 1, + 'per_page' => 0, + ]; + yield 'Negative per_page' => [ + 'page' => 1, + 'per_page' => -5, + ]; + } + + /** + * Tests get() returns null when transient returns false (cache miss). + * + * @return void + */ + public function test_get_returns_null_on_cache_miss() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( false ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns null and deletes transient when data is not an array. + * + * @return void + */ + public function test_get_returns_null_and_deletes_corrupted_cache() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( 'invalid_data' ); + + Monkey\Functions\expect( 'delete_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( true ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns cached data successfully. + * + * @return void + */ + public function test_get_returns_cached_data() { + $cached_data = [ 'item1', 'item2', 'item3' ]; + + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( $cached_data ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertSame( $cached_data, $result ); + } + + /** + * Tests get() returns cached data with various page/per_page combinations. + * + * @param int $page The page number. + * @param int $per_page The items per page. + * @param string $expected_key The expected cache key. + * @param array $cached_data The cached data to return. + * + * @dataProvider get_cache_data_provider + * + * @return void + */ + public function test_get_with_various_parameters( $page, $per_page, $expected_key, $cached_data ) { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( $expected_key ) + ->andReturn( $cached_data ); + + $result = $this->instance->get( $page, $per_page ); + + $this->assertSame( $cached_data, $result ); + } + + /** + * Data provider for get() with various parameters. + * + * @return Generator + */ + public static function get_cache_data_provider() { + yield 'First page, 10 items' => [ + 'page' => 1, + 'per_page' => 10, + 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', + 'cached_data' => [ 'data1' ], + ]; + yield 'Second page, 20 items' => [ + 'page' => 2, + 'per_page' => 20, + 'expected_key' => 'yoast_schema_aggregator_page_2_per_20_v1', + 'cached_data' => [ 'data2', 'data3' ], + ]; + yield 'Large page number' => [ + 'page' => 100, + 'per_page' => 50, + 'expected_key' => 'yoast_schema_aggregator_page_100_per_50_v1', + 'cached_data' => [ 'data100' ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php new file mode 100644 index 00000000000..5f8434c6ec0 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php @@ -0,0 +1,83 @@ +options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->with( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + '_transient_yoast_schema_aggregator_page_%', + '_transient_timeout_yoast_schema_aggregator_page_%' + ) + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( 20 ); + + $result = $this->instance->invalidate_all(); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate_all() returns false when wpdb is not available. + * + * @return void + */ + public function test_invalidate_all_returns_false_when_wpdb_not_available() { + global $wpdb; + $wpdb = null; + + $result = $this->instance->invalidate_all(); + + $this->assertFalse( $result ); + } + + /** + * Tests invalidate_all() returns false when query fails. + * + * @return void + */ + public function test_invalidate_all_returns_false_when_query_fails() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( false ); + + $result = $this->instance->invalidate_all(); + + $this->assertFalse( $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php new file mode 100644 index 00000000000..1dd30751995 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php @@ -0,0 +1,101 @@ +once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andReturn( true ); + + $result = $this->instance->invalidate( 1, 10 ); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate() with only page parameter clears all per_page variations. + * + * @return void + */ + public function test_invalidate_clears_all_per_page_variations_for_page() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->with( + "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", + '_transient_yoast_schema_aggregator_page_1_per_%', + '_transient_timeout_yoast_schema_aggregator_page_1_per_%' + ) + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( 5 ); + + $result = $this->instance->invalidate( 1, null ); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate() returns false when wpdb is not available. + * + * @return void + */ + public function test_invalidate_returns_false_when_wpdb_not_available() { + global $wpdb; + $wpdb = null; + + $result = $this->instance->invalidate( 1, null ); + + $this->assertFalse( $result ); + } + + /** + * Tests invalidate() with no parameters calls invalidate_all(). + * + * @return void + */ + public function test_invalidate_with_no_parameters_calls_invalidate_all() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andReturn( 10 ); + + $result = $this->instance->invalidate( null, null ); + + $this->assertTrue( $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php deleted file mode 100644 index 11d4eedb79d..00000000000 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Manager_Test.php +++ /dev/null @@ -1,501 +0,0 @@ -config = Mockery::mock( Config::class ); - $this->instance = new Manager( $this->config ); - } - - /** - * Tests if the constructor sets properties correctly. - * - * @return void - */ - public function test_constructor() { - $this->assertInstanceOf( - Config::class, - $this->getPropertyValue( $this->instance, 'config' ) - ); - } - - /** - * Tests get() returns null when cache is disabled. - * - * @return void - */ - public function test_get_returns_null_when_cache_disabled() { - $this->config->expects( 'cache_enabled' )->once()->andReturn( false ); - - $result = $this->instance->get( 1, 10 ); - - $this->assertNull( $result ); - } - - /** - * Tests get() returns null with invalid page number. - * - * @param int $page The page number to test. - * @param int $per_page The per_page number to test. - * - * @dataProvider invalid_page_per_page_provider - * - * @return void - */ - public function test_get_returns_null_with_invalid_parameters( $page, $per_page ) { - $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); - - $result = $this->instance->get( $page, $per_page ); - - $this->assertNull( $result ); - } - - /** - * Data provider for invalid page and per_page values. - * - * @return Generator - */ - public static function invalid_page_per_page_provider() { - yield 'Zero page' => [ - 'page' => 0, - 'per_page' => 10, - ]; - yield 'Negative page' => [ - 'page' => -1, - 'per_page' => 10, - ]; - yield 'Zero per_page' => [ - 'page' => 1, - 'per_page' => 0, - ]; - yield 'Negative per_page' => [ - 'page' => 1, - 'per_page' => -5, - ]; - } - - /** - * Tests get() returns null when transient returns false (cache miss). - * - * @return void - */ - public function test_get_returns_null_on_cache_miss() { - $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); - - Monkey\Functions\expect( 'get_transient' ) - ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) - ->andReturn( false ); - - $result = $this->instance->get( 1, 10 ); - - $this->assertNull( $result ); - } - - /** - * Tests get() returns null and deletes transient when data is not an array. - * - * @return void - */ - public function test_get_returns_null_and_deletes_corrupted_cache() { - $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); - - Monkey\Functions\expect( 'get_transient' ) - ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) - ->andReturn( 'invalid_data' ); - - Monkey\Functions\expect( 'delete_transient' ) - ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) - ->andReturn( true ); - - $result = $this->instance->get( 1, 10 ); - - $this->assertNull( $result ); - } - - /** - * Tests get() returns cached data successfully. - * - * @return void - */ - public function test_get_returns_cached_data() { - $cached_data = [ 'item1', 'item2', 'item3' ]; - - $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); - - Monkey\Functions\expect( 'get_transient' ) - ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) - ->andReturn( $cached_data ); - - $result = $this->instance->get( 1, 10 ); - - $this->assertSame( $cached_data, $result ); - } - - /** - * Tests get() returns cached data with various page/per_page combinations. - * - * @param int $page The page number. - * @param int $per_page The items per page. - * @param string $expected_key The expected cache key. - * @param array $cached_data The cached data to return. - * - * @dataProvider get_cache_data_provider - * - * @return void - */ - public function test_get_with_various_parameters( $page, $per_page, $expected_key, $cached_data ) { - $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); - - Monkey\Functions\expect( 'get_transient' ) - ->once() - ->with( $expected_key ) - ->andReturn( $cached_data ); - - $result = $this->instance->get( $page, $per_page ); - - $this->assertSame( $cached_data, $result ); - } - - /** - * Data provider for get() with various parameters. - * - * @return Generator - */ - public static function get_cache_data_provider() { - yield 'First page, 10 items' => [ - 'page' => 1, - 'per_page' => 10, - 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', - 'cached_data' => [ 'data1' ], - ]; - yield 'Second page, 20 items' => [ - 'page' => 2, - 'per_page' => 20, - 'expected_key' => 'yoast_schema_aggregator_page_2_per_20_v1', - 'cached_data' => [ 'data2', 'data3' ], - ]; - yield 'Large page number' => [ - 'page' => 100, - 'per_page' => 50, - 'expected_key' => 'yoast_schema_aggregator_page_100_per_50_v1', - 'cached_data' => [ 'data100' ], - ]; - } - - /** - * Tests set() returns false with invalid parameters. - * - * @param int $page The page number. - * @param int $per_page The items per page. - * @param array $data The data to cache. - * - * @dataProvider invalid_set_parameters_provider - * - * @return void - */ - public function test_set_returns_false_with_invalid_parameters( $page, $per_page, $data ) { - $result = $this->instance->set( $page, $per_page, $data ); - - $this->assertFalse( $result ); - } - - /** - * Data provider for invalid set() parameters. - * - * @return Generator - */ - public static function invalid_set_parameters_provider() { - yield 'Zero page' => [ - 'page' => 0, - 'per_page' => 10, - 'data' => [ 'test' ], - ]; - yield 'Negative page' => [ - 'page' => -1, - 'per_page' => 10, - 'data' => [ 'test' ], - ]; - yield 'Zero per_page' => [ - 'page' => 1, - 'per_page' => 0, - 'data' => [ 'test' ], - ]; - yield 'Negative per_page' => [ - 'page' => 1, - 'per_page' => -5, - 'data' => [ 'test' ], - ]; - } - - /** - * Tests set() caches data successfully. - * - * @return void - */ - public function test_set_caches_data_successfully() { - $data = [ 'item1', 'item2' ]; - $expiration = 3600; - - $this->config->expects( 'get_expiration' ) - ->once() - ->with( $data ) - ->andReturn( $expiration ); - - Monkey\Functions\expect( 'set_transient' ) - ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1', $data, $expiration ) - ->andReturn( true ); - - $result = $this->instance->set( 1, 10, $data ); - - $this->assertTrue( $result ); - } - - /** - * Tests set() with various data and parameters. - * - * @param int $page The page number. - * @param int $per_page The items per page. - * @param array $data The data to cache. - * @param int $expiration The expiration time. - * @param string $expected_key The expected cache key. - * - * @dataProvider set_cache_data_provider - * - * @return void - */ - public function test_set_with_various_parameters( $page, $per_page, $data, $expiration, $expected_key ) { - $this->config->expects( 'get_expiration' ) - ->once() - ->with( $data ) - ->andReturn( $expiration ); - - Monkey\Functions\expect( 'set_transient' ) - ->once() - ->with( $expected_key, $data, $expiration ) - ->andReturn( true ); - - $result = $this->instance->set( $page, $per_page, $data ); - - $this->assertTrue( $result ); - } - - /** - * Data provider for set() with various parameters. - * - * @return Generator - */ - public static function set_cache_data_provider() { - yield 'Small data, short expiration' => [ - 'page' => 1, - 'per_page' => 10, - 'data' => [ 'small' ], - 'expiration' => 1800, - 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', - ]; - yield 'Large data, long expiration' => [ - 'page' => 2, - 'per_page' => 50, - 'data' => \array_fill( 0, 100, 'large_data' ), - 'expiration' => 21600, - 'expected_key' => 'yoast_schema_aggregator_page_2_per_50_v1', - ]; - } - - /** - * Tests invalidate() deletes specific cache entry. - * - * @return void - */ - public function test_invalidate_deletes_specific_entry() { - Monkey\Functions\expect( 'delete_transient' ) - ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) - ->andReturn( true ); - - $result = $this->instance->invalidate( 1, 10 ); - - $this->assertTrue( $result ); - } - - /** - * Tests invalidate() with only page parameter clears all per_page variations. - * - * @return void - */ - public function test_invalidate_clears_all_per_page_variations_for_page() { - global $wpdb; - $wpdb = Mockery::mock( 'wpdb' ); - $wpdb->options = 'wp_options'; - - $wpdb->expects( 'prepare' ) - ->once() - ->with( - "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", - '_transient_yoast_schema_aggregator_page_1_per_%', - '_transient_timeout_yoast_schema_aggregator_page_1_per_%' - ) - ->andReturn( 'PREPARED_QUERY' ); - - $wpdb->expects( 'query' ) - ->once() - ->with( 'PREPARED_QUERY' ) - ->andReturn( 5 ); - - $result = $this->instance->invalidate( 1, null ); - - $this->assertTrue( $result ); - } - - /** - * Tests invalidate() returns false when wpdb is not available. - * - * @return void - */ - public function test_invalidate_returns_false_when_wpdb_not_available() { - global $wpdb; - $wpdb = null; - - $result = $this->instance->invalidate( 1, null ); - - $this->assertFalse( $result ); - } - - /** - * Tests invalidate() with no parameters calls invalidate_all(). - * - * @return void - */ - public function test_invalidate_with_no_parameters_calls_invalidate_all() { - global $wpdb; - $wpdb = Mockery::mock( 'wpdb' ); - $wpdb->options = 'wp_options'; - - $wpdb->expects( 'prepare' ) - ->once() - ->andReturn( 'PREPARED_QUERY' ); - - $wpdb->expects( 'query' ) - ->once() - ->with( 'PREPARED_QUERY' ) - ->andReturn( 10 ); - - $result = $this->instance->invalidate( null, null ); - - $this->assertTrue( $result ); - } - - /** - * Tests invalidate_all() deletes all cache entries. - * - * @return void - */ - public function test_invalidate_all_deletes_all_entries() { - global $wpdb; - $wpdb = Mockery::mock( 'wpdb' ); - $wpdb->options = 'wp_options'; - - $wpdb->expects( 'prepare' ) - ->once() - ->with( - "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", - '_transient_yoast_schema_aggregator_page_%', - '_transient_timeout_yoast_schema_aggregator_page_%' - ) - ->andReturn( 'PREPARED_QUERY' ); - - $wpdb->expects( 'query' ) - ->once() - ->with( 'PREPARED_QUERY' ) - ->andReturn( 20 ); - - $result = $this->instance->invalidate_all(); - - $this->assertTrue( $result ); - } - - /** - * Tests invalidate_all() returns false when wpdb is not available. - * - * @return void - */ - public function test_invalidate_all_returns_false_when_wpdb_not_available() { - global $wpdb; - $wpdb = null; - - $result = $this->instance->invalidate_all(); - - $this->assertFalse( $result ); - } - - /** - * Tests invalidate_all() returns false when query fails. - * - * @return void - */ - public function test_invalidate_all_returns_false_when_query_fails() { - global $wpdb; - $wpdb = Mockery::mock( 'wpdb' ); - $wpdb->options = 'wp_options'; - - $wpdb->expects( 'prepare' ) - ->once() - ->andReturn( 'PREPARED_QUERY' ); - - $wpdb->expects( 'query' ) - ->once() - ->with( 'PREPARED_QUERY' ) - ->andReturn( false ); - - $result = $this->instance->invalidate_all(); - - $this->assertFalse( $result ); - } -} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php new file mode 100644 index 00000000000..5c35ac3f199 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php @@ -0,0 +1,138 @@ + $data The data to cache. + * + * @dataProvider invalid_set_parameters_provider + * + * @return void + */ + public function test_set_returns_false_with_invalid_parameters( $page, $per_page, $data ) { + $result = $this->instance->set( $page, $per_page, $data ); + + $this->assertFalse( $result ); + } + + /** + * Data provider for invalid set() parameters. + * + * @return Generator + */ + public static function invalid_set_parameters_provider() { + yield 'Zero page' => [ + 'page' => 0, + 'per_page' => 10, + 'data' => [ 'test' ], + ]; + yield 'Negative page' => [ + 'page' => -1, + 'per_page' => 10, + 'data' => [ 'test' ], + ]; + yield 'Zero per_page' => [ + 'page' => 1, + 'per_page' => 0, + 'data' => [ 'test' ], + ]; + yield 'Negative per_page' => [ + 'page' => 1, + 'per_page' => -5, + 'data' => [ 'test' ], + ]; + } + + /** + * Tests set() caches data successfully. + * + * @return void + */ + public function test_set_caches_data_successfully() { + $data = [ 'item1', 'item2' ]; + $expiration = 3600; + + $this->config->expects( 'get_expiration' ) + ->once() + ->with( $data ) + ->andReturn( $expiration ); + + Monkey\Functions\expect( 'set_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1', $data, $expiration ) + ->andReturn( true ); + + $result = $this->instance->set( 1, 10, $data ); + + $this->assertTrue( $result ); + } + + /** + * Tests set() with various data and parameters. + * + * @param int $page The page number. + * @param int $per_page The items per page. + * @param array $data The data to cache. + * @param int $expiration The expiration time. + * @param string $expected_key The expected cache key. + * + * @dataProvider set_cache_data_provider + * + * @return void + */ + public function test_set_with_various_parameters( $page, $per_page, $data, $expiration, $expected_key ) { + $this->config->expects( 'get_expiration' ) + ->once() + ->with( $data ) + ->andReturn( $expiration ); + + Monkey\Functions\expect( 'set_transient' ) + ->once() + ->with( $expected_key, $data, $expiration ) + ->andReturn( true ); + + $result = $this->instance->set( $page, $per_page, $data ); + + $this->assertTrue( $result ); + } + + /** + * Data provider for set() with various parameters. + * + * @return Generator + */ + public static function set_cache_data_provider() { + yield 'Small data, short expiration' => [ + 'page' => 1, + 'per_page' => 10, + 'data' => [ 'small' ], + 'expiration' => 1800, + 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', + ]; + yield 'Large data, long expiration' => [ + 'page' => 2, + 'per_page' => 50, + 'data' => \array_fill( 0, 100, 'large_data' ), + 'expiration' => 21600, + 'expected_key' => 'yoast_schema_aggregator_page_2_per_50_v1', + ]; + } +} From 68b70c5c4afdddf9f6e89f245f8d858df04a354c Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 4 Dec 2025 16:13:02 +0100 Subject: [PATCH 153/319] Add piece-specific conditional filtering --- .../schema-node-filter-interface.php | 22 +++++++ .../webpage-schema-node-filter.php | 58 +++++++++++++++++++ .../website-schema-node-filter.php | 31 ++++++++++ 3 files changed, 111 insertions(+) create mode 100644 src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php create mode 100644 src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php create mode 100644 src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php new file mode 100644 index 00000000000..c6c8ac48f07 --- /dev/null +++ b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php @@ -0,0 +1,22 @@ + $schema The full schema. + * @param Schema_Piece $schema_piece The schema piece to be filtered. + * + * @return bool True if the schema piece should be kept, false otherwise. + */ + public function filter( array $schema, Schema_Piece $schema_piece ): bool; +} diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php new file mode 100644 index 00000000000..10ef177d734 --- /dev/null +++ b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php @@ -0,0 +1,58 @@ + + */ + private $articles_ids; + + /** + * Filters a WebPage schema piece if it contains an Article. + * + * @param array $schema The full schema. + * @param Schema_Piece $schema_piece The schema piece to be filtered. + * + * @return bool True if the schema piece should be kept, false otherwise. + */ + public function filter( array $schema, Schema_Piece $schema_piece ): bool { + $data = $schema_piece->get_data(); + $articles_ids = $this->get_articles_ids( $schema ); + foreach ( $articles_ids as $article_id ) { + if ( \str_contains( $article_id, $data['@id'] ) ) { + return false; + } + } + return true; + } + + /** + * Retrieves the IDs of all Article schema pieces in the schema. + * + * @param array $schema The full schema. + * + * @return array The IDs of the Article schema pieces. + */ + private function get_articles_ids( array $schema ): array { + if ( ! \is_array( $this->articles_ids ) ) { + $this->articles_ids = []; + foreach ( $schema as $schema_piece ) { + if ( $schema_piece->get_type() === 'Article' ) { + $schema_piece_data = $schema_piece->get_data(); + $this->articles_ids[] = $schema_piece_data['@id']; + } + } + } + return $this->articles_ids; + } +} diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php new file mode 100644 index 00000000000..2c8cb7665a0 --- /dev/null +++ b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php @@ -0,0 +1,31 @@ + $schema The full schema. + * @param Schema_Piece $schema_piece The schema piece to be filtered. + * + * @return bool True if the schema piece should be kept, false otherwise. + */ + public function filter( array $schema, Schema_Piece $schema_piece ): bool { + // Shall we support multisite here? + $blog_id = \get_current_blog_id(); + $blog_url = \trailingslashit( \get_home_url( $blog_id ) ); + $data = $schema_piece->get_data(); + if ( $data['url'] === $blog_url ) { + return false; + } + return true; + } +} From d17f0582b1685f6ea3aff310b425eb61f0f0f60b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 4 Dec 2025 16:13:16 +0100 Subject: [PATCH 154/319] Add piece-specific properties filtering --- .../article-schema-node-property-filter.php | 33 +++++++++++++ .../base-schema-node-property-filter.php | 48 +++++++++++++++++++ .../schema-node-property-filter-interface.php | 21 ++++++++ .../webpage-schema-node-property-filter.php | 33 +++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php create mode 100644 src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php create mode 100644 src/schema-aggregator/application/filtering/schema-node-property-filter/schema-node-property-filter-interface.php create mode 100644 src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php new file mode 100644 index 00000000000..cb43238c110 --- /dev/null +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php @@ -0,0 +1,33 @@ +get_data(); + + // Remove the article body to reduce schema size. + if ( isset( $data['mainEntityOfPage'] ) ) { + unset( $data['mainEntityOfPage'] ); + } + + return new Schema_Piece( $data, $filtered_piece->get_type() ); + } +} diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php new file mode 100644 index 00000000000..6d037217b18 --- /dev/null +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php @@ -0,0 +1,48 @@ + + */ + private const PROPERTIES_AVOID_LIST = [ 'potentialAction', 'isPartOf' ]; + + /** + * Filters any schema piece properties. + * + * @param Schema_Piece $schema_piece The schema piece to be filtered. + * + * @return Schema_Piece The filtered schema piece. + */ + public function filter_properties( Schema_Piece $schema_piece ): Schema_Piece { + $data = $schema_piece->get_data(); + + foreach ( $this->get_properties_avoid_list() as $property ) { + if ( isset( $data[ $property ] ) ) { + unset( $data[ $property ] ); + } + } + + return new Schema_Piece( $data, $schema_piece->get_type() ); + } + + /** + * Gets the properties avoid list. + * + * @return array The properties avoid list. + */ + private function get_properties_avoid_list(): array { + return self::PROPERTIES_AVOID_LIST; + } +} diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/schema-node-property-filter-interface.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/schema-node-property-filter-interface.php new file mode 100644 index 00000000000..16b397e76ff --- /dev/null +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/schema-node-property-filter-interface.php @@ -0,0 +1,21 @@ +get_data(); + + // Remove the article body to reduce schema size. + if ( isset( $data['breadcrumb'] ) ) { + unset( $data['breadcrumb'] ); + } + + return new Schema_Piece( $data, $filtered_piece->get_type() ); + } +} From 2b67f094aa68f5b3e3aef024483c44cee57a4d94 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 4 Dec 2025 16:13:37 +0100 Subject: [PATCH 155/319] The default filtering logic --- .../application/filtering/default-filter.php | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index f112f46d3ff..2b553be82dd 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -1,5 +1,5 @@ + */ + private $filter_categories = [ + 'action', + 'enumeration', + 'meta', + 'website', + ]; + /** * The elements context map repository. * @@ -34,8 +46,30 @@ public function __construct( Elements_Context_Map_Repository_Interface $elements * @return array The filtered schema. */ public function filter( array $schema ): array { + $filtered_schema = []; $elements_context_map = $this->elements_context_map_repository->get_map(); - // Use the map. - return $schema; + foreach ( $schema as $schema_piece ) { + $should_keep = true; + foreach ( $this->filter_categories as $category ) { + if ( \in_array( $schema_piece->get_type(), $elements_context_map[ $category ], true ) ) { + $filter_class_name = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\\' . $schema_piece->get_type() . '_Schema_Node_Filter'; + if ( \class_exists( $filter_class_name ) && \is_a( $filter_class_name, 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\Schema_Node_Filter_Interface', true ) ) { + $should_keep = ( new $filter_class_name() )->filter( $schema, $schema_piece ); + } + else { + $should_keep = false; + } + break; + } + } + if ( $should_keep ) { + $properties_filter_class_name = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\\' . $schema_piece->get_type() . '_Schema_Node_Property_Filter'; + if ( \class_exists( $properties_filter_class_name ) && \is_a( $properties_filter_class_name, 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\Schema_Node_Property_Filter_Interface', true ) ) { + $schema_piece = ( new $properties_filter_class_name() )->filter_properties( $schema_piece ); + } + $filtered_schema[] = $schema_piece; + } + } + return $filtered_schema; } } From cc155ae19fdbf3a2ddf86b734ccfb328f6be03cf Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 4 Dec 2025 16:14:26 +0100 Subject: [PATCH 156/319] Fix bug about missing constructor parameter for Default_Filter class --- .../infrastructure/filtering-strategy-factory.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php index 002ede2953f..5af027a8ebc 100644 --- a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php +++ b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php @@ -4,6 +4,8 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Default_Filter; use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Filtering_Strategy_Interface; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Base_Map_Loader; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Elements_Context_Map_Repository; /** * Factory for creating filtering strategy instances. @@ -18,10 +20,13 @@ class Filtering_Strategy_Factory { public function create(): Filtering_Strategy_Interface { $filtering_class = \apply_filters( 'wpseo_schema_aggregator_filtering_strategy', Default_Filter::class ); + $map_loader = new Base_Map_Loader(); + $elements_context_map_repository = new Elements_Context_Map_Repository( $map_loader ); + if ( \is_a( $filtering_class, Filtering_Strategy_Interface::class, true ) ) { - return new $filtering_class(); + return new $filtering_class( $elements_context_map_repository ); } - return new Default_Filter(); + return new Default_Filter( $elements_context_map_repository ); } } From f6b7f7154019f7ca6e7d79d51aaeb695001c22d9 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 4 Dec 2025 16:14:40 +0100 Subject: [PATCH 157/319] Remove unused code --- .../application/properties-filter.php | 58 ------------------- .../application/schema-pieces-aggregator.php | 13 +---- .../infrastructure/aggregator-config.php | 22 ------- 3 files changed, 1 insertion(+), 92 deletions(-) delete mode 100644 src/schema-aggregator/application/properties-filter.php diff --git a/src/schema-aggregator/application/properties-filter.php b/src/schema-aggregator/application/properties-filter.php deleted file mode 100644 index 6b6e58a342f..00000000000 --- a/src/schema-aggregator/application/properties-filter.php +++ /dev/null @@ -1,58 +0,0 @@ -config = $config; - } - - /** - * Remove properties that reference filtered-out entity types - * - * Removes properties like 'breadcrumb' that reference BreadcrumbList entities - * which have been filtered out from the allowed types. - * - * Also removes 'potentialAction' properties (ReadAction, CommentAction, SearchAction) - * which are added by Yoast but not needed for schema aggregation integration. - * - * @param Schema_Piece $piece The schema piece. - * - * @return Schema_Piece Cleaned schema piece. - */ - public function filter( Schema_Piece $piece ): Schema_Piece { - - $properties_to_remove = $this->config->get_properties_avoid_list(); - $data = $piece->get_data(); - - foreach ( $properties_to_remove as $property ) { - if ( isset( $data[ $property ] ) ) { - unset( $data[ $property ] ); - } - } - - return new Schema_Piece( $data, $piece->get_type() ); - } -} diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 7f0137e7622..3e199563ddc 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -16,13 +16,6 @@ */ class Schema_Pieces_Aggregator { - /** - * The properties filter instance. - * - * @var Properties_Filter - */ - private $properties_filter; - /** * The properties merger object * @@ -40,12 +33,10 @@ class Schema_Pieces_Aggregator { /** * Class constructor * - * @param Properties_Filter $properties_filter The properties filter object. * @param Properties_Merger $properties_merger The properties merger object. * @param Filtering_Strategy_Factory $filtering_strategy_factory The filtering strategy factory. */ - public function __construct( Properties_Filter $properties_filter, Properties_Merger $properties_merger, Filtering_Strategy_Factory $filtering_strategy_factory ) { - $this->properties_filter = $properties_filter; + public function __construct( Properties_Merger $properties_merger, Filtering_Strategy_Factory $filtering_strategy_factory ) { $this->properties_merger = $properties_merger; $this->filtering_strategy_factory = $filtering_strategy_factory; } @@ -78,8 +69,6 @@ public function aggregate( array $schema_pieces ): array { // Add new piece. $aggregated_schema[ $id ] = $piece; } - - $aggregated_schema[ $id ] = $this->properties_filter->filter( $aggregated_schema[ $id ] ); } // Return only the values to get rid of the keys (which are @id). diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index 34826ef45b9..a56444c04b8 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -33,13 +33,6 @@ class Aggregator_Config { 'WebSite', ]; - /** - * The default properties to avoid in schema pieces. - * - * @var array - */ - private const PROPERTIES_AVOID_LIST = [ 'breadcrumb', 'potentialAction' ]; - /** * The WooCommerce Conditional. * @@ -88,19 +81,4 @@ public function get_allowed_post_types(): array { return \array_intersect( $post_types, $this->post_type_helper->get_indexable_post_types() ); } - - /** - * Get list of properties to remove from a schema piece. - * - * @return array - */ - public function get_properties_avoid_list(): array { - $properties_avoid_list = \apply_filters( 'wpseo_schema_aggregator_properties_avoid_list', self::PROPERTIES_AVOID_LIST ); - - if ( ! \is_array( $properties_avoid_list ) ) { - return self::PROPERTIES_AVOID_LIST; - } - - return $properties_avoid_list; - } } From 017472389e13358551306545b568d8ee73531859 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 4 Dec 2025 16:17:31 +0100 Subject: [PATCH 158/319] Fix cs --- src/schema-aggregator/application/schema-pieces-aggregator.php | 1 - .../infrastructure/filtering-strategy-factory.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 3e199563ddc..8b2df9fec19 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -1,5 +1,4 @@ Date: Thu, 4 Dec 2025 23:42:59 +0100 Subject: [PATCH 159/319] Pass a filtering strategy instance instead of a class to get rid of the $elements_context_map_repository dependency --- .../infrastructure/filtering-strategy-factory.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php index b9667649649..2ca58003d7a 100644 --- a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php +++ b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php @@ -18,15 +18,16 @@ class Filtering_Strategy_Factory { * @return Filtering_Strategy_Interface The filtering strategy instance. */ public function create(): Filtering_Strategy_Interface { - $filtering_class = \apply_filters( 'wpseo_schema_aggregator_filtering_strategy', Default_Filter::class ); - $map_loader = new Base_Map_Loader(); $elements_context_map_repository = new Elements_Context_Map_Repository( $map_loader ); + $default_filter = new Default_Filter( $elements_context_map_repository ); + + $filtering_strategy = \apply_filters( 'wpseo_schema_aggregator_filtering_strategy', $default_filter ); - if ( \is_a( $filtering_class, Filtering_Strategy_Interface::class, true ) ) { - return new $filtering_class( $elements_context_map_repository ); + if ( $filtering_strategy instanceof Filtering_Strategy_Interface ) { + return $filtering_strategy; } - return new Default_Filter( $elements_context_map_repository ); + return $default_filter; } } From 6bc0e497152dd7647343f5c82dbb526897e7b530 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 5 Dec 2025 10:13:11 +0100 Subject: [PATCH 160/319] Fix cs --- .../application/filtering/filtering-strategy-interface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/filtering/filtering-strategy-interface.php b/src/schema-aggregator/application/filtering/filtering-strategy-interface.php index c764c5d5004..dacb4c102b7 100644 --- a/src/schema-aggregator/application/filtering/filtering-strategy-interface.php +++ b/src/schema-aggregator/application/filtering/filtering-strategy-interface.php @@ -1,5 +1,5 @@ Date: Fri, 5 Dec 2025 15:39:13 +0100 Subject: [PATCH 161/319] Use the Filtered_Map_Loader to allow using WordPress filters to manipulate the element-context map --- .../infrastructure/filtering-strategy-factory.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php index 2ca58003d7a..c175ed8e4bc 100644 --- a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php +++ b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php @@ -5,6 +5,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Default_Filter; use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Filtering_Strategy_Interface; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Base_Map_Loader; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Filtered_Map_Loader; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Elements_Context_Map_Repository; /** @@ -18,7 +19,8 @@ class Filtering_Strategy_Factory { * @return Filtering_Strategy_Interface The filtering strategy instance. */ public function create(): Filtering_Strategy_Interface { - $map_loader = new Base_Map_Loader(); + $base_map_loader = new Base_Map_Loader(); + $map_loader = new Filtered_Map_Loader( $base_map_loader ); $elements_context_map_repository = new Elements_Context_Map_Repository( $map_loader ); $default_filter = new Default_Filter( $elements_context_map_repository ); From 8cbc8a47da60c8571dd0fcb8d03e75374555c98c Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Fri, 5 Dec 2025 15:42:40 +0100 Subject: [PATCH 162/319] Tests for xml manager. --- .../Xml_Manager/Abstract_Xml_Manager_Test.php | 41 +++++ .../Cache/Xml_Manager/Constructor_Test.php | 28 ++++ .../Cache/Xml_Manager/Get_Test.php | 158 ++++++++++++++++++ .../Cache/Xml_Manager/Invalidate_Test.php | 49 ++++++ .../Cache/Xml_Manager/Set_Test.php | 121 ++++++++++++++ 5 files changed, 397 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Abstract_Xml_Manager_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Invalidate_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Abstract_Xml_Manager_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Abstract_Xml_Manager_Test.php new file mode 100644 index 00000000000..e1921f38ba6 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Abstract_Xml_Manager_Test.php @@ -0,0 +1,41 @@ +config = Mockery::mock( Config::class ); + $this->instance = new Xml_Manager( $this->config ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php new file mode 100644 index 00000000000..0d8ca947a25 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php @@ -0,0 +1,28 @@ +assertInstanceOf( + Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php new file mode 100644 index 00000000000..2096d8ae7f1 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php @@ -0,0 +1,158 @@ +config->expects( 'cache_enabled' )->once()->andReturn( false ); + + $result = $this->instance->get(); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns null when transient returns false (cache miss). + * + * @return void + */ + public function test_get_returns_null_on_cache_miss() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andReturn( false ); + + $result = $this->instance->get(); + + $this->assertNull( $result ); + } + + /** + * Tests get() returns null and deletes transient when data is not a string. + * + * @param mixed $corrupted_data The non-string data to test. + * + * @dataProvider corrupted_data_provider + * + * @return void + */ + public function test_get_returns_null_and_deletes_corrupted_cache( $corrupted_data ) { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andReturn( $corrupted_data ); + + Monkey\Functions\expect( 'delete_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andReturn( true ); + + $result = $this->instance->get(); + + $this->assertNull( $result ); + } + + /** + * Data provider for corrupted (non-string) data. + * + * @return Generator + */ + public static function corrupted_data_provider() { + yield 'Integer data' => [ + 'corrupted_data' => 123, + ]; + yield 'Array data' => [ + 'corrupted_data' => [ 'xml' => 'data' ], + ]; + yield 'Boolean data' => [ + 'corrupted_data' => true, + ]; + yield 'Object data' => [ + 'corrupted_data' => (object) [ 'xml' => 'data' ], + ]; + } + + /** + * Tests get() returns cached string data successfully. + * + * @return void + */ + public function test_get_returns_cached_data() { + $cached_data = 'test'; + + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andReturn( $cached_data ); + + $result = $this->instance->get(); + + $this->assertSame( $cached_data, $result ); + } + + /** + * Tests get() returns cached data with various XML strings. + * + * @param string $xml_data The XML data to test. + * + * @dataProvider xml_data_provider + * + * @return void + */ + public function test_get_with_various_xml_data( $xml_data ) { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andReturn( $xml_data ); + + $result = $this->instance->get(); + + $this->assertSame( $xml_data, $result ); + } + + /** + * Data provider for various XML data strings. + * + * @return Generator + */ + public static function xml_data_provider() { + yield 'Simple XML' => [ + 'xml_data' => 'test', + ]; + yield 'XML with attributes' => [ + 'xml_data' => 'data', + ]; + yield 'Empty XML' => [ + 'xml_data' => '', + ]; + yield 'Large XML' => [ + 'xml_data' => \str_repeat( 'content', 100 ), + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Invalidate_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Invalidate_Test.php new file mode 100644 index 00000000000..40a4f4ea396 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Invalidate_Test.php @@ -0,0 +1,49 @@ +once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andReturn( true ); + + $result = $this->instance->invalidate(); + + $this->assertTrue( $result ); + } + + /** + * Tests invalidate() returns false when deletion fails. + * + * @return void + */ + public function test_invalidate_returns_false_when_deletion_fails() { + Monkey\Functions\expect( 'delete_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andReturn( false ); + + $result = $this->instance->invalidate(); + + $this->assertFalse( $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php new file mode 100644 index 00000000000..4c207d87e5f --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php @@ -0,0 +1,121 @@ +test'; + $expiration = 3600; + + $this->config->expects( 'get_expiration' ) + ->once() + ->with( [ $data ] ) + ->andReturn( $expiration ); + + Monkey\Functions\expect( 'set_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1', $data, $expiration ) + ->andReturn( true ); + + $result = $this->instance->set( $data ); + + $this->assertTrue( $result ); + } + + /** + * Tests set() returns false when set_transient fails. + * + * @return void + */ + public function test_set_returns_false_when_transient_fails() { + $data = 'test'; + $expiration = 3600; + + $this->config->expects( 'get_expiration' ) + ->once() + ->with( [ $data ] ) + ->andReturn( $expiration ); + + Monkey\Functions\expect( 'set_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1', $data, $expiration ) + ->andReturn( false ); + + $result = $this->instance->set( $data ); + + $this->assertFalse( $result ); + } + + /** + * Tests set() with various XML data and expiration times. + * + * @param string $data The XML data to cache. + * @param int $expiration The expiration time in seconds. + * @param bool $expected The expected return value. + * + * @dataProvider set_data_provider + * + * @return void + */ + public function test_set_with_various_data( $data, $expiration, $expected ) { + $this->config->expects( 'get_expiration' ) + ->once() + ->with( [ $data ] ) + ->andReturn( $expiration ); + + Monkey\Functions\expect( 'set_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1', $data, $expiration ) + ->andReturn( $expected ); + + $result = $this->instance->set( $data ); + + $this->assertSame( $expected, $result ); + } + + /** + * Data provider for set() with various data and parameters. + * + * @return Generator + */ + public static function set_data_provider() { + yield 'Small XML, short expiration' => [ + 'data' => 'test', + 'expiration' => 1800, + 'expected' => true, + ]; + yield 'Large XML, long expiration' => [ + 'data' => \str_repeat( 'large content here', 500 ), + 'expiration' => 21600, + 'expected' => true, + ]; + yield 'Empty string' => [ + 'data' => '', + 'expiration' => 3600, + 'expected' => true, + ]; + yield 'XML with special characters' => [ + 'data' => 'Data < >', + 'expiration' => 3600, + 'expected' => true, + ]; + } +} From 2cdb12bc0768092b93cd2d39f8253ae764437e54 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 5 Dec 2025 15:54:12 +0100 Subject: [PATCH 163/319] Fix cs --- .../infrastructure/filtering-strategy-factory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php index c175ed8e4bc..b239e912a01 100644 --- a/src/schema-aggregator/infrastructure/filtering-strategy-factory.php +++ b/src/schema-aggregator/infrastructure/filtering-strategy-factory.php @@ -5,8 +5,8 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Default_Filter; use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Filtering_Strategy_Interface; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Base_Map_Loader; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Filtered_Map_Loader; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Elements_Context_Map_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Filtered_Map_Loader; /** * Factory for creating filtering strategy instances. From e458ceb85dc0c644066da3f9432687fd7b217448 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 10:46:47 +0100 Subject: [PATCH 164/319] Start of test for command and handlers. --- ...act_Aggregate_Site_Schema_Command_Test.php | 21 ++ .../Constructor_Test.php | 86 +++++++ .../Get_Page_Controls_Test.php | 30 +++ ...egate_Site_Schema_Command_Handler_Test.php | 64 +++++ .../Constructor_Test.php | 38 +++ .../Handle_Test.php | 127 ++++++++++ ...Aggregate_Site_Schema_Map_Command_Test.php | 98 ++++++++ ...e_Site_Schema_Map_Command_Handler_Test.php | 74 ++++++ .../Constructor_Test.php | 43 ++++ .../Handle_Test.php | 238 ++++++++++++++++++ 10 files changed, 819 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Get_Page_Controls_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Handle_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php new file mode 100644 index 00000000000..5d05f7d7d6e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php @@ -0,0 +1,21 @@ +get_page_controls(); + + $this->assertInstanceOf( Page_Controls::class, $page_controls ); + $this->assertSame( 1, $page_controls->get_page() ); + $this->assertSame( 50, $page_controls->get_page_size() ); + $this->assertSame( 'post', $page_controls->get_post_type() ); + } + + /** + * Tests constructor with various parameters. + * + * @dataProvider page_controls_data_provider + * + * @param int $page The page number. + * @param int $per_page The items per page. + * @param string $post_type The post type. + * + * @return void + */ + public function test_constructor_with_various_parameters( int $page, int $per_page, string $post_type ) { + $command = new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ); + + $page_controls = $command->get_page_controls(); + + $this->assertSame( $page, $page_controls->get_page() ); + $this->assertSame( $per_page, $page_controls->get_page_size() ); + $this->assertSame( $post_type, $page_controls->get_post_type() ); + } + + /** + * Data provider for page controls tests. + * + * @return Generator + */ + public static function page_controls_data_provider() { + yield 'First page of posts' => [ + 'page' => 1, + 'per_page' => 50, + 'post_type' => 'post', + ]; + + yield 'Second page of pages' => [ + 'page' => 2, + 'per_page' => 100, + 'post_type' => 'page', + ]; + + yield 'Custom post type' => [ + 'page' => 3, + 'per_page' => 25, + 'post_type' => 'product', + ]; + + yield 'Large page number' => [ + 'page' => 100, + 'per_page' => 10, + 'post_type' => 'post', + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Get_Page_Controls_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Get_Page_Controls_Test.php new file mode 100644 index 00000000000..31c2b91d888 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Get_Page_Controls_Test.php @@ -0,0 +1,30 @@ +get_page_controls(); + + $this->assertInstanceOf( Page_Controls::class, $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php new file mode 100644 index 00000000000..17a970a9ae1 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php @@ -0,0 +1,64 @@ +schema_piece_repository = Mockery::mock( Schema_Piece_Repository::class ); + $this->schema_piece_aggregator = Mockery::mock( Schema_Pieces_Aggregator::class ); + $this->schema_response_composer = Mockery::mock( Schema_Aggregator_Response_Composer::class ); + + $this->instance = new Aggregate_Site_Schema_Command_Handler( + $this->schema_piece_repository, + $this->schema_piece_aggregator, + $this->schema_response_composer + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php new file mode 100644 index 00000000000..209870c52c6 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php @@ -0,0 +1,38 @@ +assertInstanceOf( + Schema_Piece_Repository::class, + $this->getPropertyValue( $this->instance, 'schema_piece_repository' ) + ); + $this->assertInstanceOf( + Schema_Pieces_Aggregator::class, + $this->getPropertyValue( $this->instance, 'schema_piece_aggregator' ) + ); + $this->assertInstanceOf( + Schema_Aggregator_Response_Composer::class, + $this->getPropertyValue( $this->instance, 'schema_response_composer' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php new file mode 100644 index 00000000000..1af8658f7af --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php @@ -0,0 +1,127 @@ +schema_piece_repository + ->expects( 'get' ) + ->once() + ->with( $page, $per_page, $post_type ) + ->andReturn( $schema_pieces ); + + $this->schema_piece_aggregator + ->expects( 'aggregate' ) + ->once() + ->with( $schema_pieces ) + ->andReturn( $aggregated_pieces ); + + $this->schema_response_composer + ->expects( 'compose' ) + ->once() + ->with( $aggregated_pieces ) + ->andReturn( $composed_response ); + + $result = $this->instance->handle( $command ); + + $this->assertSame( $composed_response, $result ); + } + + /** + * Tests handle method returns array. + * + * @return void + */ + public function test_handle_returns_array() { + $command = new Aggregate_Site_Schema_Command( 1, 50, 'post' ); + + $this->schema_piece_repository + ->expects( 'get' ) + ->andReturn( [] ); + + $this->schema_piece_aggregator + ->expects( 'aggregate' ) + ->andReturn( [] ); + + $this->schema_response_composer + ->expects( 'compose' ) + ->andReturn( [] ); + + $result = $this->instance->handle( $command ); + + $this->assertIsArray( $result ); + } + + /** + * Data provider for handle orchestration tests. + * + * @return Generator + */ + public static function handle_orchestration_provider() { + $schema_piece_1 = new Schema_Piece( [ '@type' => 'Article' ], 'mainEntity' ); + $schema_piece_2 = new Schema_Piece( [ '@type' => 'Person' ], 'author' ); + + yield 'Standard post aggregation' => [ + 'page' => 1, + 'per_page' => 50, + 'post_type' => 'post', + 'schema_pieces' => [ $schema_piece_1, $schema_piece_2 ], + 'aggregated_pieces' => [ 'aggregated' => 'data' ], + 'composed_response' => [ 'response' => 'data' ], + ]; + + yield 'Different page controls' => [ + 'page' => 2, + 'per_page' => 100, + 'post_type' => 'page', + 'schema_pieces' => [], + 'aggregated_pieces' => [], + 'composed_response' => [], + ]; + + yield 'Custom post type' => [ + 'page' => 1, + 'per_page' => 25, + 'post_type' => 'product', + 'schema_pieces' => [], + 'aggregated_pieces' => [ 'product' => 'schema' ], + 'composed_response' => [ 'final' => 'response' ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php new file mode 100644 index 00000000000..98710ac4789 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php @@ -0,0 +1,98 @@ +get_post_types(); + + $this->assertSame( $post_types, $result ); + } + + /** + * Tests get_post_types returns array. + * + * @return void + */ + public function test_get_post_types_returns_array() { + $command = new Aggregate_Site_Schema_Map_Command( [ 'post' ] ); + + $result = $command->get_post_types(); + + $this->assertIsArray( $result ); + } + + /** + * Tests constructor with empty array. + * + * @return void + */ + public function test_constructor_with_empty_array() { + $command = new Aggregate_Site_Schema_Map_Command( [] ); + + $result = $command->get_post_types(); + + $this->assertSame( [], $result ); + } + + /** + * Tests constructor with various post types. + * + * @dataProvider post_types_data_provider + * + * @param array $post_types The post types. + * + * @return void + */ + public function test_constructor_with_various_post_types( array $post_types ) { + $command = new Aggregate_Site_Schema_Map_Command( $post_types ); + + $result = $command->get_post_types(); + + $this->assertSame( $post_types, $result ); + } + + /** + * Data provider for post types tests. + * + * @return \Generator + */ + public static function post_types_data_provider() { + yield 'Single post type' => [ + 'post_types' => [ 'post' ], + ]; + + yield 'Multiple post types' => [ + 'post_types' => [ 'post', 'page', 'product' ], + ]; + + yield 'Custom post types' => [ + 'post_types' => [ 'custom_type_1', 'custom_type_2' ], + ]; + + yield 'Empty array' => [ + 'post_types' => [], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php new file mode 100644 index 00000000000..e5c315d603e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php @@ -0,0 +1,74 @@ +schema_map_repository_factory = Mockery::mock( Schema_Map_Repository_Factory::class ); + $this->schema_map_builder = Mockery::mock( Schema_Map_Builder::class ); + $this->schema_map_xml_renderer = Mockery::mock( Schema_Map_Xml_Renderer::class ); + $this->indexable_helper = Mockery::mock( Indexable_Helper::class ); + + $this->instance = new Aggregate_Site_Schema_Map_Command_Handler( + $this->schema_map_repository_factory, + $this->schema_map_builder, + $this->schema_map_xml_renderer, + $this->indexable_helper + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php new file mode 100644 index 00000000000..0fa3e0af73b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php @@ -0,0 +1,43 @@ +assertInstanceOf( + Schema_Map_Repository_Factory::class, + $this->getPropertyValue( $this->instance, 'schema_map_repository_factory' ) + ); + $this->assertInstanceOf( + Schema_Map_Builder::class, + $this->getPropertyValue( $this->instance, 'schema_map_builder' ) + ); + $this->assertInstanceOf( + Schema_Map_Xml_Renderer::class, + $this->getPropertyValue( $this->instance, 'schema_map_xml_renderer' ) + ); + $this->assertInstanceOf( + Indexable_Helper::class, + $this->getPropertyValue( $this->instance, 'indexable_helper' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Handle_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Handle_Test.php new file mode 100644 index 00000000000..9e9b42f90a1 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Handle_Test.php @@ -0,0 +1,238 @@ +add_indexable_count( new Indexable_Count( 'post', 100 ) ); + $indexable_counts->add_indexable_count( new Indexable_Count( 'page', 50 ) ); + + $schema_map = [ + [ + 'post_type' => 'post', + 'url' => 'https://example.com', + 'lastmod' => '2024-01-01', + 'count' => 100, + ], + ]; + $xml_output = 'schema map'; + + $this->indexable_helper + ->expects( 'should_index_indexables' ) + ->once() + ->andReturn( true ); + + $this->schema_map_repository_factory + ->expects( 'get_repository' ) + ->once() + ->with( true ) + ->andReturn( $repository ); + + $repository + ->expects( 'get_indexable_count_per_post_type' ) + ->once() + ->with( [ 'post', 'page' ] ) + ->andReturn( $indexable_counts ); + + $this->schema_map_builder + ->expects( 'with_repository' ) + ->once() + ->with( $repository ) + ->andReturnSelf(); + + $this->schema_map_builder + ->expects( 'build' ) + ->once() + ->with( $indexable_counts ) + ->andReturn( $schema_map ); + + $this->schema_map_xml_renderer + ->expects( 'render' ) + ->once() + ->with( $schema_map ) + ->andReturn( $xml_output ); + + $result = $this->instance->handle( $command ); + + $this->assertSame( $xml_output, $result ); + } + + /** + * Tests handle method with indexables disabled. + * + * @return void + */ + public function test_handle_with_indexables_disabled() { + $command = new Aggregate_Site_Schema_Map_Command( [ 'post' ] ); + $repository = Mockery::mock( Schema_Map_Repository_Interface::class ); + + $indexable_counts = new Indexable_Count_Collection(); + $schema_map = []; + $xml_output = 'map'; + + $this->indexable_helper + ->expects( 'should_index_indexables' ) + ->once() + ->andReturn( false ); + + $this->schema_map_repository_factory + ->expects( 'get_repository' ) + ->once() + ->with( false ) + ->andReturn( $repository ); + + $repository + ->expects( 'get_indexable_count_per_post_type' ) + ->once() + ->with( [ 'post' ] ) + ->andReturn( $indexable_counts ); + + $this->schema_map_builder + ->expects( 'with_repository' ) + ->once() + ->with( $repository ) + ->andReturnSelf(); + + $this->schema_map_builder + ->expects( 'build' ) + ->once() + ->andReturn( $schema_map ); + + $this->schema_map_xml_renderer + ->expects( 'render' ) + ->once() + ->andReturn( $xml_output ); + + $result = $this->instance->handle( $command ); + + $this->assertSame( $xml_output, $result ); + } + + /** + * Tests handle method returns string. + * + * @return void + */ + public function test_handle_returns_string() { + $command = new Aggregate_Site_Schema_Map_Command( [] ); + $repository = Mockery::mock( Schema_Map_Repository_Interface::class ); + + $this->indexable_helper + ->expects( 'should_index_indexables' ) + ->andReturn( true ); + + $this->schema_map_repository_factory + ->expects( 'get_repository' ) + ->andReturn( $repository ); + + $repository + ->expects( 'get_indexable_count_per_post_type' ) + ->andReturn( new Indexable_Count_Collection() ); + + $this->schema_map_builder + ->expects( 'with_repository' ) + ->andReturnSelf(); + + $this->schema_map_builder + ->expects( 'build' ) + ->andReturn( [] ); + + $this->schema_map_xml_renderer + ->expects( 'render' ) + ->andReturn( '' ); + + $result = $this->instance->handle( $command ); + + $this->assertIsString( $result ); + } + + /** + * Tests handle method with multiple post types. + * + * @return void + */ + public function test_handle_with_multiple_post_types() { + $command = new Aggregate_Site_Schema_Map_Command( [ 'post', 'page', 'product' ] ); + $repository = Mockery::mock( Schema_Map_Repository_Interface::class ); + + $indexable_counts = new Indexable_Count_Collection(); + $indexable_counts->add_indexable_count( new Indexable_Count( 'post', 100 ) ); + $indexable_counts->add_indexable_count( new Indexable_Count( 'page', 50 ) ); + $indexable_counts->add_indexable_count( new Indexable_Count( 'product', 25 ) ); + + $schema_map = [ + [ + 'post_type' => 'post', + 'url' => 'https://example.com/post', + 'lastmod' => '2024-01-01', + 'count' => 100, + ], + [ + 'post_type' => 'page', + 'url' => 'https://example.com/page', + 'lastmod' => '2024-01-01', + 'count' => 50, + ], + ]; + $xml_output = 'complete map'; + + $this->indexable_helper + ->expects( 'should_index_indexables' ) + ->once() + ->andReturn( true ); + + $this->schema_map_repository_factory + ->expects( 'get_repository' ) + ->once() + ->andReturn( $repository ); + + $repository + ->expects( 'get_indexable_count_per_post_type' ) + ->once() + ->with( [ 'post', 'page', 'product' ] ) + ->andReturn( $indexable_counts ); + + $this->schema_map_builder + ->expects( 'with_repository' ) + ->once() + ->andReturnSelf(); + + $this->schema_map_builder + ->expects( 'build' ) + ->once() + ->andReturn( $schema_map ); + + $this->schema_map_xml_renderer + ->expects( 'render' ) + ->once() + ->andReturn( $xml_output ); + + $result = $this->instance->handle( $command ); + + $this->assertSame( $xml_output, $result ); + } +} From d48b0a78495832724f473a9014b60476d4093c02 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 12:00:37 +0100 Subject: [PATCH 165/319] Change the output format to a streamed JSONL format. --- .../schema-aggregator-response-composer.php | 20 +++++++++------- .../application/schema-pieces-aggregator.php | 24 ++++--------------- .../schema_map/schema-map-header-adapter.php | 15 +++++++----- .../site-schema-aggregator-route.php | 5 ++-- 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php index 7fcdbab3169..18a24579dab 100644 --- a/src/schema-aggregator/application/schema-aggregator-response-composer.php +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -19,14 +19,16 @@ class Schema_Aggregator_Response_Composer { * @return array The composed schema response. */ public function compose( array $schema_pieces ): array { - return [ - '@context' => 'https://schema.org', - '@graph' => \array_map( - static function ( $piece ) { - return $piece->get_data(); - }, - \array_values( $schema_pieces ) - ), - ]; + $composed_pieces = []; + foreach ( $schema_pieces as $piece ) { + $composed_pieces[] = \array_merge( + [ + '@context' => 'https://schema.org', + ], + $piece->get_data() + ); + } + + return $composed_pieces; } } diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 141d51ceec7..abcff739816 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -29,24 +29,18 @@ class Schema_Pieces_Aggregator { */ private $schema_pieces_filter; - /** - * The properties merger object - * - * @var Properties_Merger - */ - private $properties_merger; - /** * Class constructor * * @param Properties_Filter $properties_filter The properties filter object. * @param Schema_Pieces_Filter $schema_pieces_filter The schema pieces filter object. - * @param Properties_Merger $properties_merger The properties merger object. */ - public function __construct( Properties_Filter $properties_filter, Schema_Pieces_Filter $schema_pieces_filter, Properties_Merger $properties_merger ) { + public function __construct( + Properties_Filter $properties_filter, + Schema_Pieces_Filter $schema_pieces_filter + ) { $this->properties_filter = $properties_filter; $this->schema_pieces_filter = $schema_pieces_filter; - $this->properties_merger = $properties_merger; } /** @@ -68,15 +62,7 @@ public function aggregate( array $schema_pieces ): array { if ( \is_null( $id ) ) { continue; } - - if ( isset( $aggregated_schema[ $id ] ) ) { - - $aggregated_schema[ $id ] = $this->properties_merger->merge( $aggregated_schema[ $id ], $piece ); - } - else { - // Add new piece. - $aggregated_schema[ $id ] = $piece; - } + $aggregated_schema[ $id ] = $piece; $aggregated_schema[ $id ] = $this->properties_filter->filter( $aggregated_schema[ $id ] ); } diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php index 1883022b952..90028f6c603 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php @@ -3,7 +3,6 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Map; use WP_REST_Response; -use WPSEO_Utils; /** * Adapter to set proper response headers for Schema Map responses. @@ -32,11 +31,15 @@ public function set_header_for_request( WP_REST_Response $response ) { echo $data; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $data should already be escaped here since this just adds headers to the request. } else { - // For JSON responses, encode with unescaped slashes for cleaner URLs. - $json = WPSEO_Utils::format_json_encode( $data ); - - \header( 'Content-Type: application/json; charset=UTF-8' ); - echo $json; //@phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $json should already be escaped here since this just adds headers to the request. + \header( 'X-Accel-Buffering: no' ); + \header( 'Content-Type: application/jsonl' ); + foreach ( $data as $schema_piece ) { + // @phpcs:disable Yoast.Yoast.JsonEncodeAlternative.FoundWithAdditionalParams -- The pretty print option breaks the JSONL format. + echo \wp_json_encode( $schema_piece, ( \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE ) ) . \PHP_EOL; // @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $data should already be escaped here since this just adds headers to the request. + \ob_flush(); + \flush(); + // @phpcs:enable + } } } } diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 02dfe3a9e54..ea01c862d19 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -149,9 +149,8 @@ public function aggregate_site_schema( WP_REST_Request $request ) { $output = $this->cache_manager->get( $page, $per_page ); if ( $output === null ) { try { - $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); - $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); - $this->cache_manager->set( $page, $per_page, $result ); + $output = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); + $this->cache_manager->set( $page, $per_page, $output ); } catch ( Exception $exception ) { return new WP_Error( From 81361b288651e0afba44e149e39928d00cd989c8 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 13:49:10 +0100 Subject: [PATCH 166/319] CS for command tests --- ...act_Aggregate_Site_Schema_Command_Test.php | 21 ------------- ...=> Aggregate_Site_Schema_Command_Test.php} | 3 +- .../Get_Page_Controls_Test.php | 30 ------------------- ...egate_Site_Schema_Command_Handler_Test.php | 2 ++ .../Handle_Test.php | 12 ++++---- ...Aggregate_Site_Schema_Map_Command_Test.php | 3 +- ...e_Site_Schema_Map_Command_Handler_Test.php | 1 + 7 files changed, 13 insertions(+), 59 deletions(-) delete mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php rename tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/{Constructor_Test.php => Aggregate_Site_Schema_Command_Test.php} (92%) delete mode 100644 tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Get_Page_Controls_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php deleted file mode 100644 index 5d05f7d7d6e..00000000000 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Abstract_Aggregate_Site_Schema_Command_Test.php +++ /dev/null @@ -1,21 +0,0 @@ -get_page_controls(); - - $this->assertInstanceOf( Page_Controls::class, $result ); - } -} diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php index 17a970a9ae1..976b9bed5c6 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php @@ -12,6 +12,8 @@ /** * Base class for Aggregate_Site_Schema_Command_Handler tests. + * + * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded */ abstract class Abstract_Aggregate_Site_Schema_Command_Handler_Test extends TestCase { diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php index 1af8658f7af..4c237b7727c 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php @@ -21,12 +21,12 @@ final class Handle_Test extends Abstract_Aggregate_Site_Schema_Command_Handler_T * * @dataProvider handle_orchestration_provider * - * @param int $page The page number. - * @param int $per_page The items per page. - * @param string $post_type The post type. - * @param array $schema_pieces The schema pieces to return. - * @param array $aggregated_pieces The aggregated pieces. - * @param array $composed_response The composed response. + * @param int $page The page number. + * @param int $per_page The items per page. + * @param string $post_type The post type. + * @param array $schema_pieces The schema pieces to return. + * @param array $aggregated_pieces The aggregated pieces. + * @param array $composed_response The composed response. * * @return void */ diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php index 98710ac4789..156cb1406b9 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command/Aggregate_Site_Schema_Map_Command_Test.php @@ -3,6 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command; +use Generator; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command; use Yoast\WP\SEO\Tests\Unit\TestCase; @@ -76,7 +77,7 @@ public function test_constructor_with_various_post_types( array $post_types ) { /** * Data provider for post types tests. * - * @return \Generator + * @return Generator */ public static function post_types_data_provider() { yield 'Single post type' => [ diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php index e5c315d603e..0aa5519fd6a 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php @@ -13,6 +13,7 @@ /** * Base class for Aggregate_Site_Schema_Map_Command_Handler tests. + * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded */ abstract class Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test extends TestCase { From b5f82aca5e3dcf7f4e1f289300165655f1384f38 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 14:03:33 +0100 Subject: [PATCH 167/319] Remove old mention --- .../Aggregate_Site_Schema_Command_Test.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Aggregate_Site_Schema_Command_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Aggregate_Site_Schema_Command_Test.php index 2ff5ea19c16..270e6b67f25 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Aggregate_Site_Schema_Command_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command/Aggregate_Site_Schema_Command_Test.php @@ -6,6 +6,7 @@ use Generator; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; use Yoast\WP\SEO\Schema_Aggregator\Domain\Page_Controls; +use Yoast\WP\SEO\Tests\Unit\TestCase; /** * Tests the Aggregate_Site_Schema_Command constructor. @@ -15,7 +16,7 @@ * @covers Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command::__construct * @covers Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command::get_page_controls */ -final class Aggregate_Site_Schema_Command_Test extends Abstract_Aggregate_Site_Schema_Command_Test { +final class Aggregate_Site_Schema_Command_Test extends TestCase { /** * Tests constructor creates Page_Controls correctly. From 0a090d1ca79edb1fbead2ab628b703798345ede1 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 15:06:23 +0100 Subject: [PATCH 168/319] Add unit tests for Article_Config class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements comprehensive unit tests for the Article_Config class following the same structure as the Llms_Txt_Configuration tests. Each method has its own test class extending an abstract base class. Tests cover: - get_config_value() method with various data types - is_enhancement_enabled() method with all known enhancements and unknown enhancement handling - should_include_article_body() method with both excerpt present and absent scenarios All tests use data providers and properly mock WordPress filters using Brain\Monkey. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../Abstract_Article_Config_Test.php | 33 +++++++ .../Article_Config_Get_Config_Value_Test.php | 72 ++++++++++++++ ...cle_Config_Is_Enhancement_Enabled_Test.php | 96 +++++++++++++++++++ ...onfig_Should_Include_Article_Body_Test.php | 77 +++++++++++++++ 4 files changed, 278 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Abstract_Article_Config_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Abstract_Article_Config_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Abstract_Article_Config_Test.php new file mode 100644 index 00000000000..00abdca7286 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Abstract_Article_Config_Test.php @@ -0,0 +1,33 @@ +instance = new Article_Config(); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php new file mode 100644 index 00000000000..f0cd7e32a96 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php @@ -0,0 +1,72 @@ +once() + ->with( "wpseo_article_enhance_config_{$key}", $the_default ) + ->andReturn( $expected ); + + $this->assertEquals( $expected, $this->instance->get_config_value( $key, $the_default ) ); + } + + /** + * Data provider for the get_config_value test. + * + * @return Generator Test data to use. + */ + public static function get_config_value_data() { + yield 'String value' => [ + 'key' => 'some_string_key', + 'the_default' => 'default_value', + 'expected' => 'filtered_value', + ]; + yield 'Integer value' => [ + 'key' => 'some_integer_key', + 'the_default' => 100, + 'expected' => 200, + ]; + yield 'Boolean true value' => [ + 'key' => 'some_bool_key', + 'the_default' => false, + 'expected' => true, + ]; + yield 'Boolean false value' => [ + 'key' => 'another_bool_key', + 'the_default' => true, + 'expected' => false, + ]; + yield 'Max article body length constant' => [ + 'key' => 'max_article_body_length', + 'the_default' => 500, + 'expected' => 1000, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php new file mode 100644 index 00000000000..1e929051dfd --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php @@ -0,0 +1,96 @@ +once() + ->with( "wpseo_article_enhance_{$enhancement}", $default_value ) + ->andReturn( $filtered_value ); + + $this->assertEquals( $expected, $this->instance->is_enhancement_enabled( $enhancement ) ); + } + + /** + * Data provider for the is_enhancement_enabled test. + * + * @return Generator Test data to use. + */ + public static function is_enhancement_enabled_data() { + yield 'article_body enabled by default, not filtered' => [ + 'enhancement' => 'article_body', + 'default_value' => true, + 'filtered_value' => true, + 'expected' => true, + ]; + yield 'article_body enabled by default, filtered to false' => [ + 'enhancement' => 'article_body', + 'default_value' => true, + 'filtered_value' => false, + 'expected' => false, + ]; + yield 'use_excerpt enabled by default, not filtered' => [ + 'enhancement' => 'use_excerpt', + 'default_value' => true, + 'filtered_value' => true, + 'expected' => true, + ]; + yield 'use_excerpt enabled by default, filtered to false' => [ + 'enhancement' => 'use_excerpt', + 'default_value' => true, + 'filtered_value' => false, + 'expected' => false, + ]; + yield 'keywords enabled by default, not filtered' => [ + 'enhancement' => 'keywords', + 'default_value' => true, + 'filtered_value' => true, + 'expected' => true, + ]; + yield 'keywords enabled by default, filtered to false' => [ + 'enhancement' => 'keywords', + 'default_value' => true, + 'filtered_value' => false, + 'expected' => false, + ]; + yield 'unknown enhancement disabled by default, not filtered' => [ + 'enhancement' => 'unknown_enhancement', + 'default_value' => false, + 'filtered_value' => false, + 'expected' => false, + ]; + yield 'unknown enhancement disabled by default, filtered to true' => [ + 'enhancement' => 'unknown_enhancement', + 'default_value' => false, + 'filtered_value' => true, + 'expected' => true, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php new file mode 100644 index 00000000000..d16a3ad26aa --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php @@ -0,0 +1,77 @@ +once() + ->with( $filter_name, $default_value ) + ->andReturn( $filtered_value ); + + $this->assertEquals( $expected, $this->instance->should_include_article_body( $has_excerpt ) ); + } + + /** + * Data provider for the should_include_article_body test. + * + * @return Generator Test data to use. + */ + public static function should_include_article_body_data() { + yield 'Has excerpt, default false, not filtered' => [ + 'has_excerpt' => true, + 'filter_name' => 'wpseo_article_enhance_body_when_excerpt_exists', + 'default_value' => false, + 'filtered_value' => false, + 'expected' => false, + ]; + yield 'Has excerpt, default false, filtered to true' => [ + 'has_excerpt' => true, + 'filter_name' => 'wpseo_article_enhance_body_when_excerpt_exists', + 'default_value' => false, + 'filtered_value' => true, + 'expected' => true, + ]; + yield 'No excerpt, default true, not filtered' => [ + 'has_excerpt' => false, + 'filter_name' => 'wpseo_article_enhance_article_body_fallback', + 'default_value' => true, + 'filtered_value' => true, + 'expected' => true, + ]; + yield 'No excerpt, default true, filtered to false' => [ + 'has_excerpt' => false, + 'filter_name' => 'wpseo_article_enhance_article_body_fallback', + 'default_value' => true, + 'filtered_value' => false, + 'expected' => false, + ]; + } +} From b93de1ff301a980e8f1be6548ca09309c65994ac Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 15:07:36 +0100 Subject: [PATCH 169/319] Add unit tests for Person_Config class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements comprehensive unit tests for the Person_Config class following the same structure as the Article_Config tests. Each method has its own test class extending an abstract base class. Tests cover: - get_config_value() method with various data types - is_enhancement_enabled() method with the known person_job_title enhancement and unknown enhancement handling All tests use data providers and properly mock WordPress filters using Brain\Monkey. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../Abstract_Person_Config_Test.php | 33 +++++++++ .../Person_Config_Get_Config_Value_Test.php | 72 +++++++++++++++++++ ...son_Config_Is_Enhancement_Enabled_Test.php | 72 +++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Abstract_Person_Config_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Abstract_Person_Config_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Abstract_Person_Config_Test.php new file mode 100644 index 00000000000..44d085d9f51 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Abstract_Person_Config_Test.php @@ -0,0 +1,33 @@ +instance = new Person_Config(); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php new file mode 100644 index 00000000000..0ebf1ea187b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php @@ -0,0 +1,72 @@ +once() + ->with( "wpseo_person_enhance_config_{$key}", $the_default ) + ->andReturn( $expected ); + + $this->assertEquals( $expected, $this->instance->get_config_value( $key, $the_default ) ); + } + + /** + * Data provider for the get_config_value test. + * + * @return Generator Test data to use. + */ + public static function get_config_value_data() { + yield 'String value' => [ + 'key' => 'some_string_key', + 'the_default' => 'default_value', + 'expected' => 'filtered_value', + ]; + yield 'Integer value' => [ + 'key' => 'some_integer_key', + 'the_default' => 100, + 'expected' => 200, + ]; + yield 'Boolean true value' => [ + 'key' => 'some_bool_key', + 'the_default' => false, + 'expected' => true, + ]; + yield 'Boolean false value' => [ + 'key' => 'another_bool_key', + 'the_default' => true, + 'expected' => false, + ]; + yield 'Job title config' => [ + 'key' => 'job_title_max_length', + 'the_default' => 50, + 'expected' => 100, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php new file mode 100644 index 00000000000..95c737b36d9 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php @@ -0,0 +1,72 @@ +once() + ->with( "wpseo_person_enhance_{$enhancement}", $default_value ) + ->andReturn( $filtered_value ); + + $this->assertEquals( $expected, $this->instance->is_enhancement_enabled( $enhancement ) ); + } + + /** + * Data provider for the is_enhancement_enabled test. + * + * @return Generator Test data to use. + */ + public static function is_enhancement_enabled_data() { + yield 'person_job_title enabled by default, not filtered' => [ + 'enhancement' => 'person_job_title', + 'default_value' => true, + 'filtered_value' => true, + 'expected' => true, + ]; + yield 'person_job_title enabled by default, filtered to false' => [ + 'enhancement' => 'person_job_title', + 'default_value' => true, + 'filtered_value' => false, + 'expected' => false, + ]; + yield 'unknown enhancement disabled by default, not filtered' => [ + 'enhancement' => 'unknown_enhancement', + 'default_value' => false, + 'filtered_value' => false, + 'expected' => false, + ]; + yield 'unknown enhancement disabled by default, filtered to true' => [ + 'enhancement' => 'unknown_enhancement', + 'default_value' => false, + 'filtered_value' => true, + 'expected' => true, + ]; + } +} From 067cdc7daabde519f956b23c7ccef561ec483765 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 9 Dec 2025 09:51:21 +0100 Subject: [PATCH 170/319] Tiny header change to make it work with current tooling. --- .../infrastructure/schema_map/schema-map-header-adapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php index 90028f6c603..720850e4343 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-header-adapter.php @@ -32,7 +32,7 @@ public function set_header_for_request( WP_REST_Response $response ) { } else { \header( 'X-Accel-Buffering: no' ); - \header( 'Content-Type: application/jsonl' ); + \header( 'Content-Type: application/json; charset=UTF-8' ); foreach ( $data as $schema_piece ) { // @phpcs:disable Yoast.Yoast.JsonEncodeAlternative.FoundWithAdditionalParams -- The pretty print option breaks the JSONL format. echo \wp_json_encode( $schema_piece, ( \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE ) ) . \PHP_EOL; // @phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $data should already be escaped here since this just adds headers to the request. From aa0d4817bf0c1d7826e68821d0c2b98bf60b1948 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 9 Dec 2025 16:50:51 +0100 Subject: [PATCH 171/319] MAke the Filtered_Map_Loader class follow the Decorator pattern --- .../elements-context-map/filtered-map-loader.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php index b9f3b74ed8c..8f54f76cd08 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php @@ -10,16 +10,16 @@ class Filtered_Map_Loader implements Map_Loader_Interface { /** * The base map loader strategy. * - * @var Base_Map_Loader + * @var Map_Loader_Interface */ private $base_loader; /** - * Class constructor.. + * Class constructor. * - * @param Base_Map_Loader $base_loader The base map loader strategy. + * @param Map_Loader_Interface $base_loader The base map loader strategy. */ - public function __construct( Base_Map_Loader $base_loader ) { + public function __construct( Map_Loader_Interface $base_loader ) { $this->base_loader = $base_loader; } From 03d6d74489f83f9db3cc14ed4e4e7806d16f7b81 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 9 Dec 2025 16:51:34 +0100 Subject: [PATCH 172/319] Account for the new JSONL output format --- .../user-interface/site-schema-aggregator-route.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 02dfe3a9e54..6976ced5fb4 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -146,14 +146,13 @@ public function aggregate_site_schema( WP_REST_Request $request ) { $page = ( $request->get_param( 'page' ) ?? 1 ); $per_page = $this->config->get_per_page( $post_type ); - $output = $this->cache_manager->get( $page, $per_page ); + $output = $this->cache_manager->get( $post_type, $page, $per_page ); if ( $output === null ) { try { - $result = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); - $output = \str_replace( "\n", \PHP_EOL . "\t", $result ); - $this->cache_manager->set( $page, $per_page, $result ); + $output = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); + $this->cache_manager->set( $post_type, $page, $per_page, $output ); - } catch ( Exception $exception ) { + } catch ( \Exception $exception ) { return new WP_Error( 'wpseo_aggregate_site_schema_error', $exception->getMessage(), From ae10fa3296cee7b437b813e62f107a1c5c238deb Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 10 Dec 2025 12:16:45 +0100 Subject: [PATCH 173/319] Add unit tests for Schema Aggregator infrastructure classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds comprehensive unit tests for the Schema Aggregator infrastructure components: - Meta_Tags_Context_Memoizer_Adapter tests for the meta_tags_context_to_array method - Schema_Aggregator_Conditional tests for constructor and is_met method - Schema_Aggregator_Watcher tests for constructor, register_hooks, and check_schema_aggregator_enabled methods All tests use specific type hints (bool|int|string|null, array) instead of mixed types for better type safety and documentation. The test structure follows the project's established patterns with abstract base classes for shared setup code. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../Meta_Tags_Context_To_Array_Test.php | 111 +++++++++++ ...act_Schema_Aggregator_Conditional_Test.php | 46 +++++ .../Constructor_Test.php | 28 +++ .../Is_Met_Test.php | 70 +++++++ ...bstract_Schema_Aggregator_Watcher_Test.php | 46 +++++ .../Check_Schema_Aggregator_Enabled_Test.php | 187 ++++++++++++++++++ .../Constructor_Test.php | 28 +++ .../Register_Hooks_Test.php | 31 +++ 8 files changed, 547 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Meta_Tags_Context_Memoizer_Adapter/Meta_Tags_Context_To_Array_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Is_Met_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Meta_Tags_Context_Memoizer_Adapter/Meta_Tags_Context_To_Array_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Meta_Tags_Context_Memoizer_Adapter/Meta_Tags_Context_To_Array_Test.php new file mode 100644 index 00000000000..fdb94fe28ac --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Meta_Tags_Context_Memoizer_Adapter/Meta_Tags_Context_To_Array_Test.php @@ -0,0 +1,111 @@ +instance = new Meta_Tags_Context_Memoizer_Adapter(); + } + + /** + * Tests that meta_tags_context_to_array returns the schema array from the presentation. + * + * @return void + */ + public function test_meta_tags_context_to_array_returns_schema_array() { + $expected_schema = [ + '@context' => 'https://schema.org', + '@type' => 'WebPage', + 'name' => 'Test Page', + ]; + + $presentation = Mockery::mock( Indexable_Presentation::class ); + $presentation->schema = $expected_schema; + + $context = Mockery::mock( Meta_Tags_Context::class ); + $context->presentation = $presentation; + + $result = $this->instance->meta_tags_context_to_array( $context ); + + $this->assertSame( $expected_schema, $result ); + } + + /** + * Tests that meta_tags_context_to_array works with an empty schema array. + * + * @return void + */ + public function test_meta_tags_context_to_array_with_empty_schema() { + $expected_schema = []; + + $presentation = Mockery::mock( Indexable_Presentation::class ); + $presentation->schema = $expected_schema; + + $context = Mockery::mock( Meta_Tags_Context::class ); + $context->presentation = $presentation; + + $result = $this->instance->meta_tags_context_to_array( $context ); + + $this->assertSame( $expected_schema, $result ); + } + + /** + * Tests that meta_tags_context_to_array works with a complex nested schema array. + * + * @return void + */ + public function test_meta_tags_context_to_array_with_nested_schema() { + $expected_schema = [ + '@context' => 'https://schema.org', + '@graph' => [ + [ + '@type' => 'Organization', + 'name' => 'Test Org', + ], + [ + '@type' => 'WebSite', + 'url' => 'https://example.com', + ], + ], + ]; + + $presentation = Mockery::mock( Indexable_Presentation::class ); + $presentation->schema = $expected_schema; + + $context = Mockery::mock( Meta_Tags_Context::class ); + $context->presentation = $presentation; + + $result = $this->instance->meta_tags_context_to_array( $context ); + + $this->assertSame( $expected_schema, $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php new file mode 100644 index 00000000000..18fb1540ad4 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php @@ -0,0 +1,46 @@ +options = Mockery::mock( Options_Helper::class ); + + $this->instance = new Schema_Aggregator_Conditional( + $this->options + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php new file mode 100644 index 00000000000..64484fc73d1 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php @@ -0,0 +1,28 @@ +assertInstanceOf( + Options_Helper::class, + $this->getPropertyValue( $this->instance, 'options' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Is_Met_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Is_Met_Test.php new file mode 100644 index 00000000000..5feed0a7ef2 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Is_Met_Test.php @@ -0,0 +1,70 @@ +options + ->expects( 'get' ) + ->once() + ->with( 'enable_schema_aggregation_endpoint' ) + ->andReturn( $option_value ); + + $result = $this->instance->is_met(); + + $this->assertSame( $expected, $result ); + } + + /** + * Data provider for test_is_met. + * + * @return Generator Test data to use. + */ + public static function data_is_met() { + yield 'Returns true when option is boolean true' => [ + 'option_value' => true, + 'expected' => true, + ]; + yield 'Returns false when option is boolean false' => [ + 'option_value' => false, + 'expected' => false, + ]; + yield 'Returns false when option is integer 1 (strict comparison)' => [ + 'option_value' => 1, + 'expected' => false, + ]; + yield 'Returns false when option is string "1" (strict comparison)' => [ + 'option_value' => '1', + 'expected' => false, + ]; + yield 'Returns false when option is string "true" (strict comparison)' => [ + 'option_value' => 'true', + 'expected' => false, + ]; + yield 'Returns false when option is null' => [ + 'option_value' => null, + 'expected' => false, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php new file mode 100644 index 00000000000..cc84920b0c4 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php @@ -0,0 +1,46 @@ +options_helper = Mockery::mock( Options_Helper::class ); + + $this->instance = new Schema_Aggregator_Watcher( + $this->options_helper + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php new file mode 100644 index 00000000000..d5a7fbd8afe --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php @@ -0,0 +1,187 @@ +|bool|string $old_value The old value of the option. + * @param array|bool|string $new_value The new value of the option. + * @param bool $expected The expected return value. + * @param bool $should_check_timestamp Whether the timestamp should be checked. + * @param bool $should_set_timestamp Whether the timestamp should be set. + * @param int|string|null $current_timestamp The current timestamp value from options. + * + * @return void + */ + public function test_check_schema_aggregator_enabled( + $old_value, + $new_value, + $expected, + $should_check_timestamp, + $should_set_timestamp, + $current_timestamp + ) { + if ( $should_check_timestamp ) { + $this->options_helper + ->expects( 'get' ) + ->once() + ->with( 'schema_aggregation_endpoint_enabled_on' ) + ->andReturn( $current_timestamp ); + } + + if ( $should_set_timestamp ) { + $this->options_helper + ->expects( 'set' ) + ->once() + ->with( 'schema_aggregation_endpoint_enabled_on', Mockery::type( 'int' ) ); + } + + $result = $this->instance->check_schema_aggregator_enabled( $old_value, $new_value ); + + $this->assertSame( $expected, $result ); + } + + /** + * Data provider for test_check_schema_aggregator_enabled. + * + * @return Generator Test data to use. + */ + public static function data_check_schema_aggregator_enabled() { + yield 'Sets timestamp when transitioning from disabled to enabled (first time)' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => false ], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'expected' => true, + 'should_check_timestamp' => true, + 'should_set_timestamp' => true, + 'current_timestamp' => null, + ]; + yield 'Returns false when timestamp already exists' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => false ], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'expected' => false, + 'should_check_timestamp' => true, + 'should_set_timestamp' => false, + 'current_timestamp' => 1234567890, + ]; + yield 'Returns false when already enabled (no transition)' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'expected' => false, + 'should_check_timestamp' => false, + 'should_set_timestamp' => false, + 'current_timestamp' => null, + ]; + yield 'Returns false when disabling' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => false ], + 'expected' => false, + 'should_check_timestamp' => false, + 'should_set_timestamp' => false, + 'current_timestamp' => null, + ]; + yield 'Handles old_value as false (WordPress default for missing options)' => [ + 'old_value' => false, + 'new_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'expected' => true, + 'should_check_timestamp' => true, + 'should_set_timestamp' => true, + 'current_timestamp' => null, + ]; + yield 'Returns false when old_value is not array' => [ + 'old_value' => 'string', + 'new_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'expected' => false, + 'should_check_timestamp' => false, + 'should_set_timestamp' => false, + 'current_timestamp' => null, + ]; + yield 'Returns false when new_value is not array' => [ + 'old_value' => [], + 'new_value' => 'string', + 'expected' => false, + 'should_check_timestamp' => false, + 'should_set_timestamp' => false, + 'current_timestamp' => null, + ]; + yield 'Handles missing key in old_value (treated as disabled)' => [ + 'old_value' => [], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'expected' => true, + 'should_check_timestamp' => true, + 'should_set_timestamp' => true, + 'current_timestamp' => null, + ]; + yield 'Handles missing key in new_value (treated as disabled)' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'new_value' => [], + 'expected' => false, + 'should_check_timestamp' => false, + 'should_set_timestamp' => false, + 'current_timestamp' => null, + ]; + yield 'Handles truthy values with boolean casting (0 to 1 transition)' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => 0 ], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => 1 ], + 'expected' => true, + 'should_check_timestamp' => true, + 'should_set_timestamp' => true, + 'current_timestamp' => null, + ]; + yield 'Returns false when both values are truthy but would cast to true' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => 'yes' ], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => 1 ], + 'expected' => false, + 'should_check_timestamp' => false, + 'should_set_timestamp' => false, + 'current_timestamp' => null, + ]; + yield 'Sets timestamp when current timestamp is empty string' => [ + 'old_value' => [ 'enable_schema_aggregation_endpoint' => false ], + 'new_value' => [ 'enable_schema_aggregation_endpoint' => true ], + 'expected' => true, + 'should_check_timestamp' => true, + 'should_set_timestamp' => true, + 'current_timestamp' => '', + ]; + } + + /** + * Tests that the timestamp is not set when the get method returns an existing timestamp. + * + * @return void + */ + public function test_check_schema_aggregator_enabled_does_not_overwrite_existing_timestamp() { + $old_value = [ 'enable_schema_aggregation_endpoint' => false ]; + $new_value = [ 'enable_schema_aggregation_endpoint' => true ]; + + $this->options_helper + ->expects( 'get' ) + ->once() + ->with( 'schema_aggregation_endpoint_enabled_on' ) + ->andReturn( 1234567890 ); + + $this->options_helper + ->expects( 'set' ) + ->never(); + + $result = $this->instance->check_schema_aggregator_enabled( $old_value, $new_value ); + + $this->assertFalse( $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php new file mode 100644 index 00000000000..35c65e1b47c --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php @@ -0,0 +1,28 @@ +assertInstanceOf( + Options_Helper::class, + $this->getPropertyValue( $this->instance, 'options_helper' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php new file mode 100644 index 00000000000..aef05d97e8f --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php @@ -0,0 +1,31 @@ +instance->register_hooks(); + + $this->assertEquals( + 10, + \has_action( + 'update_option_wpseo', + [ $this->instance, 'check_schema_aggregator_enabled' ] + ) + ); + } +} From 6c1d532b08fa91f1bddff41179e05eeb958d7fad Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:06:54 +0100 Subject: [PATCH 174/319] Introduce the Schema_Piece_Collection to ensure type-safety --- .../domain/schema-piece-collection.php | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/schema-aggregator/domain/schema-piece-collection.php diff --git a/src/schema-aggregator/domain/schema-piece-collection.php b/src/schema-aggregator/domain/schema-piece-collection.php new file mode 100644 index 00000000000..fac2b8e9bf1 --- /dev/null +++ b/src/schema-aggregator/domain/schema-piece-collection.php @@ -0,0 +1,59 @@ + + */ + private $pieces = []; + + /** + * Class constructor. + * + * @param array $pieces Optional array of Schema_Piece objects. + */ + public function __construct( array $pieces = [] ) { + foreach ( $pieces as $piece ) { + $this->add( $piece ); + } + } + + /** + * Adds a schema piece to the collection. + * + * @param Schema_Piece $piece The schema piece to add. + * + * @return void + */ + public function add( Schema_Piece $piece ): void { + $this->pieces[] = $piece; + } + + /** + * Gets all schema pieces as an array. + * + * @return array The schema pieces. + */ + public function to_array(): array { + return $this->pieces; + } + + /** + * Gets a schema piece by index. + * + * @param int $index The index. + * + * @return Schema_Piece|null The schema piece or null if not found. + */ + public function get( int $index ): ?Schema_Piece { + return $this->pieces[ $index ] ?? null; + } +} From 4f05255cde443b333e8a03c62486a0e8001cd30c Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:09:35 +0100 Subject: [PATCH 175/319] Use the Schema_Piece_Collection class --- .../application/filtering/default-filter.php | 12 ++++++------ .../filtering/filtering-strategy-interface.php | 8 ++++---- .../schema-node-filter-interface.php | 5 +++-- .../webpage-schema-node-filter.php | 11 ++++++----- .../website-schema-node-filter.php | 5 +++-- .../schema-aggregator-response-composer.php | 8 ++++---- .../application/schema-pieces-aggregator.php | 16 +++++++--------- .../domain/schema-piece-repository-interface.php | 4 ++-- .../schema-pieces/schema-piece-repository.php | 7 ++++--- 9 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index 2b553be82dd..bebc9f24419 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -2,7 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering; -use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Elements_Context_Map_Repository_Interface; /** @@ -41,14 +41,14 @@ public function __construct( Elements_Context_Map_Repository_Interface $elements /** * Applies filtering to the given schema. * - * @param array $schema The schema to be filtered. + * @param Schema_Piece_Collection $schema The schema to be filtered. * - * @return array The filtered schema. + * @return Schema_Piece_Collection The filtered schema. */ - public function filter( array $schema ): array { + public function filter( Schema_Piece_Collection $schema ): Schema_Piece_Collection { $filtered_schema = []; $elements_context_map = $this->elements_context_map_repository->get_map(); - foreach ( $schema as $schema_piece ) { + foreach ( $schema->to_array() as $schema_piece ) { $should_keep = true; foreach ( $this->filter_categories as $category ) { if ( \in_array( $schema_piece->get_type(), $elements_context_map[ $category ], true ) ) { @@ -70,6 +70,6 @@ public function filter( array $schema ): array { $filtered_schema[] = $schema_piece; } } - return $filtered_schema; + return new Schema_Piece_Collection( $filtered_schema ); } } diff --git a/src/schema-aggregator/application/filtering/filtering-strategy-interface.php b/src/schema-aggregator/application/filtering/filtering-strategy-interface.php index dacb4c102b7..f42455eb222 100644 --- a/src/schema-aggregator/application/filtering/filtering-strategy-interface.php +++ b/src/schema-aggregator/application/filtering/filtering-strategy-interface.php @@ -2,7 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering; -use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; /** * Interface for filtering strategies. @@ -12,9 +12,9 @@ interface Filtering_Strategy_Interface { /** * Applies filtering to the given schema. * - * @param array $schema The schema to be filtered. + * @param Schema_Piece_Collection $schema The schema to be filtered. * - * @return array The filtered schema. + * @return Schema_Piece_Collection The filtered schema. */ - public function filter( array $schema ): array; + public function filter( Schema_Piece_Collection $schema ): Schema_Piece_Collection; } diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php index c6c8ac48f07..f793e372182 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; /** * Schema node filter interface. @@ -13,10 +14,10 @@ interface Schema_Node_Filter_Interface { /** * Filters a schema piece. * - * @param array $schema The full schema. + * @param Schema_Piece_Collection $schema The full schema. * @param Schema_Piece $schema_piece The schema piece to be filtered. * * @return bool True if the schema piece should be kept, false otherwise. */ - public function filter( array $schema, Schema_Piece $schema_piece ): bool; + public function filter( Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool; } diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php index 10ef177d734..224a375a9f6 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; /** * WebPage schema node filter implementation. @@ -20,12 +21,12 @@ class WebPage_Schema_Node_Filter implements Schema_Node_Filter_Interface { /** * Filters a WebPage schema piece if it contains an Article. * - * @param array $schema The full schema. + * @param Schema_Piece_Collection $schema The full schema. * @param Schema_Piece $schema_piece The schema piece to be filtered. * * @return bool True if the schema piece should be kept, false otherwise. */ - public function filter( array $schema, Schema_Piece $schema_piece ): bool { + public function filter( Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { $data = $schema_piece->get_data(); $articles_ids = $this->get_articles_ids( $schema ); foreach ( $articles_ids as $article_id ) { @@ -39,14 +40,14 @@ public function filter( array $schema, Schema_Piece $schema_piece ): bool { /** * Retrieves the IDs of all Article schema pieces in the schema. * - * @param array $schema The full schema. + * @param Schema_Piece_Collection $schema The full schema. * * @return array The IDs of the Article schema pieces. */ - private function get_articles_ids( array $schema ): array { + private function get_articles_ids( Schema_Piece_Collection $schema ): array { if ( ! \is_array( $this->articles_ids ) ) { $this->articles_ids = []; - foreach ( $schema as $schema_piece ) { + foreach ( $schema->to_array() as $schema_piece ) { if ( $schema_piece->get_type() === 'Article' ) { $schema_piece_data = $schema_piece->get_data(); $this->articles_ids[] = $schema_piece_data['@id']; diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php index 2c8cb7665a0..8ffde1c3f17 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; /** * WebSite schema node filter implementation. @@ -13,12 +14,12 @@ class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Interface { /** * Filters a WebSite schema piece if it matches the site's URL. * - * @param array $schema The full schema. + * @param Schema_Piece_Collection $schema The full schema. * @param Schema_Piece $schema_piece The schema piece to be filtered. * * @return bool True if the schema piece should be kept, false otherwise. */ - public function filter( array $schema, Schema_Piece $schema_piece ): bool { + public function filter( Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { // Shall we support multisite here? $blog_id = \get_current_blog_id(); $blog_url = \trailingslashit( \get_home_url( $blog_id ) ); diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php index 18a24579dab..5a40e2671f5 100644 --- a/src/schema-aggregator/application/schema-aggregator-response-composer.php +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -2,7 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; -use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; /** * Class Schema_Aggregator_Response_Composer @@ -14,13 +14,13 @@ class Schema_Aggregator_Response_Composer { /** * Composes the final schema response. * - * @param array $schema_pieces The schema pieces to include in the response. + * @param Schema_Piece_Collection $schema_pieces The schema pieces to include in the response. * * @return array The composed schema response. */ - public function compose( array $schema_pieces ): array { + public function compose( Schema_Piece_Collection $schema_pieces ): array { $composed_pieces = []; - foreach ( $schema_pieces as $piece ) { + foreach ( $schema_pieces->to_array() as $piece ) { $composed_pieces[] = \array_merge( [ '@context' => 'https://schema.org', diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 5904a5d8c7e..496e9de6abe 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -2,7 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; -use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Filtering_Strategy_Factory; /** @@ -10,8 +10,6 @@ * 1. Schema_Pieces are deduplicated by using the id property * 2. if a copy of the same Schema_Piece exists, properties are merged together * 3. properties in the avoid list are unset - * - * @param array $schema_pieces The schema pieces to aggregate. */ class Schema_Pieces_Aggregator { @@ -43,17 +41,17 @@ public function __construct( Properties_Merger $properties_merger, Filtering_Str /** * Main orchestrator method: deduplicates, merges and filter properties. * - * @param array $schema_pieces The schema pieces to aggregate. + * @param Schema_Piece_Collection $schema_pieces The schema pieces to aggregate. * - * @return array The aggregated schema pieces. + * @return Schema_Piece_Collection The aggregated schema pieces. */ - public function aggregate( array $schema_pieces ): array { + public function aggregate( Schema_Piece_Collection $schema_pieces ): Schema_Piece_Collection { $aggregated_schema = []; $filtering_strategy = $this->filtering_strategy_factory->create(); $filtered_schema_pieces = $filtering_strategy->filter( $schema_pieces ); - foreach ( $filtered_schema_pieces as $piece ) { + foreach ( $filtered_schema_pieces->to_array() as $piece ) { $id = $piece->get_id(); if ( \is_null( $id ) ) { @@ -63,7 +61,7 @@ public function aggregate( array $schema_pieces ): array { } - // Return only the values to get rid of the keys (which are @id). - return \array_values( $aggregated_schema ); + // Return only the values to get rid of the keys (which are @id) and wrap in a collection. + return new Schema_Piece_Collection( \array_values( $aggregated_schema ) ); } } diff --git a/src/schema-aggregator/domain/schema-piece-repository-interface.php b/src/schema-aggregator/domain/schema-piece-repository-interface.php index 1a73a58ef53..7b5c3b50d4d 100644 --- a/src/schema-aggregator/domain/schema-piece-repository-interface.php +++ b/src/schema-aggregator/domain/schema-piece-repository-interface.php @@ -15,7 +15,7 @@ interface Schema_Piece_Repository_Interface { * @param int $page_size The number of items per page. * @param string $post_type The post type to filter by. * - * @return array The schema pieces. + * @return Schema_Piece_Collection The schema pieces. */ - public function get( int $page, int $page_size, string $post_type ): array; + public function get( int $page, int $page_size, string $post_type ): Schema_Piece_Collection; } diff --git a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index 4238e563ac4..6e4f92c4fd2 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -6,6 +6,7 @@ use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Schema_Enhancement_Factory; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\Indexable_Repository_Factory; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Meta_Tags_Context_Memoizer_Adapter; @@ -100,9 +101,9 @@ public function __construct( * @param int $page_size The number of items per page. * @param string $post_type The post type to filter by. * - * @return array The aggregated schema. + * @return Schema_Piece_Collection The aggregated schema. */ - public function get( int $page, int $page_size, string $post_type ): array { + public function get( int $page, int $page_size, string $post_type ): Schema_Piece_Collection { $indexable_repository = $this->indexable_repository_factory->get_repository( $this->indexable_helper->should_index_indexables() ); $indexables = $indexable_repository->get( $page, $page_size, $post_type ); $schema_pieces = []; @@ -131,7 +132,7 @@ public function get( int $page, int $page_size, string $post_type ): array { $schema_pieces[] = $schema_piece; } } - return $schema_pieces; + return new Schema_Piece_Collection( $schema_pieces ); } /** From 022319485a77e6afd98546efabc17169f518afbe Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:11:21 +0100 Subject: [PATCH 176/319] Remove the unused Properties_Merger and update the class description --- .../application/schema-pieces-aggregator.php | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 496e9de6abe..aa2aa8429c3 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -6,20 +6,10 @@ use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Filtering_Strategy_Factory; /** - * This class is responsible for taking an array of Schema_Pieces and return another array of Schema_Pieces where: - * 1. Schema_Pieces are deduplicated by using the id property - * 2. if a copy of the same Schema_Piece exists, properties are merged together - * 3. properties in the avoid list are unset + * This class is responsible for taking a Schema_Piece_Collection and return another filtered Schema_Piece_Collection. */ class Schema_Pieces_Aggregator { - /** - * The properties merger object - * - * @var Properties_Merger - */ - private $properties_merger; - /** * The filtering strategy factory. * @@ -30,11 +20,9 @@ class Schema_Pieces_Aggregator { /** * Class constructor * - * @param Properties_Merger $properties_merger The properties merger object. * @param Filtering_Strategy_Factory $filtering_strategy_factory The filtering strategy factory. */ - public function __construct( Properties_Merger $properties_merger, Filtering_Strategy_Factory $filtering_strategy_factory ) { - $this->properties_merger = $properties_merger; + public function __construct( Filtering_Strategy_Factory $filtering_strategy_factory ) { $this->filtering_strategy_factory = $filtering_strategy_factory; } From e2624da90ac65fb7499f28a976d0c7480f0e79d1 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:11:42 +0100 Subject: [PATCH 177/319] Use the interface rather than the repository implementation --- .../application/aggregate-site-schema-command-handler.php | 8 ++++---- .../schema-pieces/schema-piece-repository.php | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index b190b731699..b47062ef9a5 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -3,7 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application; -use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Schema_Piece_Repository; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; /** * Class that handles the Aggregate_Site_Schema_Command. @@ -13,7 +13,7 @@ class Aggregate_Site_Schema_Command_Handler { /** * The Schema_Piece_Repository instance. * - * @var Schema_Piece_Repository + * @var Schema_Piece_Repository_Interface */ private $schema_piece_repository; @@ -34,12 +34,12 @@ class Aggregate_Site_Schema_Command_Handler { /** * Aggregate_Site_Schema_Command_Handler constructor. * - * @param Schema_Piece_Repository $schema_piece_repository The collector of indexables that need to be aggregated. + * @param Schema_Piece_Repository_Interface $schema_piece_repository The collector of indexables that need to be aggregated. * @param Schema_Pieces_Aggregator $schema_piece_aggregator The schema pieces aggregator. * @param Schema_Aggregator_Response_Composer $schema_response_composer The schema response composer. */ public function __construct( - Schema_Piece_Repository $schema_piece_repository, + Schema_Piece_Repository_Interface $schema_piece_repository, Schema_Pieces_Aggregator $schema_piece_aggregator, Schema_Aggregator_Response_Composer $schema_response_composer ) { diff --git a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index 6e4f92c4fd2..1973d496284 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -7,6 +7,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Schema_Enhancement_Factory; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\Indexable_Repository_Factory; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Meta_Tags_Context_Memoizer_Adapter; @@ -14,7 +15,7 @@ /** * The Schema_Piece repository. */ -class Schema_Piece_Repository { +class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { /** * The meta tags context memoizer. @@ -142,7 +143,7 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec * * @return array */ - private function get_all_schema_types( $graph ): array { + private function get_all_schema_types( array $graph ): array { $schema_types = []; foreach ( $graph as $schema_values ) { foreach ( $schema_values as $key => $value ) { From e4dc140dca050b992a2c6a5ff00fa9af0329dd99 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:13:40 +0100 Subject: [PATCH 178/319] remove unused method --- .../domain/schema-piece-collection.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/schema-aggregator/domain/schema-piece-collection.php b/src/schema-aggregator/domain/schema-piece-collection.php index fac2b8e9bf1..081ea2ed13e 100644 --- a/src/schema-aggregator/domain/schema-piece-collection.php +++ b/src/schema-aggregator/domain/schema-piece-collection.php @@ -45,15 +45,4 @@ public function add( Schema_Piece $piece ): void { public function to_array(): array { return $this->pieces; } - - /** - * Gets a schema piece by index. - * - * @param int $index The index. - * - * @return Schema_Piece|null The schema piece or null if not found. - */ - public function get( int $index ): ?Schema_Piece { - return $this->pieces[ $index ] ?? null; - } } From 4154fb4ac0f1b98c9319256659aa3e1a9af5a307 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:13:52 +0100 Subject: [PATCH 179/319] Fix cs --- .../application/aggregate-site-schema-command-handler.php | 2 +- .../schema-node-filter/schema-node-filter-interface.php | 2 +- .../schema-node-filter/webpage-schema-node-filter.php | 2 +- .../schema-node-filter/website-schema-node-filter.php | 2 +- .../user-interface/site-schema-aggregator-route.php | 3 ++- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index b47062ef9a5..94385d69062 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -34,7 +34,7 @@ class Aggregate_Site_Schema_Command_Handler { /** * Aggregate_Site_Schema_Command_Handler constructor. * - * @param Schema_Piece_Repository_Interface $schema_piece_repository The collector of indexables that need to be aggregated. + * @param Schema_Piece_Repository_Interface $schema_piece_repository The collector of indexables that need to be aggregated. * @param Schema_Pieces_Aggregator $schema_piece_aggregator The schema pieces aggregator. * @param Schema_Aggregator_Response_Composer $schema_response_composer The schema response composer. */ diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php index f793e372182..99db7419935 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php @@ -15,7 +15,7 @@ interface Schema_Node_Filter_Interface { * Filters a schema piece. * * @param Schema_Piece_Collection $schema The full schema. - * @param Schema_Piece $schema_piece The schema piece to be filtered. + * @param Schema_Piece $schema_piece The schema piece to be filtered. * * @return bool True if the schema piece should be kept, false otherwise. */ diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php index 224a375a9f6..498d0d3082f 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php @@ -22,7 +22,7 @@ class WebPage_Schema_Node_Filter implements Schema_Node_Filter_Interface { * Filters a WebPage schema piece if it contains an Article. * * @param Schema_Piece_Collection $schema The full schema. - * @param Schema_Piece $schema_piece The schema piece to be filtered. + * @param Schema_Piece $schema_piece The schema piece to be filtered. * * @return bool True if the schema piece should be kept, false otherwise. */ diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php index 8ffde1c3f17..9d2cb5cfed1 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php @@ -15,7 +15,7 @@ class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Interface { * Filters a WebSite schema piece if it matches the site's URL. * * @param Schema_Piece_Collection $schema The full schema. - * @param Schema_Piece $schema_piece The schema piece to be filtered. + * @param Schema_Piece $schema_piece The schema piece to be filtered. * * @return bool True if the schema piece should be kept, false otherwise. */ diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 6976ced5fb4..bca79a32e05 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -2,6 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\User_Interface; +use Exception; use WP_Error; use WP_REST_Request; use WP_REST_Response; @@ -152,7 +153,7 @@ public function aggregate_site_schema( WP_REST_Request $request ) { $output = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); $this->cache_manager->set( $post_type, $page, $per_page, $output ); - } catch ( \Exception $exception ) { + } catch ( Exception $exception ) { return new WP_Error( 'wpseo_aggregate_site_schema_error', $exception->getMessage(), From 2c65c52152a74192a6a4d5c850b16f6199312481 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:21:24 +0100 Subject: [PATCH 180/319] Add comment to explain the class name choice --- .../schema-node-filter/webpage-schema-node-filter.php | 3 +++ .../schema-node-filter/website-schema-node-filter.php | 3 +++ .../webpage-schema-node-property-filter.php | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php index 498d0d3082f..75cafce2ab6 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php @@ -8,6 +8,9 @@ /** * WebPage schema node filter implementation. + * + * The class name uses WebPage instead of Webpage because we need it to reflect the schema piece name. + * By doing so we can search for a piece-specific node filter in Default_Filter. */ class WebPage_Schema_Node_Filter implements Schema_Node_Filter_Interface { diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php index 9d2cb5cfed1..eb44cb787ef 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php @@ -8,6 +8,9 @@ /** * WebSite schema node filter implementation. + * + * The class name uses WebSite instead of Website because we need it to reflect the schema piece name. + * By doing so we can search for a piece-specific node filter in Default_Filter. */ class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Interface { diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php index 5bd71886e22..0a20cedb834 100644 --- a/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php @@ -8,6 +8,9 @@ /** * WebPage property schema node filter class. * + * The class name uses WebPage instead of Webpage because we need it to reflect the schema piece name. + * By doing so we can search for a piece-specific property filter in Default_Filter. + * * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded */ class WebPage_Schema_Node_Property_Filter extends Base_Schema_Node_Property_Filter implements Schema_Node_Property_Filter_Interface { From 524624baadcaa7b14fa2cae18c8cf75f36da3026 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:40:40 +0100 Subject: [PATCH 181/319] Introduce a provider to abstract away the WordPress dependencies --- .../current-site-url-provider-interface.php | 17 ++++++++ .../wordpress-current-site-url-provider.php | 42 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/schema-aggregator/domain/current-site-url-provider-interface.php create mode 100644 src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php diff --git a/src/schema-aggregator/domain/current-site-url-provider-interface.php b/src/schema-aggregator/domain/current-site-url-provider-interface.php new file mode 100644 index 00000000000..6e64a9e6c81 --- /dev/null +++ b/src/schema-aggregator/domain/current-site-url-provider-interface.php @@ -0,0 +1,17 @@ +get_current_blog_id(); + return $this->get_home_url( $blog_id ); + } + + /** + * Gets the current blog ID. + * + * @return int The blog ID. + */ + private function get_current_blog_id(): int { + return \get_current_blog_id(); + } + + /** + * Gets the home URL for the given blog ID. + * + * @param int|null $blog_id The blog ID. If null, uses the current blog. + * + * @return string The home URL with trailing slash. + */ + private function get_home_url( ?int $blog_id = null ): string { + return \trailingslashit( \get_home_url( $blog_id ) ); + } +} From a8c93a7d45b0478fa36b96bd417dd4e2455ea13b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:40:52 +0100 Subject: [PATCH 182/319] Uses the provider --- .../website-schema-node-filter.php | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php index eb44cb787ef..674637f9d79 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php @@ -3,6 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Current_Site_URL_Provider_Interface; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; @@ -14,6 +15,22 @@ */ class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Interface { + /** + * The site info provider. + * + * @var Current_Site_URL_Provider_Interface + */ + private $current_site_url_provider; + + /** + * Class constructor. + * + * @param Current_Site_URL_Provider_Interface $current_site_url_provider The site info provider. + */ + public function __construct( Current_Site_URL_Provider_Interface $current_site_url_provider ) { + $this->current_site_url_provider = $current_site_url_provider; + } + /** * Filters a WebSite schema piece if it matches the site's URL. * @@ -23,9 +40,7 @@ class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Interface { * @return bool True if the schema piece should be kept, false otherwise. */ public function filter( Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { - // Shall we support multisite here? - $blog_id = \get_current_blog_id(); - $blog_url = \trailingslashit( \get_home_url( $blog_id ) ); + $blog_url = $this->current_site_url_provider->get_current_site_url(); $data = $schema_piece->get_data(); if ( $data['url'] === $blog_url ) { return false; From 799c5ba1c6479cbef2af5e8efe659f64d766d905 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 14:52:23 +0100 Subject: [PATCH 183/319] Simplify the class --- .../wordpress-current-site-url-provider.php | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php b/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php index 21ef5d72a18..46189eb8173 100644 --- a/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php +++ b/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php @@ -6,7 +6,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Domain\Current_Site_URL_Provider_Interface; /** - * WordPress implementation of site info provider. + * WordPress implementation of current site URL provider. */ class WordPress_Current_Site_URL_Provider implements Current_Site_URL_Provider_Interface { @@ -16,27 +16,7 @@ class WordPress_Current_Site_URL_Provider implements Current_Site_URL_Provider_I * @return string The current site's home URL. */ public function get_current_site_url(): string { - $blog_id = $this->get_current_blog_id(); - return $this->get_home_url( $blog_id ); - } - - /** - * Gets the current blog ID. - * - * @return int The blog ID. - */ - private function get_current_blog_id(): int { - return \get_current_blog_id(); - } - - /** - * Gets the home URL for the given blog ID. - * - * @param int|null $blog_id The blog ID. If null, uses the current blog. - * - * @return string The home URL with trailing slash. - */ - private function get_home_url( ?int $blog_id = null ): string { + $blog_id = \get_current_blog_id(); return \trailingslashit( \get_home_url( $blog_id ) ); } -} +} \ No newline at end of file From c9551fb3652d409fc9296b6ff065c0a59e33e6a7 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 15:10:56 +0100 Subject: [PATCH 184/319] Update comment --- .../domain/current-site-url-provider-interface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/domain/current-site-url-provider-interface.php b/src/schema-aggregator/domain/current-site-url-provider-interface.php index 6e64a9e6c81..5745f3fb982 100644 --- a/src/schema-aggregator/domain/current-site-url-provider-interface.php +++ b/src/schema-aggregator/domain/current-site-url-provider-interface.php @@ -4,7 +4,7 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Domain; /** - * Interface for providing site information. + * Interface for providing current site URL. */ interface Current_Site_URL_Provider_Interface { From 5dc17c0da6d9a454c58011c60e20bd113a3fc324 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 15:11:24 +0100 Subject: [PATCH 185/319] Fix cs --- .../infrastructure/wordpress-current-site-url-provider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php b/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php index 46189eb8173..c4aaec57791 100644 --- a/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php +++ b/src/schema-aggregator/infrastructure/wordpress-current-site-url-provider.php @@ -19,4 +19,4 @@ public function get_current_site_url(): string { $blog_id = \get_current_blog_id(); return \trailingslashit( \get_home_url( $blog_id ) ); } -} \ No newline at end of file +} From 43293c6ff183bd425d82489d985bf303c1f34b15 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 15:11:35 +0100 Subject: [PATCH 186/319] Add filters output validation --- .../filtered-map-loader.php | 76 ++++++++++++++++++- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php index 8f54f76cd08..d0f4c26039a 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php @@ -2,6 +2,8 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map; +use InvalidArgumentException; + /** * Map loader that applies filters to the elements-context map. */ @@ -29,14 +31,80 @@ public function __construct( Map_Loader_Interface $base_loader ) { * @return array> The filtered elements-context map. */ public function load(): array { - $map = $this->base_loader->load(); + $base_map = $this->base_loader->load(); - $map = \apply_filters( 'wpseo_schema_aggregator_elements_context_map', $map ); + $map = \apply_filters( 'wpseo_schema_aggregator_elements_context_map', $base_map ); + try { + $this->validate_main_map_lightweight( $map ); - foreach ( $map as $context => $elements ) { - $map[ $context ] = \apply_filters( "wpseo_schema_aggregator_elements_context_map_{$context}", $elements ); + foreach ( $map as $context => $elements ) { + $filtered_elements = \apply_filters( "wpseo_schema_aggregator_elements_context_map_{$context}", $elements ); + $this->validate_elements_array( $filtered_elements, "wpseo_schema_aggregator_elements_context_map_{$context}" ); + $map[ $context ] = $filtered_elements; + } + } catch ( InvalidArgumentException $exception ) { + return $base_map; } return $map; } + + // phpcs:disable SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint -- We expect this to be anything the user provides. + + /** + * Lightweight validation for the main map - only checks structure, not contents. + * + * @param mixed $map The map to validate. + * + * @throws InvalidArgumentException When the map format is invalid. + * + * @return void + */ + private function validate_main_map_lightweight( $map ): void { + if ( ! \is_array( $map ) ) { + throw new InvalidArgumentException( 'Filter "wpseo_schema_aggregator_elements_context_map" must return an array' ); + } + + if ( ! empty( $map ) ) { + // Check only the first key-value pair for performance. + $first_key = \array_key_first( $map ); + $first_value = $map[ $first_key ]; + + if ( ! \is_string( $first_key ) ) { + throw new InvalidArgumentException( + 'Filter "wpseo_schema_aggregator_elements_context_map" must return an array with string keys (context names).' + ); + } + + if ( ! \is_array( $first_value ) ) { + throw new InvalidArgumentException( + 'Filter "wpseo_schema_aggregator_elements_context_map" must return an array with array values (element lists).' + ); + } + } + } + + /** + * Validates that the elements array has the correct format. + * + * @param mixed $elements The elements array to validate. + * @param string $filter_name The name of the filter. + * + * @throws InvalidArgumentException When the elements format is invalid. + * + * @return void + */ + private function validate_elements_array( $elements, string $filter_name ): void { + if ( ! \is_array( $elements ) ) { + throw new InvalidArgumentException( 'Filter "wpseo_schema_aggregator_elements_context_map_*" must return an array of string element names.' ); + } + + foreach ( $elements as $element ) { + if ( ! \is_string( $element ) ) { + throw new InvalidArgumentException( 'Filter "wpseo_schema_aggregator_elements_context_map_*" must return an array of string element names.' ); + } + } + } + + // phpcs:enable SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint -- We expect this to be anything the user provides. } From a26d9535b283c394a988196f37675099fa3d4024 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 10 Dec 2025 15:14:27 +0100 Subject: [PATCH 187/319] Fix cs --- .../elements-context-map/filtered-map-loader.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php index d0f4c26039a..9d72ee52701 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php @@ -87,14 +87,13 @@ private function validate_main_map_lightweight( $map ): void { /** * Validates that the elements array has the correct format. * - * @param mixed $elements The elements array to validate. - * @param string $filter_name The name of the filter. + * @param mixed $elements The elements array to validate. * * @throws InvalidArgumentException When the elements format is invalid. * * @return void */ - private function validate_elements_array( $elements, string $filter_name ): void { + private function validate_elements_array( $elements ): void { if ( ! \is_array( $elements ) ) { throw new InvalidArgumentException( 'Filter "wpseo_schema_aggregator_elements_context_map_*" must return an array of string element names.' ); } From 3a0b116106881848dcbca738f6e6e90bf3abe584 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 10 Dec 2025 16:07:42 +0100 Subject: [PATCH 188/319] Not use DI --- .../schema-node-filter/website-schema-node-filter.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php index 674637f9d79..4633bd66cc0 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php @@ -6,6 +6,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Domain\Current_Site_URL_Provider_Interface; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\WordPress_Current_Site_URL_Provider; /** * WebSite schema node filter implementation. @@ -24,11 +25,9 @@ class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Interface { /** * Class constructor. - * - * @param Current_Site_URL_Provider_Interface $current_site_url_provider The site info provider. */ - public function __construct( Current_Site_URL_Provider_Interface $current_site_url_provider ) { - $this->current_site_url_provider = $current_site_url_provider; + public function __construct() { + $this->current_site_url_provider = new WordPress_Current_Site_URL_Provider(); } /** From 91e19f027247113cd07c26d2d00b8cdfb9075a4c Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 10 Dec 2025 16:10:19 +0100 Subject: [PATCH 189/319] Tiny change. --- .../infrastructure/elements-context-map/filtered-map-loader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php index 9d72ee52701..349efd58f31 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php @@ -39,7 +39,7 @@ public function load(): array { foreach ( $map as $context => $elements ) { $filtered_elements = \apply_filters( "wpseo_schema_aggregator_elements_context_map_{$context}", $elements ); - $this->validate_elements_array( $filtered_elements, "wpseo_schema_aggregator_elements_context_map_{$context}" ); + $this->validate_elements_array( $filtered_elements ); $map[ $context ] = $filtered_elements; } } catch ( InvalidArgumentException $exception ) { From a27618c217d65507e54e36d367247774e5e4b8bb Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 12 Dec 2025 13:14:31 +0100 Subject: [PATCH 190/319] Filter the `mainEntityOfPage` property from all schema pieces --- .../article-schema-node-property-filter.php | 33 ------------------- .../base-schema-node-property-filter.php | 2 +- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php deleted file mode 100644 index cb43238c110..00000000000 --- a/src/schema-aggregator/application/filtering/schema-node-property-filter/article-schema-node-property-filter.php +++ /dev/null @@ -1,33 +0,0 @@ -get_data(); - - // Remove the article body to reduce schema size. - if ( isset( $data['mainEntityOfPage'] ) ) { - unset( $data['mainEntityOfPage'] ); - } - - return new Schema_Piece( $data, $filtered_piece->get_type() ); - } -} diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php index 6d037217b18..85d44c53b4e 100644 --- a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php @@ -16,7 +16,7 @@ class Base_Schema_Node_Property_Filter implements Schema_Node_Property_Filter_In * * @var array */ - private const PROPERTIES_AVOID_LIST = [ 'potentialAction', 'isPartOf' ]; + private const PROPERTIES_AVOID_LIST = [ 'potentialAction', 'isPartOf', 'mainEntityOfPage' ]; /** * Filters any schema piece properties. From 398835a0b54692675047362903ec57a9152c8050 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 15 Dec 2025 11:52:54 +0100 Subject: [PATCH 191/319] Add tests for the Schema_Piece_Collection class --- .../Domain/Schema_Piece_Collection_Test.php | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php diff --git a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php new file mode 100644 index 00000000000..9737b8301fd --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php @@ -0,0 +1,153 @@ +assertSame( + [], + $this->getPropertyValue( $instance, 'pieces' ) + ); + } + + /** + * Tests that an empty collection returns an empty array. + * + * @return void + */ + public function test_to_array_empty() { + $instance = new Schema_Piece_Collection(); + + $this->assertSame( [], $instance->to_array() ); + } + + /** + * Tests adding a single Schema_Piece to the collection. + * + * @return void + */ + public function test_add_single_schema_piece() { + $instance = new Schema_Piece_Collection(); + $schema_piece = new Schema_Piece( [ '@type' => 'Article', 'name' => 'Test Article' ], 'Article' ); + + $instance->add( $schema_piece ); + + $result = $instance->to_array(); + $this->assertCount( 1, $result ); + $this->assertSame( $schema_piece, $result[0] ); + } + + /** + * Tests adding multiple Schema_Piece objects to the collection. + * + * @return void + */ + public function test_add_multiple_schema_pieces() { + $instance = new Schema_Piece_Collection(); + + $piece1 = new Schema_Piece( [ '@type' => 'Article', 'name' => 'Article 1' ], 'Article' ); + $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'John Doe' ], 'Person' ); + $piece3 = new Schema_Piece( [ '@type' => 'Organization', 'name' => 'Yoast' ], 'Organization' ); + + $instance->add( $piece1 ); + $instance->add( $piece2 ); + $instance->add( $piece3 ); + + $result = $instance->to_array(); + $this->assertCount( 3, $result ); + $this->assertSame( $piece1, $result[0] ); + $this->assertSame( $piece2, $result[1] ); + $this->assertSame( $piece3, $result[2] ); + } + + /** + * Tests that to_array returns the correct type. + * + * @return void + */ + public function test_to_array_returns_array() { + $instance = new Schema_Piece_Collection(); + $schema_piece = new Schema_Piece( [ '@type' => 'WebPage', 'name' => 'Test Page' ], 'WebPage' ); + + $instance->add( $schema_piece ); + + $result = $instance->to_array(); + $this->assertIsArray( $result ); + $this->assertContainsOnlyInstancesOf( Schema_Piece::class, $result ); + } + + /** + * Tests that added items maintain their order. + * + * @return void + */ + public function test_collection_maintains_order() { + $instance = new Schema_Piece_Collection(); + + $piece1 = new Schema_Piece( [ '@type' => 'Article', 'headline' => 'Article 1' ], 'Article' ); + $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'Person 1' ], 'Person' ); + $piece3 = new Schema_Piece( [ '@type' => 'Organization', 'name' => 'Org 1' ], 'Organization' ); + $piece4 = new Schema_Piece( [ '@type' => 'WebPage', 'name' => 'Page 1' ], 'WebPage' ); + + $instance->add( $piece1 ); + $instance->add( $piece2 ); + $instance->add( $piece3 ); + $instance->add( $piece4 ); + + $result = $instance->to_array(); + + $this->assertSame( 'Article', $result[0]->get_type() ); + $this->assertSame( 'Person', $result[1]->get_type() ); + $this->assertSame( 'Organization', $result[2]->get_type() ); + $this->assertSame( 'WebPage', $result[3]->get_type() ); + } + + /** + * Tests constructor with pre-populated array. + * + * @return void + */ + public function test_constructor_with_pieces() { + $piece1 = new Schema_Piece( [ '@type' => 'Article', 'headline' => 'Test Article' ], 'Article' ); + $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'Test Person' ], 'Person' ); + + $instance = new Schema_Piece_Collection( [ $piece1, $piece2 ] ); + + $result = $instance->to_array(); + $this->assertCount( 2, $result ); + $this->assertSame( $piece1, $result[0] ); + $this->assertSame( $piece2, $result[1] ); + } + + /** + * Tests that constructor with empty array works correctly. + * + * @return void + */ + public function test_constructor_with_empty_array() { + $instance = new Schema_Piece_Collection( [] ); + + $this->assertSame( [], $instance->to_array() ); + } +} \ No newline at end of file From 6d6d14e3541d9aedce094d4d3bf1c2a6f8a836bf Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 15 Dec 2025 11:55:50 +0100 Subject: [PATCH 192/319] Fix CS --- .../Domain/Schema_Piece_Collection_Test.php | 90 ++++++++++++++++--- 1 file changed, 78 insertions(+), 12 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php index 9737b8301fd..38744c174c8 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php @@ -49,7 +49,13 @@ public function test_to_array_empty() { */ public function test_add_single_schema_piece() { $instance = new Schema_Piece_Collection(); - $schema_piece = new Schema_Piece( [ '@type' => 'Article', 'name' => 'Test Article' ], 'Article' ); + $schema_piece = new Schema_Piece( + [ + '@type' => 'Article', + 'name' => 'Test Article', + ], + 'Article' + ); $instance->add( $schema_piece ); @@ -66,9 +72,27 @@ public function test_add_single_schema_piece() { public function test_add_multiple_schema_pieces() { $instance = new Schema_Piece_Collection(); - $piece1 = new Schema_Piece( [ '@type' => 'Article', 'name' => 'Article 1' ], 'Article' ); - $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'John Doe' ], 'Person' ); - $piece3 = new Schema_Piece( [ '@type' => 'Organization', 'name' => 'Yoast' ], 'Organization' ); + $piece1 = new Schema_Piece( + [ + '@type' => 'Article', + 'name' => 'Article 1', + ], + 'Article' + ); + $piece2 = new Schema_Piece( + [ + '@type' => 'Person', + 'name' => 'John Doe', + ], + 'Person' + ); + $piece3 = new Schema_Piece( + [ + '@type' => 'Organization', + 'name' => 'Yoast', + ], + 'Organization' + ); $instance->add( $piece1 ); $instance->add( $piece2 ); @@ -88,7 +112,13 @@ public function test_add_multiple_schema_pieces() { */ public function test_to_array_returns_array() { $instance = new Schema_Piece_Collection(); - $schema_piece = new Schema_Piece( [ '@type' => 'WebPage', 'name' => 'Test Page' ], 'WebPage' ); + $schema_piece = new Schema_Piece( + [ + '@type' => 'WebPage', + 'name' => 'Test Page', + ], + 'WebPage' + ); $instance->add( $schema_piece ); @@ -105,10 +135,34 @@ public function test_to_array_returns_array() { public function test_collection_maintains_order() { $instance = new Schema_Piece_Collection(); - $piece1 = new Schema_Piece( [ '@type' => 'Article', 'headline' => 'Article 1' ], 'Article' ); - $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'Person 1' ], 'Person' ); - $piece3 = new Schema_Piece( [ '@type' => 'Organization', 'name' => 'Org 1' ], 'Organization' ); - $piece4 = new Schema_Piece( [ '@type' => 'WebPage', 'name' => 'Page 1' ], 'WebPage' ); + $piece1 = new Schema_Piece( + [ + '@type' => 'Article', + 'headline' => 'Article 1', + ], + 'Article' + ); + $piece2 = new Schema_Piece( + [ + '@type' => 'Person', + 'name' => 'Person 1', + ], + 'Person' + ); + $piece3 = new Schema_Piece( + [ + '@type' => 'Organization', + 'name' => 'Org 1', + ], + 'Organization' + ); + $piece4 = new Schema_Piece( + [ + '@type' => 'WebPage', + 'name' => 'Page 1', + ], + 'WebPage' + ); $instance->add( $piece1 ); $instance->add( $piece2 ); @@ -129,8 +183,20 @@ public function test_collection_maintains_order() { * @return void */ public function test_constructor_with_pieces() { - $piece1 = new Schema_Piece( [ '@type' => 'Article', 'headline' => 'Test Article' ], 'Article' ); - $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'Test Person' ], 'Person' ); + $piece1 = new Schema_Piece( + [ + '@type' => 'Article', + 'headline' => 'Test Article', + ], + 'Article' + ); + $piece2 = new Schema_Piece( + [ + '@type' => 'Person', + 'name' => 'Test Person', + ], + 'Person' + ); $instance = new Schema_Piece_Collection( [ $piece1, $piece2 ] ); @@ -150,4 +216,4 @@ public function test_constructor_with_empty_array() { $this->assertSame( [], $instance->to_array() ); } -} \ No newline at end of file +} From 598db9e9a372d5e45c039c3900a0e1f35b8026f3 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 15 Dec 2025 12:03:12 +0100 Subject: [PATCH 193/319] Add a new Schemamap line to the robots.txt file when the feature is enabled and the blog is public. --- src/helpers/robots-txt-helper.php | 32 ++++++- src/presenters/robots-txt-presenter.php | 24 +++++ ...indexables-update-listener-integration.php | 8 +- .../site-schema-robots-txt-integration.php | 46 ++++++++++ tests/Unit/Helpers/Robots_Txt_Helper_Test.php | 64 +++++++++++++ .../Front_End/Robots_Txt_Integration_Test.php | 92 +++++++++++-------- ...ite_Schema_Robots_Txt_Integration_Test.php | 33 +++++++ ..._Txt_Integration_Get_Conditionals_Test.php | 31 +++++++ ...egration_Maybe_Add_Xml_Schema_Map_Test.php | 88 ++++++++++++++++++ ...ts_Txt_Integration_Register_Hooks_Test.php | 31 +++++++ 10 files changed, 408 insertions(+), 41 deletions(-) create mode 100644 src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Abstract_Site_Schema_Robots_Txt_Integration_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php diff --git a/src/helpers/robots-txt-helper.php b/src/helpers/robots-txt-helper.php index 846e9876565..7329438ff9d 100644 --- a/src/helpers/robots-txt-helper.php +++ b/src/helpers/robots-txt-helper.php @@ -23,12 +23,20 @@ class Robots_Txt_Helper { */ protected $robots_txt_sitemaps; + /** + * Holds an array with absolute URLs of schema maps. + * + * @var array + */ + private $robots_txt_schemamaps; + /** * Constructor for Robots_Txt_Helper. */ public function __construct() { $this->robots_txt_user_agents = new User_Agent_List(); $this->robots_txt_sitemaps = []; + $this->robots_txt_schemamaps = []; } /** @@ -70,6 +78,19 @@ public function add_sitemap( $absolute_path ) { } } + /** + * Add schema to robots.txt if it does not exist yet. + * + * @param string $absolute_path The absolute path to the sitemap to add. + * + * @return void + */ + public function add_schemamap( $absolute_path ) { + if ( ! \in_array( $absolute_path, $this->robots_txt_schemamaps, true ) ) { + $this->robots_txt_schemamaps[] = $absolute_path; + } + } + /** * Get all registered disallow directives per user agent. * @@ -91,12 +112,21 @@ public function get_allow_directives() { /** * Get all registered sitemap rules. * - * @return array The registered sitemap rules. + * @return array The registered sitemap rules. */ public function get_sitemap_rules() { return $this->robots_txt_sitemaps; } + /** + * Get all registered schemamap rules. + * + * @return array The registered schemamap rules. + */ + public function get_schemamap_rules() { + return $this->robots_txt_schemamaps; + } + /** * Get all registered user agents * diff --git a/src/presenters/robots-txt-presenter.php b/src/presenters/robots-txt-presenter.php index ef87c9113d7..bfd25c52b7d 100644 --- a/src/presenters/robots-txt-presenter.php +++ b/src/presenters/robots-txt-presenter.php @@ -41,6 +41,13 @@ class Robots_Txt_Presenter extends Abstract_Presenter { */ public const SITEMAP_FIELD = 'Sitemap'; + /** + * Text to be outputted for the schemamap rule. + * + * @var string + */ + public const SCHEMAMAP_FIELD = 'Schemamap'; + /** * Holds the Robots_Txt_Helper. * @@ -67,6 +74,7 @@ public function present() { $robots_txt_content = $this->handle_user_agents( $robots_txt_content ); $robots_txt_content = $this->handle_site_maps( $robots_txt_content ); + $robots_txt_content = $this->handle_schema_maps( $robots_txt_content ); return $robots_txt_content . self::YOAST_OUTPUT_AFTER_COMMENT; } @@ -147,4 +155,20 @@ private function handle_site_maps( $robots_txt_content ) { return $robots_txt_content; } + + /** + * Handles adding schema map content to the robots txt content. + * + * @param string $robots_txt_content The current working robots txt string. + * + * @return string + */ + private function handle_schema_maps( $robots_txt_content ) { + $registered_schemamaps = $this->robots_txt_helper->get_schemamap_rules(); + foreach ( $registered_schemamaps as $schamamap ) { + $robots_txt_content .= self::SCHEMAMAP_FIELD . ': ' . $schamamap . \PHP_EOL; + } + + return $robots_txt_content; + } } diff --git a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php index 82f120f3698..a7503450ff9 100644 --- a/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php +++ b/src/schema-aggregator/user-interface/cache/indexables-update-listener-integration.php @@ -44,9 +44,11 @@ public function reset_cache( $indexable, $indexable_before ) { return false; } - $page = $this->get_page_number( $indexable ); - $this->manager->invalidate( $indexable->object_sub_type, $page ); - $this->xml_manager->invalidate(); + if ( $indexable->object_sub_type !== null ) { + $page = $this->get_page_number( $indexable ); + $this->manager->invalidate( $indexable->object_sub_type, $page ); + $this->xml_manager->invalidate(); + } return true; } diff --git a/src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php b/src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php new file mode 100644 index 00000000000..74c9cc288d0 --- /dev/null +++ b/src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php @@ -0,0 +1,46 @@ + The conditionals that must be met to load this. + */ + public static function get_conditionals() { + return [ Schema_Aggregator_Conditional::class ]; + } + + /** + * Registers the hooks for this integration. + * + * @return void + */ + public function register_hooks() { + \add_action( 'Yoast\WP\SEO\register_robots_rules', [ $this, 'maybe_add_xml_schema_map' ], 10, 1 ); + } + + /** + * Adds the XML schema map to the robots.txt if the site is public. + * + * @param Robots_Txt_Helper $robots_txt_helper The robots.txt helper. + * + * @return void + */ + public function maybe_add_xml_schema_map( Robots_Txt_Helper $robots_txt_helper ) { + if ( (string) \get_option( 'blog_public' ) === '0' ) { + return; + } + $robots_txt_helper->add_schemamap( \esc_url( \rest_url( Main::API_V1_NAMESPACE . '/' . Site_Schema_Aggregator_Xml_Route::ROUTE_PREFIX . '/get-xml' ) ) ); + } +} diff --git a/tests/Unit/Helpers/Robots_Txt_Helper_Test.php b/tests/Unit/Helpers/Robots_Txt_Helper_Test.php index b89c78a6160..50256bd69b6 100644 --- a/tests/Unit/Helpers/Robots_Txt_Helper_Test.php +++ b/tests/Unit/Helpers/Robots_Txt_Helper_Test.php @@ -285,4 +285,68 @@ public static function add_sitemap_dataprovider() { 'Duplicate sitemap' => $duplicate_sitemap, ]; } + + /** + * Tests if add_schemamap works as expected. + * + * @dataProvider add_schemamap_dataprovider + * + * @covers ::add_allow + * + * @param array $schemamaps The schemamaps to be passed to the function. + * @param array $expected The expected result. + * + * @return void + */ + public function test_add_schemamap( $schemamaps, $expected ) { + foreach ( $schemamaps as $schemamap ) { + $this->instance->add_schemamap( $schemamap ); + } + + $this->assertEquals( $expected, $this->instance->get_schemamap_rules() ); + } + + /** + * Data provider for test_add_schemamap. + * + * @return array Data to use for test_add_schemamap. + */ + public static function add_schemamap_dataprovider() { + $single_schemamap = [ + 'sitemaps' => [ + 'http://sitemap.com/wp-json/yoast/v1/schema-aggregator/get-xml', + ], + 'expected' => [ + 'http://sitemap.com/wp-json/yoast/v1/schema-aggregator/get-xml', + ], + ]; + $multiple_schemamaps = [ + 'sitemaps' => [ + 'http://sitemap.com/wp-json/yoast/v1/schema-aggregator/get-xml', + 'http://example.com/wp-json/yoast/v1/schema-aggregator/get-xml', + 'http://google.com/wp-json/yoast/v1/schema-aggregator/get-xml', + ], + 'expected' => [ + 'http://sitemap.com/wp-json/yoast/v1/schema-aggregator/get-xml', + 'http://example.com/wp-json/yoast/v1/schema-aggregator/get-xml', + 'http://google.com/wp-json/yoast/v1/schema-aggregator/get-xml', + ], + ]; + $duplicate_schemamaps = [ + 'sitemaps' => [ + 'http://sitemap.com/wp-json/yoast/v1/schema-aggregator/get-xml', + 'http://sitemap.com/wp-json/yoast/v1/schema-aggregator/get-xml', + 'http://google.com/wp-json/yoast/v1/schema-aggregator/get-xml', + ], + 'expected' => [ + 'http://sitemap.com/wp-json/yoast/v1/schema-aggregator/get-xml', + 'http://google.com/wp-json/yoast/v1/schema-aggregator/get-xml', + ], + ]; + return [ + 'Single schemamap' => $single_schemamap, + 'Multiple schemamaps' => $multiple_schemamaps, + 'Duplicate schemamaps' => $duplicate_schemamaps, + ]; + } } diff --git a/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php b/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php index d8823312d8e..e2bef069556 100644 --- a/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php +++ b/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php @@ -166,14 +166,19 @@ public function test_public_site_with_sitemaps() { ->expects( 'get_sitemap_rules' ) ->andReturn( [ 'http://basic.wordpress.test/sitemap_index.xml' ] ); + $this->robots_txt_helper + ->expects( 'get_schemamap_rules' ) + ->andReturn( [ 'http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' ] ); + $expected = '# START YOAST BLOCK' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . 'User-agent: *' . \PHP_EOL - . 'Disallow:' . \PHP_EOL - . \PHP_EOL - . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . '# END YOAST BLOCK'; + . '# ---------------------------' . \PHP_EOL + . 'User-agent: *' . \PHP_EOL + . 'Disallow:' . \PHP_EOL + . \PHP_EOL + . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL + . 'Schemamap: http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' . \PHP_EOL + . '# ---------------------------' . \PHP_EOL + . '# END YOAST BLOCK'; $this->assertSame( $expected, $this->instance->filter_robots( '' ) ); } @@ -258,15 +263,18 @@ public function test_multisite_sitemaps( $multisite ) { $this->robots_txt_helper ->expects( 'get_sitemap_rules' ) ->andReturn( [ 'http://basic.wordpress.test/sitemap_index.xml' ] ); - + $this->robots_txt_helper + ->expects( 'get_schemamap_rules' ) + ->andReturn( [ 'http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' ] ); $expected = '# START YOAST BLOCK' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . 'User-agent: *' . \PHP_EOL - . 'Disallow:' . \PHP_EOL - . \PHP_EOL - . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . '# END YOAST BLOCK'; + . '# ---------------------------' . \PHP_EOL + . 'User-agent: *' . \PHP_EOL + . 'Disallow:' . \PHP_EOL + . \PHP_EOL + . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL + . 'Schemamap: http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' . \PHP_EOL + . '# ---------------------------' . \PHP_EOL + . '# END YOAST BLOCK'; $this->assertSame( $expected, $this->instance->filter_robots( '' ) ); } @@ -377,15 +385,18 @@ public function test_multisite_sitemaps_without_yoast_seo_active() { $this->robots_txt_helper ->expects( 'get_sitemap_rules' ) ->andReturn( [ 'http://basic.wordpress.test/sitemap_index.xml' ] ); - + $this->robots_txt_helper + ->expects( 'get_schemamap_rules' ) + ->andReturn( [ 'http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' ] ); $expected = '# START YOAST BLOCK' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . 'User-agent: *' . \PHP_EOL - . 'Disallow:' . \PHP_EOL - . \PHP_EOL - . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . '# END YOAST BLOCK'; + . '# ---------------------------' . \PHP_EOL + . 'User-agent: *' . \PHP_EOL + . 'Disallow:' . \PHP_EOL + . \PHP_EOL + . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL + . 'Schemamap: http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' . \PHP_EOL + . '# ---------------------------' . \PHP_EOL + . '# END YOAST BLOCK'; $this->assertSame( $expected, $this->instance->filter_robots( '' ) ); } @@ -459,15 +470,18 @@ public function test_multisite_sitemaps_option_not_found() { $this->robots_txt_helper ->expects( 'get_sitemap_rules' ) ->andReturn( [ 'http://basic.wordpress.test/sitemap_index.xml' ] ); - + $this->robots_txt_helper + ->expects( 'get_schemamap_rules' ) + ->andReturn( [ 'http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' ] ); $expected = '# START YOAST BLOCK' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . 'User-agent: *' . \PHP_EOL - . 'Disallow:' . \PHP_EOL - . \PHP_EOL - . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . '# END YOAST BLOCK'; + . '# ---------------------------' . \PHP_EOL + . 'User-agent: *' . \PHP_EOL + . 'Disallow:' . \PHP_EOL + . \PHP_EOL + . 'Sitemap: http://basic.wordpress.test/sitemap_index.xml' . \PHP_EOL + . 'Schemamap: http://basic.wordpress.test/wp-json/yoast/v1/schema-aggregator/get-xml' . \PHP_EOL + . '# ---------------------------' . \PHP_EOL + . '# END YOAST BLOCK'; $this->assertSame( $expected, $this->instance->filter_robots( '' ) ); } @@ -495,13 +509,17 @@ public function test_public_site_without_sitemaps() { ->expects( 'get_sitemap_rules' ) ->andReturn( [] ); + $this->robots_txt_helper + ->expects( 'get_schemamap_rules' ) + ->andReturn( [] ); + $expected = '# START YOAST BLOCK' . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . 'User-agent: *' . \PHP_EOL - . 'Disallow:' . \PHP_EOL - . \PHP_EOL - . '# ---------------------------' . \PHP_EOL - . '# END YOAST BLOCK'; + . '# ---------------------------' . \PHP_EOL + . 'User-agent: *' . \PHP_EOL + . 'Disallow:' . \PHP_EOL + . \PHP_EOL + . '# ---------------------------' . \PHP_EOL + . '# END YOAST BLOCK'; $this->assertSame( $expected, $this->instance->filter_robots( '' ) ); } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Abstract_Site_Schema_Robots_Txt_Integration_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Abstract_Site_Schema_Robots_Txt_Integration_Test.php new file mode 100644 index 00000000000..6a27f6dc6ae --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Abstract_Site_Schema_Robots_Txt_Integration_Test.php @@ -0,0 +1,33 @@ +instance = new Site_Schema_Robots_Txt_Integration(); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php new file mode 100644 index 00000000000..790fbbdf18a --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php @@ -0,0 +1,31 @@ +assertEquals( + [ Schema_Aggregator_Conditional::class ], + Site_Schema_Robots_Txt_Integration::get_conditionals() + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php new file mode 100644 index 00000000000..1754d2216dc --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php @@ -0,0 +1,88 @@ +once() + ->with( 'blog_public' ) + ->andReturn( $blog_public ); + + if ( $should_add_schema ) { + $expected_url = 'http://example.com/wp-json/yoast/v1/schema-aggregator/get-xml'; + + Functions\expect( 'rest_url' ) + ->once() + ->with( Main::API_V1_NAMESPACE . '/' . Site_Schema_Aggregator_Xml_Route::ROUTE_PREFIX . '/get-xml' ) + ->andReturn( $expected_url ); + + Functions\expect( 'esc_url' ) + ->once() + ->with( $expected_url ) + ->andReturn( $expected_url ); + + $robots_txt_helper + ->expects( 'add_schemamap' ) + ->with( $expected_url ) + ->once(); + } + else { + $robots_txt_helper + ->expects( 'add_schemamap' ) + ->never(); + } + + $this->instance->maybe_add_xml_schema_map( $robots_txt_helper ); + } + + /** + * Data provider for the maybe_add_xml_schema_map test. + * + * @return Generator Test data to use. + */ + public static function maybe_add_xml_schema_map_data() { + yield 'Blog is private (0)' => [ + 'blog_public' => '0', + 'should_add_schema' => false, + ]; + yield 'Blog is public (1)' => [ + 'blog_public' => '1', + 'should_add_schema' => true, + ]; + yield 'Blog is public (empty string treated as public)' => [ + 'blog_public' => '', + 'should_add_schema' => true, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php new file mode 100644 index 00000000000..b2722f8634d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php @@ -0,0 +1,31 @@ +instance->register_hooks(); + + $this->assertNotFalse( + Monkey\Actions\has( 'Yoast\WP\SEO\register_robots_rules', [ $this->instance, 'maybe_add_xml_schema_map' ] ) + ); + } +} From 030a0243230ceea016fa41f2d48fdf44a74abacc Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 15 Dec 2025 13:22:00 +0100 Subject: [PATCH 194/319] Add filter to overwrite discovery robots txt --- .../site-schema-robots-txt-integration.php | 4 ++ tests/Unit/Helpers/Robots_Txt_Helper_Test.php | 6 +-- ...egration_Maybe_Add_Xml_Schema_Map_Test.php | 43 ++++++++++++++----- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php b/src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php index 74c9cc288d0..a2ec2c3634f 100644 --- a/src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php +++ b/src/schema-aggregator/user-interface/site-schema-robots-txt-integration.php @@ -41,6 +41,10 @@ public function maybe_add_xml_schema_map( Robots_Txt_Helper $robots_txt_helper ) if ( (string) \get_option( 'blog_public' ) === '0' ) { return; } + + if ( \apply_filters( 'wpseo_disable_robots_schemamap', false ) ) { + return; + } $robots_txt_helper->add_schemamap( \esc_url( \rest_url( Main::API_V1_NAMESPACE . '/' . Site_Schema_Aggregator_Xml_Route::ROUTE_PREFIX . '/get-xml' ) ) ); } } diff --git a/tests/Unit/Helpers/Robots_Txt_Helper_Test.php b/tests/Unit/Helpers/Robots_Txt_Helper_Test.php index 50256bd69b6..484aca79881 100644 --- a/tests/Unit/Helpers/Robots_Txt_Helper_Test.php +++ b/tests/Unit/Helpers/Robots_Txt_Helper_Test.php @@ -293,8 +293,8 @@ public static function add_sitemap_dataprovider() { * * @covers ::add_allow * - * @param array $schemamaps The schemamaps to be passed to the function. - * @param array $expected The expected result. + * @param array> $schemamaps The schemamaps to be passed to the function. + * @param array> $expected The expected result. * * @return void */ @@ -309,7 +309,7 @@ public function test_add_schemamap( $schemamaps, $expected ) { /** * Data provider for test_add_schemamap. * - * @return array Data to use for test_add_schemamap. + * @return array> Data to use for test_add_schemamap. */ public static function add_schemamap_dataprovider() { $single_schemamap = [ diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php index 1754d2216dc..e51f3e4d0bb 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php @@ -26,12 +26,14 @@ final class Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test ext * * @dataProvider maybe_add_xml_schema_map_data * - * @param string $blog_public The blog_public option value. - * @param bool $should_add_schema Whether add_schemamap should be called. + * @param string $blog_public The blog_public option value. + * @param bool $filter_disabled Whether the filter disables schemamap. + * @param bool $should_add_schema Whether add_schemamap should be called. + * @param bool $should_check_filter Whether the filter should be checked. * * @return void */ - public function test_maybe_add_xml_schema_map( $blog_public, $should_add_schema ) { + public function test_maybe_add_xml_schema_map( $blog_public, $filter_disabled, $should_add_schema, $should_check_filter ) { $robots_txt_helper = Mockery::mock( Robots_Txt_Helper::class ); Functions\expect( 'get_option' ) @@ -39,6 +41,13 @@ public function test_maybe_add_xml_schema_map( $blog_public, $should_add_schema ->with( 'blog_public' ) ->andReturn( $blog_public ); + if ( $should_check_filter ) { + Functions\expect( 'apply_filters' ) + ->once() + ->with( 'wpseo_disable_robots_schemamap', false ) + ->andReturn( $filter_disabled ); + } + if ( $should_add_schema ) { $expected_url = 'http://example.com/wp-json/yoast/v1/schema-aggregator/get-xml'; @@ -73,16 +82,28 @@ public function test_maybe_add_xml_schema_map( $blog_public, $should_add_schema */ public static function maybe_add_xml_schema_map_data() { yield 'Blog is private (0)' => [ - 'blog_public' => '0', - 'should_add_schema' => false, + 'blog_public' => '0', + 'filter_disabled' => false, + 'should_add_schema' => false, + 'should_check_filter' => false, + ]; + yield 'Blog is public (1), filter not disabled' => [ + 'blog_public' => '1', + 'filter_disabled' => false, + 'should_add_schema' => true, + 'should_check_filter' => true, ]; - yield 'Blog is public (1)' => [ - 'blog_public' => '1', - 'should_add_schema' => true, + yield 'Blog is public (empty string), filter not disabled' => [ + 'blog_public' => '', + 'filter_disabled' => false, + 'should_add_schema' => true, + 'should_check_filter' => true, ]; - yield 'Blog is public (empty string treated as public)' => [ - 'blog_public' => '', - 'should_add_schema' => true, + yield 'Blog is public (1), filter disabled' => [ + 'blog_public' => '1', + 'filter_disabled' => true, + 'should_add_schema' => false, + 'should_check_filter' => true, ]; } } From 82eaf342b54aa72e4b709500f7c34395ffcc82a8 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 15 Dec 2025 14:11:00 +0100 Subject: [PATCH 195/319] Rename filters --- src/schema-aggregator/infrastructure/config.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index c6199d89597..97a75bbf3ed 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -103,7 +103,7 @@ public function get_expiration( array $data ): int { $cache_ttl = ( 30 * \MINUTE_IN_SECONDS ); } - $cache_ttl = \apply_filters( 'yoast_schema_aggregator_cache_ttl', $cache_ttl ); + $cache_ttl = \apply_filters( 'wpseo_schema_aggregator_cache_ttl', $cache_ttl ); if ( ! \is_int( $cache_ttl ) || $cache_ttl <= 0 ) { return self::DEFAULT_CACHE_TTL; @@ -122,7 +122,7 @@ public function get_expiration( array $data ): int { * @return bool True if caching is enabled, false otherwise. */ public function cache_enabled(): bool { - $enabled = \apply_filters( 'yoast_schema_aggregator_cache_enabled', true ); + $enabled = \apply_filters( 'wpseo_schema_aggregator_cache_enabled', true ); if ( \is_bool( $enabled ) ) { return $enabled; From 823912f5dda4d662a5ce59c7151a341295be184c Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 15 Dec 2025 14:19:30 +0100 Subject: [PATCH 196/319] Add `primaryImageOfPage` to the list of filtered-out properties for every schema piece --- .../base-schema-node-property-filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php index 85d44c53b4e..477fb8dbb6f 100644 --- a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php @@ -16,7 +16,7 @@ class Base_Schema_Node_Property_Filter implements Schema_Node_Property_Filter_In * * @var array */ - private const PROPERTIES_AVOID_LIST = [ 'potentialAction', 'isPartOf', 'mainEntityOfPage' ]; + private const PROPERTIES_AVOID_LIST = [ 'potentialAction', 'isPartOf', 'mainEntityOfPage', 'primaryImageOfPage' ]; /** * Filters any schema piece properties. From 55255de62024e149f6530a15dfd9df2f473c6aca Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 15 Dec 2025 14:20:04 +0100 Subject: [PATCH 197/319] When there's no specific filter for the current schema piece, we still want to apply the base filter to it --- .../application/filtering/default-filter.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index bebc9f24419..44952661e8e 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -2,6 +2,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering; +use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\Base_Schema_Node_Property_Filter; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Elements_Context_Map_Repository_Interface; @@ -67,6 +68,9 @@ public function filter( Schema_Piece_Collection $schema ): Schema_Piece_Collecti if ( \class_exists( $properties_filter_class_name ) && \is_a( $properties_filter_class_name, 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\Schema_Node_Property_Filter_Interface', true ) ) { $schema_piece = ( new $properties_filter_class_name() )->filter_properties( $schema_piece ); } + else { + $schema_piece = ( new Base_Schema_Node_Property_Filter() )->filter_properties( $schema_piece ); + } $filtered_schema[] = $schema_piece; } } From 1acbdb9a81364f977b6140ad719c41cb8c9da30e Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 15 Dec 2025 15:41:39 +0100 Subject: [PATCH 198/319] Add additional checks to routes and cache validation to make sure we don't add empty or nonsense transients to a site. --- src/schema-aggregator/application/cache/manager.php | 2 +- .../user-interface/site-schema-aggregator-route.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/application/cache/manager.php b/src/schema-aggregator/application/cache/manager.php index 5a9b25db8b8..ca36462669d 100644 --- a/src/schema-aggregator/application/cache/manager.php +++ b/src/schema-aggregator/application/cache/manager.php @@ -93,7 +93,7 @@ public function get( string $post_type, int $page, int $per_page ): ?array { */ public function set( string $post_type, int $page, int $per_page, array $data ): bool { try { - if ( $page < 1 || $per_page < 1 || ! \is_array( $data ) ) { + if ( $page < 1 || $per_page < 1 || empty( $data ) ) { return false; } diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index bca79a32e05..9fe3c49bc83 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -106,7 +106,7 @@ public function register_routes() { 'post_type' => [ 'required' => true, 'validate_callback' => static function ( $param ) { - return \is_string( $param ) && \preg_match( '/^[a-z0-9_-]+$/', $param ); + return \is_string( $param ) && \preg_match( '/^[a-z0-9_-]+$/', $param ) && \post_type_exists( $param ); }, 'sanitize_callback' => 'sanitize_key', ], @@ -117,7 +117,7 @@ public function register_routes() { $schema_aggregator_route_page['args']['page'] = [ 'default' => 1, 'validate_callback' => static function ( $param ) { - return \is_numeric( $param ) && $param > 0; + return \is_numeric( $param ) && $param > 0 && $param < \PHP_INT_MAX; }, 'sanitize_callback' => 'absint', ]; From 0aae8b32bb4f99ad47de92bf63ea1f1409582d13 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 16 Dec 2025 10:51:36 +0100 Subject: [PATCH 199/319] Adapt tests to recent changes --- .../Handle_Test.php | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php index 4c237b7727c..a759b52ba8e 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php @@ -6,6 +6,7 @@ use Generator; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; /** * Tests the Aggregate_Site_Schema_Command_Handler handle method. @@ -21,12 +22,12 @@ final class Handle_Test extends Abstract_Aggregate_Site_Schema_Command_Handler_T * * @dataProvider handle_orchestration_provider * - * @param int $page The page number. - * @param int $per_page The items per page. - * @param string $post_type The post type. - * @param array $schema_pieces The schema pieces to return. - * @param array $aggregated_pieces The aggregated pieces. - * @param array $composed_response The composed response. + * @param int $page The page number. + * @param int $per_page The items per page. + * @param string $post_type The post type. + * @param Schema_Piece_Collection $schema_pieces The schema pieces to return. + * @param Schema_Piece_Collection $aggregated_pieces The aggregated pieces. + * @param array $composed_response The composed response. * * @return void */ @@ -34,8 +35,8 @@ public function test_handle_orchestrates_aggregation_process( int $page, int $per_page, string $post_type, - array $schema_pieces, - array $aggregated_pieces, + Schema_Piece_Collection $schema_pieces, + Schema_Piece_Collection $aggregated_pieces, array $composed_response ) { $command = new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ); @@ -73,11 +74,11 @@ public function test_handle_returns_array() { $this->schema_piece_repository ->expects( 'get' ) - ->andReturn( [] ); + ->andReturn( new Schema_Piece_Collection() ); $this->schema_piece_aggregator ->expects( 'aggregate' ) - ->andReturn( [] ); + ->andReturn( new Schema_Piece_Collection() ); $this->schema_response_composer ->expects( 'compose' ) @@ -101,8 +102,8 @@ public static function handle_orchestration_provider() { 'page' => 1, 'per_page' => 50, 'post_type' => 'post', - 'schema_pieces' => [ $schema_piece_1, $schema_piece_2 ], - 'aggregated_pieces' => [ 'aggregated' => 'data' ], + 'schema_pieces' => new Schema_Piece_Collection( [ $schema_piece_1, $schema_piece_2 ] ), + 'aggregated_pieces' => new Schema_Piece_Collection( [ $schema_piece_1 ] ), 'composed_response' => [ 'response' => 'data' ], ]; @@ -110,8 +111,8 @@ public static function handle_orchestration_provider() { 'page' => 2, 'per_page' => 100, 'post_type' => 'page', - 'schema_pieces' => [], - 'aggregated_pieces' => [], + 'schema_pieces' => new Schema_Piece_Collection(), + 'aggregated_pieces' => new Schema_Piece_Collection(), 'composed_response' => [], ]; @@ -119,8 +120,8 @@ public static function handle_orchestration_provider() { 'page' => 1, 'per_page' => 25, 'post_type' => 'product', - 'schema_pieces' => [], - 'aggregated_pieces' => [ 'product' => 'schema' ], + 'schema_pieces' => new Schema_Piece_Collection(), + 'aggregated_pieces' => new Schema_Piece_Collection( [ $schema_piece_1 ] ), 'composed_response' => [ 'final' => 'response' ], ]; } From a1de6e62d8edf2a7d19c0ae04ab9282c15d58b6e Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 17 Dec 2025 16:21:59 +0100 Subject: [PATCH 200/319] Fix typo --- src/presenters/robots-txt-presenter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/presenters/robots-txt-presenter.php b/src/presenters/robots-txt-presenter.php index bfd25c52b7d..d50b070d3a3 100644 --- a/src/presenters/robots-txt-presenter.php +++ b/src/presenters/robots-txt-presenter.php @@ -165,8 +165,8 @@ private function handle_site_maps( $robots_txt_content ) { */ private function handle_schema_maps( $robots_txt_content ) { $registered_schemamaps = $this->robots_txt_helper->get_schemamap_rules(); - foreach ( $registered_schemamaps as $schamamap ) { - $robots_txt_content .= self::SCHEMAMAP_FIELD . ': ' . $schamamap . \PHP_EOL; + foreach ( $registered_schemamaps as $schemamap ) { + $robots_txt_content .= self::SCHEMAMAP_FIELD . ': ' . $schemamap . \PHP_EOL; } return $robots_txt_content; From e8855b3383d33fa23c0f24b199400c48851f9226 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 17 Dec 2025 16:23:00 +0100 Subject: [PATCH 201/319] Fix tests --- tests/Unit/Presenters/Robots_Txt_Presenter_Test.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php b/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php index 88a5fd227fa..d63a9cfa281 100644 --- a/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php +++ b/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php @@ -52,6 +52,7 @@ protected function set_up() { * @covers ::present * @covers ::handle_user_agents * @covers ::handle_site_maps + * @covers ::handle_schema_maps * * @param array $robots_txt_user_agents Output for the registered user agents. * @param array $sitemaps Output for the registered sitemaps. @@ -68,6 +69,10 @@ public function test_present( $robots_txt_user_agents, $sitemaps, $expected ) { ->expects( 'get_sitemap_rules' ) ->andReturn( $sitemaps ); + $this->robots_txt_helper + ->expects( 'get_schemamap_rules' ) + ->andReturn( [] ); + $this->assertSame( $expected, $this->instance->present() From 78d0b9d9350b280b9cdf90d578aa063d3e916d5e Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 18 Dec 2025 15:54:00 +0100 Subject: [PATCH 202/319] test: add unit tests for Config and Aggregator_Config infrastructure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added comprehensive unit tests for Config infrastructure: - Config_Cache_Enabled_Test - Config_Get_Big_Per_Post_Type_Test - Config_Get_Default_Per_Post_Type_Test - Config_Get_Expiration_Test - Config_Get_Max_Per_Page_Test - Config_Get_Per_Page_Test Added unit tests for Aggregator_Config infrastructure: - Aggregator_Config_Get_Allowed_Post_Types_Test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../Abstract_Aggregator_Config_Test.php | 52 +++++++ ...tor_Config_Get_Allowed_Post_Types_Test.php | 112 ++++++++++++++ .../Config/Abstract_Config_Test.php | 33 ++++ .../Config/Config_Cache_Enabled_Test.php | 81 ++++++++++ .../Config_Get_Big_Per_Post_Type_Test.php | 95 ++++++++++++ .../Config_Get_Default_Per_Post_Type_Test.php | 95 ++++++++++++ .../Config/Config_Get_Expiration_Test.php | 145 ++++++++++++++++++ .../Config/Config_Get_Max_Per_Page_Test.php | 25 +++ .../Config/Config_Get_Per_Page_Test.php | 144 +++++++++++++++++ 9 files changed, 782 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Abstract_Aggregator_Config_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Config/Abstract_Config_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Abstract_Aggregator_Config_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Abstract_Aggregator_Config_Test.php new file mode 100644 index 00000000000..6041ea9ee54 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Abstract_Aggregator_Config_Test.php @@ -0,0 +1,52 @@ +woocommerce_conditional = Mockery::mock( WooCommerce_Conditional::class ); + $this->post_type_helper = Mockery::mock( Post_Type_Helper::class ); + $this->instance = new Aggregator_Config( $this->woocommerce_conditional, $this->post_type_helper ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php new file mode 100644 index 00000000000..b1ec7d6ce25 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php @@ -0,0 +1,112 @@ + $default_post_types The default post types from the helper. + * @param mixed $filtered_value The value returned by the filter. + * @param array $expected The expected result. + * + * @return void + */ + public function test_get_allowed_post_types( $default_post_types, $filtered_value, $expected ) { + $this->post_type_helper + ->expects( 'get_indexable_post_types' ) + ->once() + ->andReturn( $default_post_types ); + + Functions\expect( 'apply_filters' ) + ->once() + ->with( 'wpseo_schema_aggregator_post_types', $default_post_types ) + ->andReturn( $filtered_value ); + + $this->assertEquals( $expected, $this->instance->get_allowed_post_types() ); + } + + /** + * Data provider for the get_allowed_post_types test. + * + * @return Generator Test data to use. + */ + public static function get_allowed_post_types_data() { + yield 'Filter returns valid array - uses filtered value' => [ + 'default_post_types' => [ 'post', 'page' ], + 'filtered_value' => [ 'post', 'page', 'custom' ], + 'expected' => [ 'post', 'page', 'custom' ], + ]; + + yield 'Filter returns same as default - uses default value' => [ + 'default_post_types' => [ 'post', 'page', 'product' ], + 'filtered_value' => [ 'post', 'page', 'product' ], + 'expected' => [ 'post', 'page', 'product' ], + ]; + + yield 'Filter returns empty array - uses empty array' => [ + 'default_post_types' => [ 'post', 'page' ], + 'filtered_value' => [], + 'expected' => [], + ]; + + yield 'Filter returns string - falls back to default' => [ + 'default_post_types' => [ 'post', 'page' ], + 'filtered_value' => 'invalid_string', + 'expected' => [ 'post', 'page' ], + ]; + + yield 'Filter returns null - falls back to default' => [ + 'default_post_types' => [ 'post', 'page' ], + 'filtered_value' => null, + 'expected' => [ 'post', 'page' ], + ]; + + yield 'Filter returns integer - falls back to default' => [ + 'default_post_types' => [ 'post', 'page' ], + 'filtered_value' => 123, + 'expected' => [ 'post', 'page' ], + ]; + + yield 'Filter returns boolean false - falls back to default' => [ + 'default_post_types' => [ 'post', 'page' ], + 'filtered_value' => false, + 'expected' => [ 'post', 'page' ], + ]; + + yield 'Filter returns object - falls back to default' => [ + 'default_post_types' => [ 'post', 'page' ], + 'filtered_value' => new stdClass(), + 'expected' => [ 'post', 'page' ], + ]; + + yield 'Single post type from helper' => [ + 'default_post_types' => [ 'post' ], + 'filtered_value' => [ 'post' ], + 'expected' => [ 'post' ], + ]; + + yield 'Many post types including custom' => [ + 'default_post_types' => [ 'post', 'page', 'product', 'event', 'recipe' ], + 'filtered_value' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], + 'expected' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Abstract_Config_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Abstract_Config_Test.php new file mode 100644 index 00000000000..0ed272ef196 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Abstract_Config_Test.php @@ -0,0 +1,33 @@ +instance = new Config(); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php new file mode 100644 index 00000000000..86a3da4b54c --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php @@ -0,0 +1,81 @@ +once() + ->with( 'wpseo_schema_aggregator_cache_enabled', true ) + ->andReturn( $filtered_value ); + + $this->assertEquals( $expected, $this->instance->cache_enabled() ); + } + + /** + * Data provider for the cache_enabled test. + * + * @return Generator Test data to use. + */ + public static function cache_enabled_data() { + yield 'Default true - cache enabled' => [ + 'filtered_value' => true, + 'expected' => true, + ]; + + yield 'Filter returns false - cache disabled' => [ + 'filtered_value' => false, + 'expected' => false, + ]; + + yield 'Filter returns non-boolean string - defaults to true' => [ + 'filtered_value' => 'yes', + 'expected' => true, + ]; + + yield 'Filter returns non-boolean integer - defaults to true' => [ + 'filtered_value' => 1, + 'expected' => true, + ]; + + yield 'Filter returns null - defaults to true' => [ + 'filtered_value' => null, + 'expected' => true, + ]; + + yield 'Filter returns array - defaults to true' => [ + 'filtered_value' => [], + 'expected' => true, + ]; + + yield 'Filter returns object - defaults to true' => [ + 'filtered_value' => new stdClass(), + 'expected' => true, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php new file mode 100644 index 00000000000..2bd0fe138ff --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php @@ -0,0 +1,95 @@ +once() + ->with( 'wpseo_schema_aggregator_per_page_big', 100 ) + ->andReturn( $filtered_value ); + + $this->assertEquals( $expected, $this->instance->get_big_per_post_type() ); + } + + /** + * Data provider for the get_big_per_post_type test. + * + * @return Generator Test data to use. + */ + public static function get_big_per_post_type_data() { + yield 'Default value 100' => [ + 'filtered_value' => 100, + 'expected' => 100, + ]; + + yield 'Filter returns valid positive integer' => [ + 'filtered_value' => 50, + 'expected' => 50, + ]; + + yield 'Filter returns larger valid integer' => [ + 'filtered_value' => 200, + 'expected' => 200, + ]; + + yield 'Filter returns zero - falls back to default' => [ + 'filtered_value' => 0, + 'expected' => 100, + ]; + + yield 'Filter returns negative - falls back to default' => [ + 'filtered_value' => -50, + 'expected' => 100, + ]; + + yield 'Filter returns string number - casts to int' => [ + 'filtered_value' => '150', + 'expected' => 150, + ]; + + yield 'Filter returns non-numeric string - casts to zero, falls back to default' => [ + 'filtered_value' => 'invalid', + 'expected' => 100, + ]; + + yield 'Filter returns float - casts to int' => [ + 'filtered_value' => 75.5, + 'expected' => 75, + ]; + + yield 'Filter returns 1 - minimum valid value' => [ + 'filtered_value' => 1, + 'expected' => 1, + ]; + + yield 'Filter returns large number over max - not capped here' => [ + 'filtered_value' => 2000, + 'expected' => 2000, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php new file mode 100644 index 00000000000..9297fde3951 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php @@ -0,0 +1,95 @@ +once() + ->with( 'wpseo_schema_aggregator_per_page', 1000 ) + ->andReturn( $filtered_value ); + + $this->assertEquals( $expected, $this->instance->get_default_per_post_type() ); + } + + /** + * Data provider for the get_default_per_post_type test. + * + * @return Generator Test data to use. + */ + public static function get_default_per_post_type_data() { + yield 'Default value 1000' => [ + 'filtered_value' => 1000, + 'expected' => 1000, + ]; + + yield 'Filter returns valid positive integer' => [ + 'filtered_value' => 500, + 'expected' => 500, + ]; + + yield 'Filter returns larger valid integer' => [ + 'filtered_value' => 1500, + 'expected' => 1500, + ]; + + yield 'Filter returns zero - falls back to default' => [ + 'filtered_value' => 0, + 'expected' => 1000, + ]; + + yield 'Filter returns negative - falls back to default' => [ + 'filtered_value' => -100, + 'expected' => 1000, + ]; + + yield 'Filter returns string number - casts to int' => [ + 'filtered_value' => '750', + 'expected' => 750, + ]; + + yield 'Filter returns non-numeric string - casts to zero, falls back to default' => [ + 'filtered_value' => 'invalid', + 'expected' => 1000, + ]; + + yield 'Filter returns float - casts to int' => [ + 'filtered_value' => 999.9, + 'expected' => 999, + ]; + + yield 'Filter returns 1 - minimum valid value' => [ + 'filtered_value' => 1, + 'expected' => 1, + ]; + + yield 'Filter returns large number over max - not capped here' => [ + 'filtered_value' => 5000, + 'expected' => 5000, + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php new file mode 100644 index 00000000000..f3023cf446b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php @@ -0,0 +1,145 @@ + $data The data to cache. + * @param mixed $filtered_ttl The value returned by the filter. + * @param int $expected The expected result. + * + * @return void + */ + public function test_get_expiration( $data, $filtered_ttl, $expected ) { + Functions\expect( 'apply_filters' ) + ->once() + ->with( 'wpseo_schema_aggregator_cache_ttl', Mockery::type( 'int' ) ) + ->andReturn( $filtered_ttl ); + + $this->assertEquals( $expected, $this->instance->get_expiration( $data ) ); + } + + /** + * Data provider for the get_expiration test. + * + * @return Generator Test data to use. + */ + public static function get_expiration_data() { + yield 'Small data (< 100KB) - shorter cache' => [ + 'data' => self::generate_array_of_size( 50000 ), + 'filtered_ttl' => 1800, + 'expected' => 1800, + ]; + + yield 'Medium data (100KB - 1MB) - default cache' => [ + 'data' => self::generate_array_of_size( 500000 ), + 'filtered_ttl' => 3600, + 'expected' => 3600, + ]; + + yield 'Large data (> 1MB) - longer cache' => [ + 'data' => self::generate_array_of_size( 1100000 ), + 'filtered_ttl' => 21600, + 'expected' => 21600, + ]; + + yield 'Filter returns invalid (zero) - falls back to default' => [ + 'data' => self::generate_array_of_size( 500000 ), + 'filtered_ttl' => 0, + 'expected' => 3600, + ]; + + yield 'Filter returns invalid (negative) - falls back to default' => [ + 'data' => self::generate_array_of_size( 500000 ), + 'filtered_ttl' => -100, + 'expected' => 3600, + ]; + + yield 'Filter returns non-integer (string) - falls back to default' => [ + 'data' => self::generate_array_of_size( 500000 ), + 'filtered_ttl' => 'invalid', + 'expected' => 3600, + ]; + + yield 'Filter returns valid positive integer' => [ + 'data' => self::generate_array_of_size( 50000 ), + 'filtered_ttl' => 7200, + 'expected' => 7200, + ]; + + yield 'Empty array - small data cache' => [ + 'data' => [], + 'filtered_ttl' => 1800, + 'expected' => 1800, + ]; + + yield 'Data just below small boundary' => [ + 'data' => self::generate_array_of_size( 102399 ), + 'filtered_ttl' => 1800, + 'expected' => 1800, + ]; + + yield 'Data at small boundary (102400 bytes) - uses default' => [ + 'data' => self::generate_array_of_size( 102400 ), + 'filtered_ttl' => 3600, + 'expected' => 3600, + ]; + + yield 'Data just above small boundary' => [ + 'data' => self::generate_array_of_size( 102401 ), + 'filtered_ttl' => 3600, + 'expected' => 3600, + ]; + + yield 'Data just below large boundary' => [ + 'data' => self::generate_array_of_size( 1048575 ), + 'filtered_ttl' => 3600, + 'expected' => 3600, + ]; + + yield 'Data just above large boundary (1048577 bytes) - uses large cache' => [ + 'data' => self::generate_array_of_size( 1048577 ), + 'filtered_ttl' => 21600, + 'expected' => 21600, + ]; + } + + /** + * Helper method to generate an array of approximately the specified serialized size. + * + * @param int $target_bytes The target size in bytes. + * + * @return array An array with approximately the specified serialized size. + */ + private static function generate_array_of_size( $target_bytes ) { + $data = []; + $key = 0; + // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- This is just a test. + $length = \strlen( \serialize( $data ) ); + while ( $length < $target_bytes ) { + $data[ 'key_' . $key ] = \str_repeat( 'x', 100 ); + ++$key; + } + + return $data; + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php new file mode 100644 index 00000000000..8dafc7d671f --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php @@ -0,0 +1,25 @@ +assertEquals( 1000, $this->instance->get_max_per_page() ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php new file mode 100644 index 00000000000..9f2ab88c316 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php @@ -0,0 +1,144 @@ +once() + ->with( 'wpseo_schema_aggregator_big_schema_post_types', [ 'product' ] ) + ->andReturn( $big_schema_post_types_filter ); + + $big_schema_list = \is_array( $big_schema_post_types_filter ) ? $big_schema_post_types_filter : [ 'product' ]; + $is_big_schema = \in_array( $post_type, $big_schema_list, true ); + + if ( $is_big_schema ) { + Functions\expect( 'apply_filters' ) + ->once() + ->with( 'wpseo_schema_aggregator_per_page_big', 100 ) + ->andReturn( $per_page_big_filter ); + } + else { + Functions\expect( 'apply_filters' ) + ->once() + ->with( 'wpseo_schema_aggregator_per_page', 1000 ) + ->andReturn( $per_page_default_filter ); + } + + $this->assertEquals( $expected, $this->instance->get_per_page( $post_type ) ); + } + + /** + * Data provider for the get_per_page test. + * + * @return Generator Test data to use. + */ + public static function get_per_page_data() { + yield 'Product post type with default big schema list - returns big per page' => [ + 'post_type' => 'product', + 'big_schema_post_types_filter' => [ 'product' ], + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 1000, + 'expected' => 100, + ]; + + yield 'Post type with default settings - returns default per page' => [ + 'post_type' => 'post', + 'big_schema_post_types_filter' => [ 'product' ], + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 1000, + 'expected' => 1000, + ]; + + yield 'Page post type - returns default per page' => [ + 'post_type' => 'page', + 'big_schema_post_types_filter' => [ 'product' ], + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 1000, + 'expected' => 1000, + ]; + + yield 'Custom post type added to big schema list via filter' => [ + 'post_type' => 'event', + 'big_schema_post_types_filter' => [ 'product', 'event' ], + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 1000, + 'expected' => 100, + ]; + + yield 'Big schema filter returns non-array - falls back to default list' => [ + 'post_type' => 'product', + 'big_schema_post_types_filter' => 'invalid', + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 1000, + 'expected' => 100, + ]; + + yield 'Big schema filter returns empty array - no big schema types' => [ + 'post_type' => 'product', + 'big_schema_post_types_filter' => [], + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 1000, + 'expected' => 1000, + ]; + + yield 'Per page exceeds max - capped at max' => [ + 'post_type' => 'post', + 'big_schema_post_types_filter' => [ 'product' ], + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 1500, + 'expected' => 1000, + ]; + + yield 'Big per page exceeds max - capped at max' => [ + 'post_type' => 'product', + 'big_schema_post_types_filter' => [ 'product' ], + 'per_page_big_filter' => 2000, + 'per_page_default_filter' => 1000, + 'expected' => 1000, + ]; + + yield 'Custom per page values within limits' => [ + 'post_type' => 'post', + 'big_schema_post_types_filter' => [ 'product' ], + 'per_page_big_filter' => 100, + 'per_page_default_filter' => 500, + 'expected' => 500, + ]; + + yield 'Big per page custom value within limits' => [ + 'post_type' => 'product', + 'big_schema_post_types_filter' => [ 'product' ], + 'per_page_big_filter' => 50, + 'per_page_default_filter' => 1000, + 'expected' => 50, + ]; + } +} From 208b496dea417cbcd2e4ee24dea074a59f5f4093 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 5 Jan 2026 12:38:13 +0100 Subject: [PATCH 203/319] Fix enhancers to work on single schema pieces --- .../enhancement/article-schema-enhancer.php | 43 +++++++++---------- .../enhancement/person-schema-enhancer.php | 12 +++--- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php index ebece01559d..e4cde46f919 100644 --- a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php @@ -42,32 +42,29 @@ public function set_article_config( Article_Config $config ) { * @return Schema_Piece The enhanced schema piece. */ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Schema_Piece { + $schema_data = $schema_piece->get_data(); + if ( ! isset( $schema_data['@type'] ) ) { + return $schema_piece; + } + if ( + \in_array( + $schema_data['@type'], + [ + 'Article', + 'NewsArticle', + 'BlogPosting', + ], + true + ) ) { + $schema_data = $this->enhance_schema_piece( $schema_data, $indexable ); + } - $data = $schema_piece->get_data(); - foreach ( $data as $key => $schema_data ) { - if ( ! isset( $schema_data['@type'] ) ) { - continue; - } - if ( - \in_array( - $schema_data['@type'], - [ - 'Article', - 'NewsArticle', - 'BlogPosting', - ], - true - ) ) { - $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); - } - - if ( + if ( \is_array( $schema_data['@type'] ) && \in_array( 'Article', $schema_data['@type'], true ) ) { - $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); - } + $schema_data = $this->enhance_schema_piece( $schema_data, $indexable ); } - return new Schema_Piece( $data, $schema_piece->get_type() ); + return new Schema_Piece( $schema_data, $schema_piece->get_type() ); } /** @@ -78,7 +75,7 @@ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Sch * * @return array The enhanced schema data. */ - private function enhance_schema_piece( $schema_data, $indexable ) { + private function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { try { $has_excerpt = false; diff --git a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php index 952e2e60b16..cea231d5f2b 100644 --- a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php @@ -40,14 +40,12 @@ public function set_person_config( Person_Config $config ) { * @return Schema_Piece The enhanced schema piece. */ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Schema_Piece { - $data = $schema_piece->get_data(); - foreach ( $data as $key => $schema_data ) { - if ( isset( $schema_data['@type'] ) && $schema_data['@type'] === 'Person' ) { - $data[ $key ] = $this->enhance_schema_piece( $schema_data, $indexable ); - } + $schema_data = $schema_piece->get_data(); + if ( isset( $schema_data['@type'] ) && $schema_data['@type'] === 'Person' ) { + $schema_data = $this->enhance_schema_piece( $schema_data, $indexable ); } - return new Schema_Piece( $data, $schema_piece->get_type() ); + return new Schema_Piece( $schema_data, $schema_piece->get_type() ); } /** @@ -58,7 +56,7 @@ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Sch * * @return array The enhanced schema data. */ - private function enhance_schema_piece( $schema_data, $indexable ) { + private function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { try { // Add jobTitle if enabled and not already present. if ( $this->config->is_enhancement_enabled( 'person_job_title' ) && ! isset( $entity['jobTitle'] ) ) { From 7fa398825d1e1b4e76a59b95e048c5b1708c0dbd Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 8 Jan 2026 12:28:00 +0100 Subject: [PATCH 204/319] Add unit tests for the cache integrations. --- ...ables_Update_Listener_Integration_Test.php | 76 +++++++ ...ener_Integration_Get_Conditionals_Test.php | 31 +++ ...stener_Integration_Register_Hooks_Test.php | 31 +++ ..._Listener_Integration_Reset_Cache_Test.php | 193 ++++++++++++++++++ ...e_Change_Listener_Integration_TestCase.php | 76 +++++++ ...ener_Integration_Get_Conditionals_Test.php | 32 +++ ...stener_Integration_Register_Hooks_Test.php | 31 +++ ..._Listener_Integration_Reset_Cache_Test.php | 184 +++++++++++++++++ 8 files changed, 654 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php new file mode 100644 index 00000000000..598ac2d59ad --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php @@ -0,0 +1,76 @@ +indexable_repository = Mockery::mock( Indexable_Repository::class ); + $this->config = Mockery::mock( Config::class ); + $this->manager = Mockery::mock( Manager::class ); + $this->xml_manager = Mockery::mock( Xml_Manager::class ); + + $this->instance = new Indexables_Update_Listener_Integration( + $this->indexable_repository, + $this->config, + $this->manager, + $this->xml_manager + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php new file mode 100644 index 00000000000..8b72409a97b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php @@ -0,0 +1,31 @@ +assertEquals( + [ Schema_Aggregator_Conditional::class ], + Indexables_Update_Listener_Integration::get_conditionals() + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php new file mode 100644 index 00000000000..293b1e07364 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php @@ -0,0 +1,31 @@ +instance->register_hooks(); + + $this->assertNotFalse( + Monkey\Actions\has( 'wpseo_save_indexable', [ $this->instance, 'reset_cache' ] ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php new file mode 100644 index 00000000000..0af5b5c789d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php @@ -0,0 +1,193 @@ + null, + 'object_sub_type' => null, + ]; + $indexable = (object) [ + 'permalink' => 'https://example.com/test', + 'object_sub_type' => null, + ]; + + yield 'permalink is null with no object_sub_type' => [ + 'indexable' => $indexable, + 'indexable_before' => $indexable_before, + ]; + + $indexable_before2 = (object) [ + 'permalink' => null, + 'object_sub_type' => 'post', + ]; + $indexable2 = (object) [ + 'permalink' => 'https://example.com/post', + 'object_sub_type' => 'post', + ]; + + yield 'permalink is null with object_sub_type' => [ + 'indexable' => $indexable2, + 'indexable_before' => $indexable_before2, + ]; + } + + /** + * Tests that reset_cache invalidates all caches when permalink is null. + * + * @dataProvider permalink_is_null_provider + * + * @param object $indexable The indexable object. + * @param object $indexable_before The indexable before the update. + * + * @return void + */ + public function test_reset_cache_invalidates_all_when_permalink_is_null( $indexable, $indexable_before ) { + $this->manager->shouldReceive( 'invalidate_all' )->once(); + $this->xml_manager->shouldReceive( 'invalidate' )->once(); + + $result = $this->instance->reset_cache( $indexable, $indexable_before ); + + $this->assertFalse( $result ); + } + + /** + * Data provider for object_sub_type is not null scenarios. + * + * @return Generator + */ + public function object_sub_type_provider() { + yield 'post type' => [ + 'object_sub_type' => 'post', + 'indexable_id' => 123, + 'count_before' => 5, + 'per_page' => 10, + 'expected_page' => 1, + ]; + + yield 'page type' => [ + 'object_sub_type' => 'page', + 'indexable_id' => 456, + 'count_before' => 15, + 'per_page' => 10, + 'expected_page' => 2, + ]; + + yield 'custom post type' => [ + 'object_sub_type' => 'product', + 'indexable_id' => 789, + 'count_before' => 25, + 'per_page' => 20, + 'expected_page' => 2, + ]; + } + + /** + * Tests that reset_cache invalidates specific cache when object_sub_type is not null. + * + * @dataProvider object_sub_type_provider + * + * @param string $object_sub_type The object sub type. + * @param int $indexable_id The indexable ID. + * @param int $count_before The count of items before this indexable. + * @param int $per_page Items per page. + * @param int $expected_page The expected page number. + * + * @return void + */ + public function test_reset_cache_invalidates_specific_when_object_sub_type_is_not_null( $object_sub_type, $indexable_id, $count_before, $per_page, $expected_page ) { + $indexable_before = (object) [ + 'permalink' => 'https://example.com/test', + 'object_sub_type' => $object_sub_type, + ]; + $indexable = (object) [ + 'permalink' => 'https://example.com/test', + 'object_sub_type' => $object_sub_type, + 'id' => $indexable_id, + ]; + + // Mock the repository query chain for get_page_number. + $query_mock = Mockery::mock(); + $query_mock->shouldReceive( 'where_raw' ) + ->with( '( is_public IS NULL OR is_public = 1 )' ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'where' ) + ->with( 'object_sub_type', $object_sub_type ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'where' ) + ->with( 'post_status', 'publish' ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'where_lt' ) + ->with( 'id', $indexable_id ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'count' ) + ->once() + ->andReturn( $count_before ); + + $this->indexable_repository->shouldReceive( 'query' ) + ->once() + ->andReturn( $query_mock ); + + $this->config->shouldReceive( 'get_per_page' ) + ->with( $object_sub_type ) + ->once() + ->andReturn( $per_page ); + + $this->manager->shouldReceive( 'invalidate' ) + ->with( $object_sub_type, $expected_page ) + ->once(); + $this->xml_manager->shouldReceive( 'invalidate' )->once(); + + $result = $this->instance->reset_cache( $indexable, $indexable_before ); + + $this->assertTrue( $result ); + } + + /** + * Tests that reset_cache returns true when no conditions are met. + * + * @return void + */ + public function test_reset_cache_returns_true_when_no_conditions_met() { + $indexable_before = (object) [ + 'permalink' => 'https://example.com/test', + 'object_sub_type' => null, + ]; + $indexable = (object) [ + 'permalink' => 'https://example.com/test', + 'object_sub_type' => null, + ]; + + $this->manager->shouldNotReceive( 'invalidate_all' ); + $this->manager->shouldNotReceive( 'invalidate' ); + $this->xml_manager->shouldNotReceive( 'invalidate' ); + + $result = $this->instance->reset_cache( $indexable, $indexable_before ); + + $this->assertTrue( $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php new file mode 100644 index 00000000000..5c7c809f28d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php @@ -0,0 +1,76 @@ +indexable_repository = Mockery::mock( Indexable_Repository::class ); + $this->config = Mockery::mock( Config::class ); + $this->manager = Mockery::mock( Manager::class ); + $this->xml_manager = Mockery::mock( Xml_Manager::class ); + + $this->instance = new WooCommerce_Product_Type_Change_Listener_Integration( + $this->indexable_repository, + $this->config, + $this->manager, + $this->xml_manager + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php new file mode 100644 index 00000000000..877e9c3a7e5 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php @@ -0,0 +1,32 @@ +instance->get_conditionals(); + + $this->assertIsArray( $actual ); + $this->assertContains( Schema_Aggregator_Conditional::class, $actual ); + $this->assertContains( WooCommerce_Conditional::class, $actual ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php new file mode 100644 index 00000000000..ddffd85b3d5 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php @@ -0,0 +1,31 @@ +instance->register_hooks(); + + $this->assertNotFalse( + Monkey\Actions\has( 'woocommerce_product_type_changed', [ $this->instance, 'reset_cache' ] ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php new file mode 100644 index 00000000000..241c8851d88 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php @@ -0,0 +1,184 @@ + [ + 'product_id' => 0, + ]; + + yield 'product ID is null' => [ + 'product_id' => null, + ]; + + yield 'product ID is false' => [ + 'product_id' => false, + ]; + } + + /** + * Tests that reset_cache returns false when product ID is empty. + * + * @dataProvider product_id_is_empty_provider + * + * @param mixed $product_id The product ID. + * + * @return void + */ + public function test_reset_cache_returns_false_when_product_id_is_empty( $product_id ) { + $product = Mockery::mock( 'WC_Product' ); + $product->shouldReceive( 'get_id' ) + ->once() + ->andReturn( $product_id ); + + $this->indexable_repository->shouldNotReceive( 'find_by_id_and_type' ); + $this->manager->shouldNotReceive( 'invalidate_all' ); + $this->manager->shouldNotReceive( 'invalidate' ); + $this->xml_manager->shouldNotReceive( 'invalidate' ); + + $result = $this->instance->reset_cache( $product ); + + $this->assertFalse( $result ); + } + + /** + * Tests that reset_cache invalidates all when indexable is not found. + * + * @return void + */ + public function test_reset_cache_invalidates_all_when_indexable_not_found() { + $product = Mockery::mock( 'WC_Product' ); + $product->shouldReceive( 'get_id' ) + ->once() + ->andReturn( 123 ); + + $this->indexable_repository->shouldReceive( 'find_by_id_and_type' ) + ->with( 123, 'post' ) + ->once() + ->andReturn( null ); + + $this->manager->shouldReceive( 'invalidate_all' )->once(); + $this->xml_manager->shouldReceive( 'invalidate' )->once(); + + $result = $this->instance->reset_cache( $product ); + + $this->assertFalse( $result ); + } + + /** + * Data provider for indexable found scenarios. + * + * @return Generator + */ + public function indexable_found_provider() { + yield 'first page' => [ + 'product_id' => 123, + 'count_before' => 5, + 'per_page' => 10, + 'expected_page' => 1, + ]; + + yield 'second page' => [ + 'product_id' => 456, + 'count_before' => 15, + 'per_page' => 10, + 'expected_page' => 2, + ]; + + yield 'third page with custom per_page' => [ + 'product_id' => 789, + 'count_before' => 40, + 'per_page' => 20, + 'expected_page' => 3, + ]; + } + + /** + * Tests that reset_cache invalidates specific cache when indexable is found. + * + * @dataProvider indexable_found_provider + * + * @param int $product_id The product ID. + * @param int $count_before The count of items before this product. + * @param int $per_page Items per page. + * @param int $expected_page The expected page number. + * + * @return void + */ + public function test_reset_cache_invalidates_specific_when_indexable_found( $product_id, $count_before, $per_page, $expected_page ) { + $product = Mockery::mock( 'WC_Product' ); + $product->shouldReceive( 'get_id' ) + ->once() + ->andReturn( $product_id ); + + $indexable = (object) [ + 'id' => $product_id, + 'object_sub_type' => 'product', + ]; + + $this->indexable_repository->shouldReceive( 'find_by_id_and_type' ) + ->with( $product_id, 'post' ) + ->once() + ->andReturn( $indexable ); + + // Mock the repository query chain for get_page_number. + $query_mock = Mockery::mock(); + $query_mock->shouldReceive( 'where_raw' ) + ->with( '( is_public IS NULL OR is_public = 1 )' ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'where' ) + ->with( 'object_sub_type', 'product' ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'where' ) + ->with( 'post_status', 'publish' ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'where_lt' ) + ->with( 'id', $product_id ) + ->once() + ->andReturnSelf(); + $query_mock->shouldReceive( 'count' ) + ->once() + ->andReturn( $count_before ); + + $this->indexable_repository->shouldReceive( 'query' ) + ->once() + ->andReturn( $query_mock ); + + $this->config->shouldReceive( 'get_per_page' ) + ->with( 'product' ) + ->once() + ->andReturn( $per_page ); + + $this->manager->shouldReceive( 'invalidate' ) + ->with( 'product', $expected_page ) + ->once(); + $this->xml_manager->shouldReceive( 'invalidate' )->once(); + + $result = $this->instance->reset_cache( $product ); + + $this->assertTrue( $result ); + } +} From ecf7722ebd99112170dadd6b1f74d229957632c4 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 8 Jan 2026 15:00:51 +0100 Subject: [PATCH 205/319] Update ai-tools to add schema aggregator. --- packages/js/src/settings/site-features/ai-tools.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/js/src/settings/site-features/ai-tools.js b/packages/js/src/settings/site-features/ai-tools.js index ba3c3c53ca9..40f9b4505fc 100644 --- a/packages/js/src/settings/site-features/ai-tools.js +++ b/packages/js/src/settings/site-features/ai-tools.js @@ -1,6 +1,7 @@ import { __ } from "@wordpress/i18n"; import { ReactComponent as AIGeneratorIcon } from "../../../../../images/icon-sparkles.svg"; import { ReactComponent as LlmtxtIcon } from "../../../../../images/icon-llms-txt.svg"; +import { ReactComponent as SchemaAggregationIcon } from "../../../../../images/icon-schema-aggregation-endpoint.svg"; export const aiToolsFeatures = { aiGenerator: { @@ -27,4 +28,16 @@ export const aiToolsFeatures = { learnMoreLinkId: "link-llms-txt", learnMoreLinkAriaLabel: __( "llms.txt", "wordpress-seo" ), }, + schemaAggregation: { + name: "wpseo.enable_schema_aggregation_endpoint", + id: "card-wpseo-enable_schema_aggregation_endpoint", + inputId: "input-wpseo-enable_schema_aggregation_endpoint", + Icon: SchemaAggregationIcon, + isPremiumFeature: false, + title: __( "Schema aggregation endpoint", "wordpress-seo" ), + description: __( "Provides everything required to connect with your site's public structured data. This enables conversational interfaces like NLWeb to power natural language queries on your content.", "wordpress-seo" ), + learnMoreUrl: "https://yoa.st/site-features-schema-aggregation-endpoint-learn-more", + learnMoreLinkId: "link-schema-aggregation-endpoint", + learnMoreLinkAriaLabel: __( "Schema aggregation endpoint", "wordpress-seo" ), + }, }; From b9ac6f02cb93e0bf47b692a5aa19623b0e5d6f37 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 09:44:00 +0100 Subject: [PATCH 206/319] Add unit tests for Schema Enhancement classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive unit tests for Abstract_Schema_Enhancer and Schema_Enhancement_Factory classes: - Abstract_Schema_Enhancer: Tests trim_content_to_max_length method with various scenarios including word boundary breaking, ellipsis addition, and edge cases - Schema_Enhancement_Factory: Tests constructor initialization and get_enhancer method for Article and Person types, including multiple type arrays Tests follow Yoast patterns with separate files per method and abstract base classes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ...Abstract_Abstract_Schema_Enhancer_Test.php | 49 ++++++ .../Trim_Content_To_Max_Length_Test.php | 151 ++++++++++++++++++ ...stract_Schema_Enhancement_Factory_Test.php | 53 ++++++ .../Constructor_Test.php | 33 ++++ .../Get_Enhancer_Test.php | 107 +++++++++++++ 5 files changed, 393 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php new file mode 100644 index 00000000000..dbecb8b0c4a --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php @@ -0,0 +1,49 @@ +instance = new Concrete_Schema_Enhancer_For_Testing(); + } +} + +/** + * Concrete implementation of Abstract_Schema_Enhancer for testing protected methods. + */ +class Concrete_Schema_Enhancer_For_Testing extends Abstract_Schema_Enhancer { + + /** + * Exposes the protected trim_content_to_max_length method for testing. + * + * @param int $max_length Maximum length of content. + * @param string $content The content to trim. + * + * @return string The trimmed content. + */ + public function public_trim_content_to_max_length( int $max_length, string $content ): string { + return $this->trim_content_to_max_length( $max_length, $content ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php new file mode 100644 index 00000000000..bbb309fa074 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php @@ -0,0 +1,151 @@ +instance->public_trim_content_to_max_length( 0, $content ); + + $this->assertSame( $content, $result ); + } + + /** + * Tests trim_content_to_max_length() returns content unchanged when content is shorter than max_length. + * + * @return void + */ + public function test_trim_content_returns_unchanged_when_shorter_than_max() { + $content = 'Short content'; + + $result = $this->instance->public_trim_content_to_max_length( 100, $content ); + + $this->assertSame( $content, $result ); + } + + /** + * Tests trim_content_to_max_length() trims content at word boundary. + * + * @return void + */ + public function test_trim_content_breaks_at_word_boundary() { + $content = 'This is a long piece of content that needs trimming'; + + $result = $this->instance->public_trim_content_to_max_length( 30, $content ); + + // The method trims to 30 chars, then looks for space within 90% threshold + $this->assertSame( 'This is a long piece of conten...', $result ); + } + + /** + * Tests trim_content_to_max_length() adds ellipsis when trimming. + * + * @return void + */ + public function test_trim_content_adds_ellipsis() { + $content = 'This content is too long and will be trimmed'; + + $result = $this->instance->public_trim_content_to_max_length( 25, $content ); + + $this->assertStringEndsWith( '...', $result ); + } + + /** + * Tests trim_content_to_max_length() with no spaces (breaks mid-word). + * + * @return void + */ + public function test_trim_content_breaks_mid_word_when_no_spaces() { + $content = 'Thisisaverylongwordwithoutanyspaces'; + + $result = $this->instance->public_trim_content_to_max_length( 20, $content ); + + $this->assertSame( 'Thisisaverylongwordw...', $result ); + } + + /** + * Tests trim_content_to_max_length() with space too close to start. + * + * @return void + */ + public function test_trim_content_ignores_space_too_close_to_start() { + $content = 'A longlonglonglongword here'; + + $result = $this->instance->public_trim_content_to_max_length( 15, $content ); + + // Space is at position 1, which is < (15 * 0.9 = 13.5), so it won't be used + $this->assertSame( 'A longlonglongl...', $result ); + } + + /** + * Tests trim_content_to_max_length() with various scenarios. + * + * @param int $max_length The maximum length. + * @param string $content The content to trim. + * @param string $expected The expected result. + * + * @dataProvider trim_content_data_provider + * + * @return void + */ + public function test_trim_content_with_various_scenarios( $max_length, $content, $expected ) { + $result = $this->instance->public_trim_content_to_max_length( $max_length, $content ); + + $this->assertSame( $expected, $result ); + } + + /** + * Data provider for trim_content_to_max_length tests. + * + * @return Generator + */ + public static function trim_content_data_provider() { + yield 'Empty string' => [ + 'max_length' => 50, + 'content' => '', + 'expected' => '', + ]; + yield 'Single word shorter than max' => [ + 'max_length' => 20, + 'content' => 'Hello', + 'expected' => 'Hello', + ]; + yield 'Exact max length' => [ + 'max_length' => 11, + 'content' => 'Hello World', + 'expected' => 'Hello World', + ]; + yield 'One character over max' => [ + 'max_length' => 10, + 'content' => 'Hello World', + 'expected' => 'Hello Worl...', + ]; + yield 'Multiple sentences' => [ + 'max_length' => 35, + 'content' => 'This is sentence one. This is sentence two.', + 'expected' => 'This is sentence one. This is sente...', + ]; + yield 'Negative max length' => [ + 'max_length' => -1, + 'content' => 'Some content', + 'expected' => 'Some content', + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php new file mode 100644 index 00000000000..1610fb56504 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php @@ -0,0 +1,53 @@ +article_enhancer = Mockery::mock( Article_Schema_Enhancer::class ); + $this->person_enhancer = Mockery::mock( Person_Schema_Enhancer::class ); + $this->instance = new Schema_Enhancement_Factory( + $this->article_enhancer, + $this->person_enhancer + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php new file mode 100644 index 00000000000..aef2831ccda --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php @@ -0,0 +1,33 @@ +assertInstanceOf( + Article_Schema_Enhancer::class, + $this->getPropertyValue( $this->instance, 'article_schema_enhancer' ) + ); + $this->assertInstanceOf( + Person_Schema_Enhancer::class, + $this->getPropertyValue( $this->instance, 'person_schema_enhancer' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php new file mode 100644 index 00000000000..42f9573722e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php @@ -0,0 +1,107 @@ +instance->get_enhancer( [ 'Article' ] ); + + $this->assertInstanceOf( Article_Schema_Enhancer::class, $result ); + $this->assertSame( $this->article_enhancer, $result ); + } + + /** + * Tests get_enhancer() returns Person enhancer for Person type. + * + * @return void + */ + public function test_get_enhancer_returns_person_enhancer_for_person_type() { + $result = $this->instance->get_enhancer( [ 'Person' ] ); + + $this->assertInstanceOf( Person_Schema_Enhancer::class, $result ); + $this->assertSame( $this->person_enhancer, $result ); + } + + /** + * Tests get_enhancer() returns null for unknown type. + * + * @return void + */ + public function test_get_enhancer_returns_null_for_unknown_type() { + $result = $this->instance->get_enhancer( [ 'Organization' ] ); + + $this->assertNull( $result ); + } + + /** + * Tests get_enhancer() with multiple types (returns first match). + * + * @param array $schema_types The schema types to test. + * @param string|null $expected_type The expected enhancer type. + * + * @dataProvider get_enhancer_data_provider + * + * @return void + */ + public function test_get_enhancer_with_various_types( $schema_types, $expected_type ) { + $result = $this->instance->get_enhancer( $schema_types ); + + if ( $expected_type === null ) { + $this->assertNull( $result ); + } elseif ( $expected_type === 'Article' ) { + $this->assertInstanceOf( Article_Schema_Enhancer::class, $result ); + } elseif ( $expected_type === 'Person' ) { + $this->assertInstanceOf( Person_Schema_Enhancer::class, $result ); + } + } + + /** + * Data provider for get_enhancer tests. + * + * @return Generator + */ + public static function get_enhancer_data_provider() { + yield 'Article type' => [ + 'schema_types' => [ 'Article' ], + 'expected_type' => 'Article', + ]; + yield 'Person type' => [ + 'schema_types' => [ 'Person' ], + 'expected_type' => 'Person', + ]; + yield 'Unknown type' => [ + 'schema_types' => [ 'WebPage' ], + 'expected_type' => null, + ]; + yield 'Multiple types with Article first' => [ + 'schema_types' => [ 'Article', 'Person' ], + 'expected_type' => 'Article', + ]; + yield 'Multiple types with Person first' => [ + 'schema_types' => [ 'Person', 'Article' ], + 'expected_type' => 'Person', + ]; + yield 'Multiple unknown types' => [ + 'schema_types' => [ 'WebPage', 'Organization' ], + 'expected_type' => null, + ]; + } +} From 87fd9369b08bcaea0d2d1212eec510732469317b Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 09:44:37 +0100 Subject: [PATCH 207/319] Fix bug in Person_Schema_Enhancer jobTitle check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix undefined variable bug where the code was checking $entity['jobTitle'] instead of $schema_data['jobTitle'] on line 64. This caused the isset() check to always fail, resulting in existing jobTitle values being incorrectly overridden. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../application/enhancement/person-schema-enhancer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php index cea231d5f2b..130acbeabb4 100644 --- a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php @@ -59,7 +59,7 @@ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Sch private function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { try { // Add jobTitle if enabled and not already present. - if ( $this->config->is_enhancement_enabled( 'person_job_title' ) && ! isset( $entity['jobTitle'] ) ) { + if ( $this->config->is_enhancement_enabled( 'person_job_title' ) && ! isset( $schema_data['jobTitle'] ) ) { $job_title = $this->get_person_job_title( $indexable->author_id ); if ( $job_title !== null && $job_title !== '' ) { $schema_data['jobTitle'] = $job_title; From c3af9866bc1e1ade2ddb8a05a668efa3ecdaf1d8 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 09:52:46 +0100 Subject: [PATCH 208/319] Refactor: Split Concrete_Schema_Enhancer_For_Testing into separate file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the Concrete_Schema_Enhancer_For_Testing test helper class from Abstract_Abstract_Schema_Enhancer_Test.php into its own file for better organization and reusability. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ...Abstract_Abstract_Schema_Enhancer_Test.php | 19 - .../Concrete_Schema_Enhancer_For_Testing.php | 24 + .../Trim_Content_To_Max_Length_Test.php | 2 - .../Article_Schema_Enhancer_Test.php | 555 ++++++++++++++++++ .../Person_Schema_Enhancer_Test.php | 428 ++++++++++++++ 5 files changed, 1007 insertions(+), 21 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Concrete_Schema_Enhancer_For_Testing.php create mode 100644 tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php create mode 100644 tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php index dbecb8b0c4a..44ab6fd4fc9 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Abstract_Abstract_Schema_Enhancer_Test.php @@ -3,7 +3,6 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Enhancement\Abstract_Schema_Enhancer; -use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Abstract_Schema_Enhancer; use Yoast\WP\SEO\Tests\Unit\TestCase; /** @@ -29,21 +28,3 @@ protected function set_up() { $this->instance = new Concrete_Schema_Enhancer_For_Testing(); } } - -/** - * Concrete implementation of Abstract_Schema_Enhancer for testing protected methods. - */ -class Concrete_Schema_Enhancer_For_Testing extends Abstract_Schema_Enhancer { - - /** - * Exposes the protected trim_content_to_max_length method for testing. - * - * @param int $max_length Maximum length of content. - * @param string $content The content to trim. - * - * @return string The trimmed content. - */ - public function public_trim_content_to_max_length( int $max_length, string $content ): string { - return $this->trim_content_to_max_length( $max_length, $content ); - } -} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Concrete_Schema_Enhancer_For_Testing.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Concrete_Schema_Enhancer_For_Testing.php new file mode 100644 index 00000000000..76b31b705db --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Concrete_Schema_Enhancer_For_Testing.php @@ -0,0 +1,24 @@ +trim_content_to_max_length( $max_length, $content ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php index bbb309fa074..d3706f8b61a 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php @@ -50,7 +50,6 @@ public function test_trim_content_breaks_at_word_boundary() { $result = $this->instance->public_trim_content_to_max_length( 30, $content ); - // The method trims to 30 chars, then looks for space within 90% threshold $this->assertSame( 'This is a long piece of conten...', $result ); } @@ -90,7 +89,6 @@ public function test_trim_content_ignores_space_too_close_to_start() { $result = $this->instance->public_trim_content_to_max_length( 15, $content ); - // Space is at position 1, which is < (15 * 0.9 = 13.5), so it won't be used $this->assertSame( 'A longlonglongl...', $result ); } diff --git a/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php new file mode 100644 index 00000000000..2ef0594f4a9 --- /dev/null +++ b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php @@ -0,0 +1,555 @@ +instance = new Article_Schema_Enhancer(); + $this->config = new Article_Config(); + $this->indexable_post_watcher = \YoastSEO()->classes->get( Indexable_Post_Watcher::class ); + $this->indexable_repository = \YoastSEO()->classes->get( Indexable_Repository::class ); + + $this->instance->set_article_config( $this->config ); + + // Delete all indexables before each test to ensure a clean slate. + global $wpdb; + $table = Model::get_table_name( 'Indexable' ); + $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + } + + /** + * Tests enhance() adds description from excerpt for Article type. + * + * @return void + */ + public function test_enhance_adds_description_from_excerpt_for_article() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'This is a test excerpt for the article.', + 'post_content' => 'This is the full article content.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'description', $enhanced_data[0] ); + $this->assertSame( 'This is a test excerpt for the article.', $enhanced_data[0]['description'] ); + } + + /** + * Gets all indexable records for a post. + * + * @param WP_Post $post The post to get indexables for. + * + * @return Indexable[] The indexables for the post. + */ + private function get_indexables_for( $post ) { + $orm = Model::of_type( 'Indexable' ); + + return $orm + ->where( 'object_id', $post->ID ) + ->where( 'object_type', 'post' ) + ->where( 'object_sub_type', $post->post_type ) + ->find_many(); + } + + /** + * Tests enhance() adds both description and articleBody when filter is enabled. + * + * @return void + */ + public function test_enhance_adds_article_body_when_no_excerpt() { + // Enable articleBody even when excerpt exists. + \add_filter( 'wpseo_article_enhance_body_when_excerpt_exists', '__return_true' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'Test excerpt', + 'post_content' => 'This is the full article content that should appear as articleBody.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'description', $enhanced_data[0] ); + $this->assertArrayHasKey( 'articleBody', $enhanced_data[0] ); + $this->assertSame( 'This is the full article content that should appear as articleBody.', $enhanced_data[0]['articleBody'] ); + + // Clean up filter. + \remove_filter( 'wpseo_article_enhance_body_when_excerpt_exists', '__return_true' ); + } + + /** + * Tests enhance() adds keywords from tags. + * + * @return void + */ + public function test_enhance_adds_keywords_from_tags() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + ] + ); + + // Create and assign tags. + $tag1 = $this->factory()->tag->create( [ 'name' => 'SEO' ] ); + $tag2 = $this->factory()->tag->create( [ 'name' => 'WordPress' ] ); + \wp_set_post_tags( $post->ID, [ $tag1, $tag2 ] ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'keywords', $enhanced_data[0] ); + $this->assertSame( 'SEO, WordPress', $enhanced_data[0]['keywords'] ); + } + + /** + * Tests enhance() adds keywords from categories when filter is enabled. + * + * @return void + */ + public function test_enhance_adds_keywords_from_categories_when_enabled() { + // Enable categories as keywords. + \add_filter( 'wpseo_article_enhance_config_categories_as_keywords', '__return_true' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + ] + ); + + // Create and assign category. + $category = $this->factory()->category->create( [ 'name' => 'Technology' ] ); + \wp_set_post_categories( $post->ID, [ $category ] ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'keywords', $enhanced_data[0] ); + $this->assertStringContainsString( 'Technology', $enhanced_data[0]['keywords'] ); + + // Clean up filter. + \remove_filter( 'wpseo_article_enhance_config_categories_as_keywords', '__return_true' ); + } + + /** + * Tests enhance() works with NewsArticle type. + * + * @return void + */ + public function test_enhance_works_with_news_article_type() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test News Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'Breaking news excerpt.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'NewsArticle', + 'name' => 'Test News Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'description', $enhanced_data[0] ); + $this->assertSame( 'Breaking news excerpt.', $enhanced_data[0]['description'] ); + } + + /** + * Tests enhance() works with BlogPosting type. + * + * @return void + */ + public function test_enhance_works_with_blog_posting_type() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Blog Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'Blog post excerpt.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'BlogPosting', + 'name' => 'Test Blog Post', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'description', $enhanced_data[0] ); + $this->assertSame( 'Blog post excerpt.', $enhanced_data[0]['description'] ); + } + + /** + * Tests enhance() works with Article in array of types. + * + * @return void + */ + public function test_enhance_works_with_article_in_type_array() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'Article with multiple types.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => [ 'Article', 'WebPage' ], + 'name' => 'Test Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'description', $enhanced_data[0] ); + $this->assertSame( 'Article with multiple types.', $enhanced_data[0]['description'] ); + } + + /** + * Tests enhance() does not override existing description. + * + * @return void + */ + public function test_enhance_does_not_override_existing_description() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'This should not be used.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + 'description' => 'Existing description', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertSame( 'Existing description', $enhanced_data[0]['description'] ); + } + + /** + * Tests enhance() does not override existing articleBody. + * + * @return void + */ + public function test_enhance_does_not_override_existing_article_body() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_content' => 'This should not be used.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + 'articleBody' => 'Existing article body', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertSame( 'Existing article body', $enhanced_data[0]['articleBody'] ); + } + + /** + * Tests enhance() does not override existing keywords. + * + * @return void + */ + public function test_enhance_does_not_override_existing_keywords() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + ] + ); + + // Create and assign tags. + $tag = $this->factory()->tag->create( [ 'name' => 'SEO' ] ); + \wp_set_post_tags( $post->ID, [ $tag ] ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + 'keywords' => 'Existing, Keywords', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertSame( 'Existing, Keywords', $enhanced_data[0]['keywords'] ); + } + + /** + * Tests enhance() returns unchanged schema when no enhancements possible. + * + * @return void + */ + public function test_enhance_returns_unchanged_when_no_enhancements_possible() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'WebPage', + 'name' => 'Test Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertSame( $schema_data, $enhanced_data ); + } + + /** + * Tests enhance() with disabled enhancements. + * + * @return void + */ + public function test_enhance_respects_disabled_enhancements() { + // Disable all enhancements. + \add_filter( 'wpseo_article_enhance_use_excerpt', '__return_false' ); + \add_filter( 'wpseo_article_enhance_article_body', '__return_false' ); + \add_filter( 'wpseo_article_enhance_keywords', '__return_false' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'This should not be added.', + 'post_content' => 'This should not be added.', + ] + ); + + // Create and assign tags. + $tag = $this->factory()->tag->create( [ 'name' => 'SEO' ] ); + \wp_set_post_tags( $post->ID, [ $tag ] ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'articleBody', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); + + // Clean up filters. + \remove_filter( 'wpseo_article_enhance_use_excerpt', '__return_false' ); + \remove_filter( 'wpseo_article_enhance_article_body', '__return_false' ); + \remove_filter( 'wpseo_article_enhance_keywords', '__return_false' ); + } + + /** + * Tests enhance() with multiple schema pieces. + * + * @return void + */ + public function test_enhance_processes_multiple_schema_pieces() { + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Article', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_excerpt' => 'Test excerpt.', + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Article', + 'name' => 'Test Article 1', + ], + [ + '@type' => 'WebPage', + 'name' => 'Test Page', + ], + [ + '@type' => 'NewsArticle', + 'name' => 'Test Article 2', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'description', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'description', $enhanced_data[1] ); + $this->assertArrayHasKey( 'description', $enhanced_data[2] ); + } +} diff --git a/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php b/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php new file mode 100644 index 00000000000..8208204b58b --- /dev/null +++ b/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php @@ -0,0 +1,428 @@ +instance = new Person_Schema_Enhancer(); + $this->config = new Person_Config(); + $this->indexable_post_watcher = \YoastSEO()->classes->get( Indexable_Post_Watcher::class ); + $this->indexable_repository = \YoastSEO()->classes->get( Indexable_Repository::class ); + + $this->instance->set_person_config( $this->config ); + + // Delete all indexables before each test to ensure a clean slate. + global $wpdb; + $table = Model::get_table_name( 'Indexable' ); + $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + } + + /** + * Tests enhance() adds jobTitle from user meta for Person type. + * + * @return void + */ + public function test_enhance_adds_job_title_from_user_meta() { + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Person', + 'name' => 'Test Author', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'author' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'jobTitle', $enhanced_data[0] ); + $this->assertSame( 'Senior Developer', $enhanced_data[0]['jobTitle'] ); + } + + /** + * Tests enhance() does not override existing jobTitle. + * + * @return void + */ + public function test_enhance_does_not_override_existing_job_title() { + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Person', + 'name' => 'Test Author', + 'jobTitle' => 'Existing Job Title', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'author' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertSame( 'Existing Job Title', $enhanced_data[0]['jobTitle'] ); + } + + /** + * Tests enhance() does not add jobTitle when user meta is empty. + * + * @return void + */ + public function test_enhance_does_not_add_job_title_when_empty() { + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + // Set empty job title. + \update_user_meta( $user_id, 'job_title', '' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Person', + 'name' => 'Test Author', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'author' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + } + + /** + * Tests enhance() does not add jobTitle when user meta does not exist. + * + * @return void + */ + public function test_enhance_does_not_add_job_title_when_meta_not_exists() { + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Person', + 'name' => 'Test Author', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'author' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + } + + /** + * Tests enhance() trims whitespace from job title. + * + * @return void + */ + public function test_enhance_trims_whitespace_from_job_title() { + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + \update_user_meta( $user_id, 'job_title', ' Senior Developer ' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Person', + 'name' => 'Test Author', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'author' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'jobTitle', $enhanced_data[0] ); + $this->assertSame( 'Senior Developer', $enhanced_data[0]['jobTitle'] ); + } + + /** + * Tests enhance() ignores non-Person types. + * + * @return void + */ + public function test_enhance_ignores_non_person_types() { + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Organization', + 'name' => 'Test Org', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'publisher' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + } + + /** + * Tests enhance() with disabled enhancement. + * + * @return void + */ + public function test_enhance_respects_disabled_enhancement() { + // Disable person_job_title enhancement. + \add_filter( 'wpseo_person_enhance_person_job_title', '__return_false' ); + + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Person', + 'name' => 'Test Author', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'author' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + + // Clean up filter. + \remove_filter( 'wpseo_person_enhance_person_job_title', '__return_false' ); + } + + /** + * Tests enhance() processes multiple schema pieces. + * + * @return void + */ + public function test_enhance_processes_multiple_schema_pieces() { + $user_id = $this->factory()->user->create( + [ + 'user_login' => 'testauthor', + 'role' => 'author', + ] + ); + + \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); + + $post = $this->factory()->post->create_and_get( + [ + 'post_title' => 'Test Post', + 'post_type' => 'post', + 'post_status' => 'publish', + 'post_author' => $user_id, + ] + ); + + $indexable = \current( $this->get_indexables_for( $post ) ); + + $schema_data = [ + [ + '@type' => 'Person', + 'name' => 'Test Author 1', + ], + [ + '@type' => 'Organization', + 'name' => 'Test Org', + ], + [ + '@type' => 'Person', + 'name' => 'Test Author 2', + ], + ]; + $schema_piece = new Schema_Piece( $schema_data, 'author' ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayHasKey( 'jobTitle', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[1] ); + $this->assertArrayHasKey( 'jobTitle', $enhanced_data[2] ); + } + + /** + * Gets all indexable records for a post. + * + * @param WP_Post $post The post to get indexables for. + * + * @return Indexable[] The indexables for the post. + */ + private function get_indexables_for( $post ) { + $orm = Model::of_type( 'Indexable' ); + + return $orm + ->where( 'object_id', $post->ID ) + ->where( 'object_type', 'post' ) + ->where( 'object_sub_type', $post->post_type ) + ->find_many(); + } +} From f67b94d913328d51b76c16fd7ae1703209465796 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 8 Dec 2025 09:53:10 +0100 Subject: [PATCH 209/319] Fix code style in Get_Enhancer_Test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply code formatting standards to Get_Enhancer_Test.php including proper spacing and brace alignment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Schema_Enhancement_Factory/Get_Enhancer_Test.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php index 42f9573722e..c9d94e3542c 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Get_Enhancer_Test.php @@ -54,7 +54,7 @@ public function test_get_enhancer_returns_null_for_unknown_type() { /** * Tests get_enhancer() with multiple types (returns first match). * - * @param array $schema_types The schema types to test. + * @param array $schema_types The schema types to test. * @param string|null $expected_type The expected enhancer type. * * @dataProvider get_enhancer_data_provider @@ -66,9 +66,11 @@ public function test_get_enhancer_with_various_types( $schema_types, $expected_t if ( $expected_type === null ) { $this->assertNull( $result ); - } elseif ( $expected_type === 'Article' ) { + } + elseif ( $expected_type === 'Article' ) { $this->assertInstanceOf( Article_Schema_Enhancer::class, $result ); - } elseif ( $expected_type === 'Person' ) { + } + elseif ( $expected_type === 'Person' ) { $this->assertInstanceOf( Person_Schema_Enhancer::class, $result ); } } From 413ec4c1f3e1a620ddcdb20bcff52e4adb51cef1 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 24 Dec 2025 16:41:21 +0100 Subject: [PATCH 210/319] Add more unit tests --- .../Trim_Content_To_Max_Length_Test.php | 1 + .../Abstract_Article_Schema_Enhancer_Test.php | 35 + .../Article_Schema_Enhancer_Test.php | 864 ++++++++++++++++++ .../Enhance_Schema_Piece_Test.php | 586 ++++++++++++ .../Set_Article_Config_Test.php | 58 ++ 5 files changed, 1544 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Abstract_Article_Schema_Enhancer_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php index d3706f8b61a..c6c59079551 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php @@ -1,3 +1,4 @@ + instance = new Article_Schema_Enhancer(); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php new file mode 100644 index 00000000000..e3883556fb5 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php @@ -0,0 +1,864 @@ +instance = new Article_Schema_Enhancer(); + $this->config = Mockery::mock( Article_Config::class ); + $this->instance->set_article_config( $this->config ); + } + + /** + * Tests exception handling in enhance_schema_piece method. + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * + * @return void + */ + public function test_enhance_schema_piece_handles_exception() { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_data = [ + [ + '@type' => 'Article', + ], + ]; + + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andThrow( new Exception( 'Test exception' ) ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertSame( $schema_data[0], $enhanced_data[0] ); + } + + /** + * Tests exception handling in get_article_keywords method. + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_article_keywords + * + * @return void + */ + public function test_get_article_keywords_handles_exception() { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_data = [ + [ + '@type' => 'Article', + ], + ]; + + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + Functions\expect( 'get_the_tags' ) + ->with( 123 ) + ->andThrow( new Exception( 'Test exception' ) ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( true ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); + } + + /** + * Tests exception handling in get_excerpt method. + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_excerpt + * + * @return void + */ + public function test_get_excerpt_handles_exception() { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_data = [ + [ + '@type' => 'Article', + ], + ]; + + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', 123 ) + ->andThrow( new Exception( 'Test exception' ) ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( true ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( false ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); + } + + /** + * Tests exception handling in get_article_body method. + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_article_body + * + * @return void + */ + public function test_get_article_body_handles_exception() { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_data = [ + [ + '@type' => 'Article', + ], + ]; + + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + Functions\expect( 'get_post_field' ) + ->with( 'post_content', 123 ) + ->andThrow( new Exception( 'Test exception' ) ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( true ); + + $this->config + ->expects( 'should_include_article_body' ) + ->with( false ) + ->andReturn( true ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( false ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertArrayNotHasKey( 'articleBody', $enhanced_data[0] ); + } + + /** + * Tests enhance() with all enhancements enabled at once. + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_excerpt + * @covers ::get_article_body + * @covers ::get_article_keywords + * + * @return void + */ + public function test_enhance_with_all_enhancements_enabled() { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_data = [ + [ + '@type' => 'Article', + ], + ]; + + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + // Setup excerpt + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', 123 ) + ->andReturn( 'This is an excerpt' ); + + Functions\expect( 'wp_strip_all_tags' ) + ->with( 'This is an excerpt' ) + ->andReturn( 'This is an excerpt' ); + + // Setup article body + Functions\expect( 'get_post_field' ) + ->with( 'post_content', 123 ) + ->andReturn( 'This is the full article content' ); + + Functions\expect( 'strip_shortcodes' ) + ->with( 'This is the full article content' ) + ->andReturn( 'This is the full article content' ); + + Functions\expect( 'wp_strip_all_tags' ) + ->with( 'This is the full article content' ) + ->andReturn( 'This is the full article content' ); + + // Setup keywords + $tag1 = (object) [ 'name' => 'tag1' ]; + $tags_array = [ $tag1 ]; + + Functions\expect( 'get_the_tags' ) + ->with( 123 ) + ->andReturn( $tags_array ); + + // Config expectations + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( true ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'excerpt_max_length', 0 ) + ->andReturn( 0 ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( true ); + + $this->config + ->expects( 'should_include_article_body' ) + ->with( true ) + ->andReturn( true ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'strip_shortcodes_from_body', true ) + ->andReturn( true ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'strip_html_from_body', true ) + ->andReturn( true ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) + ->andReturn( 500 ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( true ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'categories_as_keywords', false ) + ->andReturn( false ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + + $enhanced_data = $result->get_data(); + $this->assertSame( 'This is an excerpt', $enhanced_data[0]['description'] ); + $this->assertSame( 'This is the full article content', $enhanced_data[0]['articleBody'] ); + $this->assertSame( 'tag1', $enhanced_data[0]['keywords'] ); + } + + /** + * Data provider for enhance_schema_piece testing. + * + * @return array> + */ + public function data_provider_for_enhance_schema_piece() { + return [ + 'excerpt_enhancement_disabled' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => false, + 'keywords' => false, + ], + 'schema_data' => [ '@type' => 'Article' ], + 'expected_fields' => [], + 'excerpt_data' => null, + 'body_data' => null, + 'keywords_data' => null, + ], + 'excerpt_enhancement_enabled_with_valid_excerpt' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => false, + 'keywords' => false, + ], + 'schema_data' => [ '@type' => 'Article' ], + 'expected_fields' => [ 'description' => 'Valid excerpt text' ], + 'excerpt_data' => [ + 'post_excerpt' => 'Valid excerpt text', + 'excerpt_max_length' => 0, + ], + 'body_data' => null, + 'keywords_data' => null, + ], + 'excerpt_enhancement_with_existing_description' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => false, + 'keywords' => false, + ], + 'schema_data' => [ '@type' => 'Article', 'description' => 'Existing description' ], + 'expected_fields' => [ 'description' => 'Existing description' ], + 'excerpt_data' => [ + 'post_excerpt' => 'Valid excerpt text', + 'excerpt_max_length' => 0, + ], + 'body_data' => null, + 'keywords_data' => null, + ], + 'article_body_enhancement_enabled' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => true, + 'keywords' => false, + ], + 'schema_data' => [ '@type' => 'Article' ], + 'expected_fields' => [ 'articleBody' => 'Article content' ], + 'excerpt_data' => null, + 'body_data' => [ + 'post_content' => 'Article content', + 'should_include' => true, + 'strip_shortcodes' => true, + 'strip_html' => true, + 'max_length' => 500, + ], + 'keywords_data' => null, + ], + 'article_body_with_existing_body' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => true, + 'keywords' => false, + ], + 'schema_data' => [ '@type' => 'Article', 'articleBody' => 'Existing body' ], + 'expected_fields' => [ 'articleBody' => 'Existing body' ], + 'excerpt_data' => null, + 'body_data' => [ + 'post_content' => 'Article content', + 'should_include' => true, + 'strip_shortcodes' => true, + 'strip_html' => true, + 'max_length' => 500, + ], + 'keywords_data' => null, + ], + 'keywords_enhancement_enabled' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => false, + 'keywords' => true, + ], + 'schema_data' => [ '@type' => 'Article' ], + 'expected_fields' => [ 'keywords' => 'tag1, tag2' ], + 'excerpt_data' => null, + 'body_data' => null, + 'keywords_data' => [ + 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], + 'categories_as_keywords' => false, + ], + ], + 'keywords_with_existing_keywords' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => false, + 'keywords' => true, + ], + 'schema_data' => [ '@type' => 'Article', 'keywords' => 'existing, keywords' ], + 'expected_fields' => [ 'keywords' => 'existing, keywords' ], + 'excerpt_data' => null, + 'body_data' => null, + 'keywords_data' => [ + 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], + 'categories_as_keywords' => false, + ], + ], + 'all_enhancements_enabled' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => true, + 'keywords' => true, + ], + 'schema_data' => [ '@type' => 'Article' ], + 'expected_fields' => [ + 'description' => 'Test excerpt', + 'articleBody' => 'Test content', + 'keywords' => 'test-tag', + ], + 'excerpt_data' => [ + 'post_excerpt' => 'Test excerpt', + 'excerpt_max_length' => 0, + ], + 'body_data' => [ + 'post_content' => 'Test content', + 'should_include' => true, + 'strip_shortcodes' => true, + 'strip_html' => true, + 'max_length' => 500, + ], + 'keywords_data' => [ + 'tags' => [ (object) [ 'name' => 'test-tag' ] ], + 'categories_as_keywords' => false, + ], + ], + ]; + } + + /** + * Tests enhance_schema_piece method with various configurations. + * + * @dataProvider data_provider_for_enhance_schema_piece + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_excerpt + * @covers ::get_article_body + * @covers ::get_article_keywords + * + * @param array $config Configuration for enhancements. + * @param array $schema_data Input schema data. + * @param array $expected_fields Expected output fields. + * @param array|null $excerpt_data Excerpt mock data. + * @param array|null $body_data Body mock data. + * @param array|null $keywords_data Keywords mock data. + * + * @return void + */ + public function test_enhance_schema_piece_with_different_configurations( $config, $schema_data, $expected_fields, $excerpt_data, $body_data, $keywords_data ) { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_piece = new Schema_Piece( [ $schema_data ], 'Article' ); + + // Setup config mocks + foreach ( $config as $enhancement => $enabled ) { + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( $enhancement ) + ->andReturn( $enabled ); + } + + // Setup excerpt mocks + if ( $excerpt_data !== null && $config['use_excerpt'] ) { + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', 123 ) + ->andReturn( $excerpt_data['post_excerpt'] ); + + Functions\expect( 'wp_strip_all_tags' ) + ->with( $excerpt_data['post_excerpt'] ) + ->andReturn( $excerpt_data['post_excerpt'] ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'excerpt_max_length', 0 ) + ->andReturn( $excerpt_data['excerpt_max_length'] ); + } + + // Setup body mocks + if ( $body_data !== null && $config['article_body'] ) { + $has_excerpt = $excerpt_data !== null && $config['use_excerpt'] && ! isset( $schema_data['description'] ); + + $this->config + ->expects( 'should_include_article_body' ) + ->with( $has_excerpt ) + ->andReturn( $body_data['should_include'] ); + + if ( $body_data['should_include'] && ! isset( $schema_data['articleBody'] ) ) { + Functions\expect( 'get_post_field' ) + ->with( 'post_content', 123 ) + ->andReturn( $body_data['post_content'] ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'strip_shortcodes_from_body', true ) + ->andReturn( $body_data['strip_shortcodes'] ); + + if ( $body_data['strip_shortcodes'] ) { + Functions\expect( 'strip_shortcodes' ) + ->with( $body_data['post_content'] ) + ->andReturn( $body_data['post_content'] ); + } + + $this->config + ->expects( 'get_config_value' ) + ->with( 'strip_html_from_body', true ) + ->andReturn( $body_data['strip_html'] ); + + if ( $body_data['strip_html'] ) { + Functions\expect( 'wp_strip_all_tags' ) + ->with( $body_data['post_content'] ) + ->andReturn( $body_data['post_content'] ); + } + + $this->config + ->expects( 'get_config_value' ) + ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) + ->andReturn( $body_data['max_length'] ); + } + } + + // Setup keywords mocks + if ( $keywords_data !== null && $config['keywords'] && ! isset( $schema_data['keywords'] ) ) { + Functions\expect( 'get_the_tags' ) + ->with( 123 ) + ->andReturn( $keywords_data['tags'] ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'categories_as_keywords', false ) + ->andReturn( $keywords_data['categories_as_keywords'] ); + } + + $result = $this->instance->enhance( $schema_piece, $indexable ); + $enhanced_data = $result->get_data(); + + foreach ( $expected_fields as $field => $expected_value ) { + $this->assertSame( $expected_value, $enhanced_data[0][$field] ); + } + + // Ensure fields that shouldn't be added are not present + $all_possible_fields = [ 'description', 'articleBody', 'keywords' ]; + foreach ( $all_possible_fields as $field ) { + if ( ! isset( $expected_fields[$field] ) && ! isset( $schema_data[$field] ) ) { + $this->assertArrayNotHasKey( $field, $enhanced_data[0] ); + } + } + } + + /** + * Data provider for testing edge cases and error conditions. + * + * @return array> + */ + public function data_provider_for_edge_cases() { + return [ + 'empty_excerpt' => [ + 'post_excerpt' => '', + 'excerpt_prefer_manual' => false, + 'post_content' => 'Some content', + 'expected_result' => 'Some content', + ], + 'whitespace_only_excerpt' => [ + 'post_excerpt' => ' ', + 'excerpt_prefer_manual' => false, + 'post_content' => 'Some content', + 'expected_result' => 'Some content', + ], + 'empty_excerpt_prefer_manual' => [ + 'post_excerpt' => '', + 'excerpt_prefer_manual' => true, + 'post_content' => 'Some content', + 'expected_result' => null, + ], + 'wp_error_excerpt' => [ + 'post_excerpt' => new WP_Error( 'error', 'Error message' ), + 'excerpt_prefer_manual' => false, + 'post_content' => 'Some content', + 'expected_result' => 'Some content', + ], + 'wp_error_content' => [ + 'post_excerpt' => '', + 'excerpt_prefer_manual' => false, + 'post_content' => new WP_Error( 'error', 'Error message' ), + 'expected_result' => null, + ], + 'empty_content' => [ + 'post_excerpt' => '', + 'excerpt_prefer_manual' => false, + 'post_content' => '', + 'expected_result' => null, + ], + 'tags_null' => [ + 'tags' => null, + 'categories_as_keywords' => false, + 'expected_keywords' => [], + ], + 'tags_false' => [ + 'tags' => false, + 'categories_as_keywords' => false, + 'expected_keywords' => [], + ], + 'tags_without_name_property' => [ + 'tags' => [ (object) [ 'slug' => 'tag1' ] ], + 'categories_as_keywords' => false, + 'expected_keywords' => [], + ], + 'categories_with_uncategorized' => [ + 'tags' => [], + 'categories_as_keywords' => true, + 'categories' => [ + (object) [ 'name' => 'Category1' ], + (object) [ 'name' => 'Uncategorized' ], + (object) [ 'name' => 'Category2' ], + ], + 'expected_keywords' => [ 'Category1', 'Category2' ], + ], + ]; + } + + /** + * Tests get_excerpt method with edge cases. + * + * @dataProvider data_provider_for_edge_cases + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_excerpt + * + * @param mixed $post_excerpt Post excerpt value. + * @param bool $excerpt_prefer_manual Whether to prefer manual excerpts. + * @param mixed $post_content Post content value. + * @param string|null $expected_result Expected result. + * + * @return void + */ + public function test_get_excerpt_edge_cases( $post_excerpt, $excerpt_prefer_manual, $post_content, $expected_result ) { + if ( ! \in_array( 'expected_result', \array_keys( \func_get_args() ), true ) ) { + $this->markTestSkipped( 'This test case is for keywords, not excerpt' ); + } + + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_data = [ [ '@type' => 'Article' ] ]; + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( true ); + + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', 123 ) + ->andReturn( $post_excerpt ); + + if ( ! \is_wp_error( $post_excerpt ) ) { + $this->config + ->expects( 'get_config_value' ) + ->with( 'excerpt_prefer_manual', false ) + ->andReturn( $excerpt_prefer_manual ); + + if ( ( empty( $post_excerpt ) || \trim( $post_excerpt ) === '' ) && ! $excerpt_prefer_manual ) { + Functions\expect( 'get_post_field' ) + ->with( 'post_content', 123 ) + ->andReturn( $post_content ); + + if ( ! \is_wp_error( $post_content ) && ! empty( $post_content ) ) { + Functions\expect( 'wp_trim_excerpt' ) + ->with( $post_content, 123 ) + ->andReturn( $expected_result ); + } + } + + if ( $expected_result !== null ) { + Functions\expect( 'wp_strip_all_tags' ) + ->with( $expected_result ) + ->andReturn( $expected_result ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'excerpt_max_length', 0 ) + ->andReturn( 0 ); + } + } + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( false ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + $enhanced_data = $result->get_data(); + + if ( $expected_result !== null ) { + $this->assertSame( $expected_result, $enhanced_data[0]['description'] ); + } else { + $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); + } + } + + /** + * Tests get_article_keywords method with edge cases. + * + * @dataProvider data_provider_for_edge_cases + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_article_keywords + * + * @param mixed $tags Tags data. + * @param bool $categories_as_keywords Whether to include categories. + * @param array|null $categories Categories data. + * @param array $expected_keywords Expected keywords. + * + * @return void + */ + public function test_get_article_keywords_edge_cases( $tags = null, $categories_as_keywords = false, $categories = null, $expected_keywords = [] ) { + if ( ! \in_array( 'expected_keywords', \array_keys( \func_get_args() ), true ) ) { + $this->markTestSkipped( 'This test case is for excerpt, not keywords' ); + } + + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_data = [ [ '@type' => 'Article' ] ]; + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( true ); + + Functions\expect( 'get_the_tags' ) + ->with( 123 ) + ->andReturn( $tags ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'categories_as_keywords', false ) + ->andReturn( $categories_as_keywords ); + + if ( $categories_as_keywords && $categories !== null ) { + Functions\expect( 'get_the_category' ) + ->with( 123 ) + ->andReturn( $categories ); + } + + $result = $this->instance->enhance( $schema_piece, $indexable ); + $enhanced_data = $result->get_data(); + + if ( ! empty( $expected_keywords ) ) { + $this->assertSame( \implode( ', ', $expected_keywords ), $enhanced_data[0]['keywords'] ); + } else { + $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); + } + } + + /** + * Tests enhance_schema_piece with null and invalid indexable object_id. + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * + * @return void + */ + public function test_enhance_schema_piece_with_invalid_object_id() { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = null; + + $schema_data = [ [ '@type' => 'Article' ] ]; + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( true ); + + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', null ) + ->andReturn( null ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( false ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + $enhanced_data = $result->get_data(); + + $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'articleBody', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php new file mode 100644 index 00000000000..16a739573dd --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php @@ -0,0 +1,586 @@ +config = Mockery::mock( Article_Config::class ); + $this->instance->set_article_config( $this->config ); + } + + public function test_enhance_schema_piece_trigger_exception() { + $indexable = new Indexable_Mock(); + $indexable->object_id = 123123123; + $schema_data = [ + '@type' => 'Article', + '@context' => 'https://schema.org', + 'headline' => 'How to Optimize Your WordPress Site for SEO', + 'author' => [ + '@type' => 'Person', + 'name' => 'John Doe' + ], + 'datePublished' => '2024-01-15T10:30:00+00:00', + 'dateModified' => '2024-01-16T14:20:00+00:00', + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'My WordPress Blog', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://example.com/logo.png' + ] + ], + 'mainEntityOfPage' => [ + '@type' => 'WebPage', + '@id' => 'https://example.com/seo-optimization-guide' + ] + ]; + + $schema_piece = new Schema_Piece($schema_data, 'Article'); + + Functions\expect('get_post_field') + ->once() + ->with('post_excerpt', $indexable->object_id) + ->andThrow(new \Exception('Test exception')); + + $this->config->shouldReceive('is_enhancement_enabled') + ->with('use_excerpt') + ->andReturn(true); + + $result = $this->instance->enhance($schema_piece, $indexable); + + $this->assertEquals($schema_data, $result->get_data()); + } + /** + * Provides data for schema type validation tests. + * + * @return Generator + */ + public static function schema_type_provider(): Generator { + yield 'Article type' => [ + 'schema_data' => [ + [ + '@type' => 'Article', + ], + ], + 'schema_type' => 'Article', + 'should_enhance' => true, + 'expected_type' => 'Article', + 'expected_data_unchanged' => false, + ]; + + yield 'NewsArticle type' => [ + 'schema_data' => [ + [ + '@type' => 'NewsArticle', + ], + ], + 'schema_type' => 'NewsArticle', + 'should_enhance' => true, + 'expected_type' => 'NewsArticle', + 'expected_data_unchanged' => false, + ]; + + yield 'BlogPosting type' => [ + 'schema_data' => [ + [ + '@type' => 'BlogPosting', + ], + ], + 'schema_type' => 'BlogPosting', + 'should_enhance' => true, + 'expected_type' => 'BlogPosting', + 'expected_data_unchanged' => false, + ]; + + yield 'Array type containing Article' => [ + 'schema_data' => [ + [ + '@type' => [ 'Article', 'WebPage' ], + ], + ], + 'schema_type' => 'Article', + 'should_enhance' => true, + 'expected_type' => 'Article', + 'expected_data_unchanged' => false, + ]; + + yield 'Non-article type (WebPage)' => [ + 'schema_data' => [ + [ + '@type' => 'WebPage', + ], + ], + 'schema_type' => 'WebPage', + 'should_enhance' => false, + 'expected_type' => 'WebPage', + 'expected_data_unchanged' => true, + ]; + + yield 'Missing @type' => [ + 'schema_data' => [ + [ + 'name' => 'Some content', + ], + ], + 'schema_type' => 'Unknown', + 'should_enhance' => false, + 'expected_type' => 'Unknown', + 'expected_data_unchanged' => true, + ]; + } + + /** + * Data provider for enhance_schema_piece edge cases and error conditions. + * + * @return Generator + */ + public static function enhance_schema_piece_data_provider(): Generator { + yield 'all_enhancements_disabled' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => false, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => 123, + 'expected_fields' => [], + ]; + + yield 'excerpt_enhancement_enabled_with_valid_excerpt' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => false, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => 123, + 'expected_fields' => [ + 'description' => 'Valid excerpt text', + ], + ]; + + yield 'excerpt_with_existing_description_should_not_override' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => false, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + 'description' => 'Existing description', + ], + 'post_id' => 123, + 'expected_fields' => [ + 'description' => 'Existing description', + ], + ]; + + yield 'article_body_enhancement_enabled' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => true, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => 123, + 'expected_fields' => [ + 'articleBody' => 'Article content without HTML', + ], + ]; + + yield 'article_body_with_existing_body_should_not_override' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => true, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + 'articleBody' => 'Existing body', + ], + 'post_id' => 123, + 'expected_fields' => [ + 'articleBody' => 'Existing body', + ], + ]; + + yield 'keywords_enhancement_enabled_with_tags' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => false, + 'keywords' => true, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => 123, + 'expected_fields' => [ + 'keywords' => 'tag1, tag2', + ], + ]; + + yield 'keywords_with_existing_keywords_should_not_override' => [ + 'config' => [ + 'use_excerpt' => false, + 'article_body' => false, + 'keywords' => true, + ], + 'schema_data' => [ + '@type' => 'Article', + 'keywords' => 'existing, keywords', + ], + 'post_id' => 123, + 'expected_fields' => [ + 'keywords' => 'existing, keywords', + ], + ]; + + yield 'all_enhancements_enabled_with_no_existing_fields' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => true, + 'keywords' => true, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => 123, + 'expected_fields' => [ + 'description' => 'Test excerpt', + 'articleBody' => 'Test content', + 'keywords' => 'test-tag', + ], + ]; + + yield 'invalid_post_id_null' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => true, + 'keywords' => true, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => null, + 'expected_fields' => [], + ]; + + yield 'invalid_post_id_zero' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => true, + 'keywords' => true, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => 0, + 'expected_fields' => [], + ]; + + yield 'empty_excerpt_with_manual_preference' => [ + 'config' => [ + 'use_excerpt' => true, + 'article_body' => false, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + ], + 'post_id' => 123, + 'expected_fields' => [], + ]; + } + + /** + * Tests enhance_schema_piece method with various configurations using data provider. + * + * @dataProvider enhance_schema_piece_data_provider + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_excerpt + * @covers ::get_article_body + * @covers ::get_article_keywords + * + * @param array $config Configuration for enhancements. + * @param array $schema_data Input schema data. + * @param int|null $post_id Post ID for testing. + * @param array $expected_fields Expected output fields. + * + * @return void + */ + public function test_enhance_schema_piece_with_different_configurations( $config, $schema_data, $post_id, $expected_fields ) { + $indexable = new Indexable_Mock(); + $indexable->object_id = $post_id; + + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + // Setup configuration mocks + foreach ( $config as $enhancement => $enabled ) { + $this->config->shouldReceive( 'is_enhancement_enabled' ) + ->with( $enhancement ) + ->andReturn( $enabled ); + } + + // Setup WordPress function mocks based on test case + $this->setup_wordpress_mocks_for_test_case( $config, $expected_fields, $post_id ); + + $result = $this->instance->enhance( $schema_piece, $indexable ); + $enhanced_data = $result->get_data(); + + // Assert expected fields are present with correct values + foreach ( $expected_fields as $field => $expected_value ) { + $this->assertSame( $expected_value, $enhanced_data[$field], "Field {$field} should match expected value" ); + } + + // Assert fields that shouldn't be added are not present + $all_possible_fields = [ 'description', 'articleBody', 'keywords' ]; + foreach ( $all_possible_fields as $field ) { + if ( ! isset( $expected_fields[$field] ) && ! isset( $schema_data[$field] ) ) { + $this->assertArrayNotHasKey( $field, $enhanced_data, "Field {$field} should not be present" ); + } + } + } + + /** + * Data provider for testing error conditions. + * + * @return Generator + */ + public static function error_conditions_data_provider(): Generator { + yield 'excerpt_wp_error' => [ + 'enhancement' => 'use_excerpt', + 'post_id' => 123, + 'mock_function' => 'get_post_field', + 'mock_params' => [ 'post_excerpt', 123 ], + 'mock_exception' => new \Exception( 'Database error' ), + 'expected_field_absent' => 'description', + ]; + + yield 'article_body_wp_error' => [ + 'enhancement' => 'article_body', + 'post_id' => 456, + 'mock_function' => 'get_post_field', + 'mock_params' => [ 'post_content', 456 ], + 'mock_exception' => new \Exception( 'Content fetch error' ), + 'expected_field_absent' => 'articleBody', + ]; + + yield 'keywords_wp_error' => [ + 'enhancement' => 'keywords', + 'post_id' => 789, + 'mock_function' => 'get_the_tags', + 'mock_params' => [ 789 ], + 'mock_exception' => new \Exception( 'Tags fetch error' ), + 'expected_field_absent' => 'keywords', + ]; + } + + /** + * Tests error handling in enhance_schema_piece method. + * + * @dataProvider error_conditions_data_provider + * + * @covers ::enhance + * @covers ::enhance_schema_piece + * @covers ::get_excerpt + * @covers ::get_article_body + * @covers ::get_article_keywords + * + * @param string $enhancement Enhancement to test. + * @param int $post_id Post ID for testing. + * @param string $mock_function Function to mock. + * @param array $mock_params Parameters for the mock function. + * @param \Exception $mock_exception Exception to throw. + * @param string $expected_field_absent Field that should not be present. + * + * @return void + */ + public function test_enhance_schema_piece_error_handling( $enhancement, $post_id, $mock_function, $mock_params, $mock_exception, $expected_field_absent ) { + $indexable = new Indexable_Mock(); + $indexable->object_id = $post_id; + + $schema_data = [ + '@type' => 'Article', + ]; + + $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + + // Setup config to only enable the enhancement being tested + $enhancements = [ 'use_excerpt', 'article_body', 'keywords' ]; + foreach ( $enhancements as $enh ) { + $this->config->shouldReceive( 'is_enhancement_enabled' ) + ->with( $enh ) + ->andReturn( $enh === $enhancement ); + } + + // Setup the failing WordPress function + Functions\expect( $mock_function ) + ->with( ...$mock_params ) + ->andThrow( $mock_exception ); + + // Setup additional mocks for article body enhancement + if ( $enhancement === 'article_body' ) { + $this->config->shouldReceive( 'should_include_article_body' ) + ->with( false ) + ->andReturn( true ); + } + + $result = $this->instance->enhance( $schema_piece, $indexable ); + $enhanced_data = $result->get_data(); + + // Assert the field is not added due to the error + $this->assertArrayNotHasKey( $expected_field_absent, $enhanced_data ); + // Assert original schema data is preserved + $this->assertSame( 'Article', $enhanced_data['@type'] ); + } + + /** + * Sets up WordPress function mocks for specific test cases. + * + * @param array $config Configuration settings. + * @param array $expected_fields Expected output fields. + * @param int|null $post_id Post ID. + * + * @return void + */ + private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, $post_id ) { + // Handle excerpt mocks + if ( $config['use_excerpt'] && isset( $expected_fields['description'] ) ) { + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', $post_id ) + ->andReturn( $expected_fields['description'] ); + + Functions\expect( 'wp_strip_all_tags' ) + ->with( $expected_fields['description'] ) + ->andReturn( $expected_fields['description'] ); + + $this->config->shouldReceive( 'get_config_value' ) + ->with( 'excerpt_max_length', 0 ) + ->andReturn( 0 ); + } elseif ( $config['use_excerpt'] && ! isset( $expected_fields['description'] ) ) { + if ( $post_id === null || $post_id === 0 ) { + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', $post_id ) + ->andReturn( null ); + } else { + // Test case for empty excerpt with manual preference + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', $post_id ) + ->andReturn( '' ); + + $this->config->shouldReceive( 'get_config_value' ) + ->with( 'excerpt_prefer_manual', false ) + ->andReturn( true ); + } + } + + // Handle article body mocks + if ( $config['article_body'] && isset( $expected_fields['articleBody'] ) ) { + $has_excerpt = isset( $expected_fields['description'] ); + + $this->config->shouldReceive( 'should_include_article_body' ) + ->with( $has_excerpt ) + ->andReturn( true ); + + Functions\expect( 'get_post_field' ) + ->with( 'post_content', $post_id ) + ->andReturn( 'Article content with

HTML

' ); + + $this->config->shouldReceive( 'get_config_value' ) + ->with( 'strip_shortcodes_from_body', true ) + ->andReturn( true ); + + Functions\expect( 'strip_shortcodes' ) + ->with( 'Article content with

HTML

' ) + ->andReturn( 'Article content with

HTML

' ); + + $this->config->shouldReceive( 'get_config_value' ) + ->with( 'strip_html_from_body', true ) + ->andReturn( true ); + + Functions\expect( 'wp_strip_all_tags' ) + ->with( 'Article content with

HTML

' ) + ->andReturn( $expected_fields['articleBody'] ); + + $this->config->shouldReceive( 'get_config_value' ) + ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) + ->andReturn( 500 ); + } elseif ( $config['article_body'] && ! isset( $expected_fields['articleBody'] ) ) { + $has_excerpt = isset( $expected_fields['description'] ); + + $this->config->shouldReceive( 'should_include_article_body' ) + ->with( $has_excerpt ) + ->andReturn( true ); + + if ( $post_id === null || $post_id === 0 ) { + Functions\expect( 'get_post_field' ) + ->with( 'post_content', $post_id ) + ->andReturn( null ); + } + } + + // Handle keywords mocks + if ( $config['keywords'] && isset( $expected_fields['keywords'] ) ) { + $keywords = explode( ', ', $expected_fields['keywords'] ); + $tag_objects = []; + foreach ( $keywords as $keyword ) { + $tag_objects[] = (object) [ 'name' => $keyword ]; + } + + Functions\expect( 'get_the_tags' ) + ->with( $post_id ) + ->andReturn( $tag_objects ); + + $this->config->shouldReceive( 'get_config_value' ) + ->with( 'categories_as_keywords', false ) + ->andReturn( false ); + } elseif ( $config['keywords'] && ! isset( $expected_fields['keywords'] ) ) { + if ( $post_id === null || $post_id === 0 ) { + Functions\expect( 'get_the_tags' ) + ->with( $post_id ) + ->andReturn( null ); + + $this->config->shouldReceive( 'get_config_value' ) + ->with( 'categories_as_keywords', false ) + ->andReturn( false ); + } + } + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php new file mode 100644 index 00000000000..98154ff38b3 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php @@ -0,0 +1,58 @@ +config = Mockery::mock( Article_Config::class ); + $this->instance->set_article_config( $this->config ); + } + + /** + * Tests set_article_config() method. + * + * @covers ::set_article_config + * + * @return void + */ + public function test_set_article_config() { + $config = Mockery::mock( Article_Config::class ); + $instance = new Article_Schema_Enhancer(); + + $instance->set_article_config( $config ); + + $this->assertInstanceOf( Article_Schema_Enhancer::class, $instance ); + } +} From 3e04ed126084694e8c6800b4e16fe8ab4085d2b1 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 24 Dec 2025 16:52:43 +0100 Subject: [PATCH 211/319] Fix cs --- .../Article_Schema_Enhancer_Test.php | 295 ++++++++-------- .../Enhance_Schema_Piece_Test.php | 334 ++++++------------ .../Set_Article_Config_Test.php | 9 +- 3 files changed, 254 insertions(+), 384 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php index e3883556fb5..ba69086c818 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php @@ -1,5 +1,6 @@ instance = new Article_Schema_Enhancer(); - $this->config = Mockery::mock( Article_Config::class ); + $this->config = Mockery::mock( Article_Config::class ); $this->instance->set_article_config( $this->config ); } @@ -57,7 +58,7 @@ protected function set_up() { * @return void */ public function test_enhance_schema_piece_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; $schema_data = [ @@ -89,7 +90,7 @@ public function test_enhance_schema_piece_handles_exception() { * @return void */ public function test_get_article_keywords_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; $schema_data = [ @@ -135,7 +136,7 @@ public function test_get_article_keywords_handles_exception() { * @return void */ public function test_get_excerpt_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; $schema_data = [ @@ -181,7 +182,7 @@ public function test_get_excerpt_handles_exception() { * @return void */ public function test_get_article_body_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; $schema_data = [ @@ -234,7 +235,7 @@ public function test_get_article_body_handles_exception() { * @return void */ public function test_enhance_with_all_enhancements_enabled() { - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; $schema_data = [ @@ -245,7 +246,6 @@ public function test_enhance_with_all_enhancements_enabled() { $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - // Setup excerpt Functions\expect( 'get_post_field' ) ->with( 'post_excerpt', 123 ) ->andReturn( 'This is an excerpt' ); @@ -254,7 +254,6 @@ public function test_enhance_with_all_enhancements_enabled() { ->with( 'This is an excerpt' ) ->andReturn( 'This is an excerpt' ); - // Setup article body Functions\expect( 'get_post_field' ) ->with( 'post_content', 123 ) ->andReturn( 'This is the full article content' ); @@ -267,7 +266,6 @@ public function test_enhance_with_all_enhancements_enabled() { ->with( 'This is the full article content' ) ->andReturn( 'This is the full article content' ); - // Setup keywords $tag1 = (object) [ 'name' => 'tag1' ]; $tags_array = [ $tag1 ]; @@ -275,7 +273,6 @@ public function test_enhance_with_all_enhancements_enabled() { ->with( 123 ) ->andReturn( $tags_array ); - // Config expectations $this->config ->expects( 'is_enhancement_enabled' ) ->with( 'use_excerpt' ) @@ -337,138 +334,147 @@ public function test_enhance_with_all_enhancements_enabled() { public function data_provider_for_enhance_schema_piece() { return [ 'excerpt_enhancement_disabled' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => false, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ '@type' => 'Article' ], + 'schema_data' => [ '@type' => 'Article' ], 'expected_fields' => [], - 'excerpt_data' => null, - 'body_data' => null, - 'keywords_data' => null, + 'excerpt_data' => null, + 'body_data' => null, + 'keywords_data' => null, ], 'excerpt_enhancement_enabled_with_valid_excerpt' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => false, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ '@type' => 'Article' ], + 'schema_data' => [ '@type' => 'Article' ], 'expected_fields' => [ 'description' => 'Valid excerpt text' ], - 'excerpt_data' => [ - 'post_excerpt' => 'Valid excerpt text', + 'excerpt_data' => [ + 'post_excerpt' => 'Valid excerpt text', 'excerpt_max_length' => 0, ], - 'body_data' => null, - 'keywords_data' => null, + 'body_data' => null, + 'keywords_data' => null, ], 'excerpt_enhancement_with_existing_description' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => false, - 'keywords' => false, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + 'description' => 'Existing description', ], - 'schema_data' => [ '@type' => 'Article', 'description' => 'Existing description' ], 'expected_fields' => [ 'description' => 'Existing description' ], - 'excerpt_data' => [ - 'post_excerpt' => 'Valid excerpt text', + 'excerpt_data' => [ + 'post_excerpt' => 'Valid excerpt text', 'excerpt_max_length' => 0, ], - 'body_data' => null, - 'keywords_data' => null, + 'body_data' => null, + 'keywords_data' => null, ], 'article_body_enhancement_enabled' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => true, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ '@type' => 'Article' ], + 'schema_data' => [ '@type' => 'Article' ], 'expected_fields' => [ 'articleBody' => 'Article content' ], - 'excerpt_data' => null, - 'body_data' => [ - 'post_content' => 'Article content', - 'should_include' => true, + 'excerpt_data' => null, + 'body_data' => [ + 'post_content' => 'Article content', + 'should_include' => true, 'strip_shortcodes' => true, - 'strip_html' => true, - 'max_length' => 500, + 'strip_html' => true, + 'max_length' => 500, ], - 'keywords_data' => null, + 'keywords_data' => null, ], 'article_body_with_existing_body' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => true, - 'keywords' => false, + 'keywords' => false, + ], + 'schema_data' => [ + '@type' => 'Article', + 'articleBody' => 'Existing body', ], - 'schema_data' => [ '@type' => 'Article', 'articleBody' => 'Existing body' ], 'expected_fields' => [ 'articleBody' => 'Existing body' ], - 'excerpt_data' => null, - 'body_data' => [ - 'post_content' => 'Article content', - 'should_include' => true, + 'excerpt_data' => null, + 'body_data' => [ + 'post_content' => 'Article content', + 'should_include' => true, 'strip_shortcodes' => true, - 'strip_html' => true, - 'max_length' => 500, + 'strip_html' => true, + 'max_length' => 500, ], - 'keywords_data' => null, + 'keywords_data' => null, ], 'keywords_enhancement_enabled' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => false, - 'keywords' => true, + 'keywords' => true, ], - 'schema_data' => [ '@type' => 'Article' ], + 'schema_data' => [ '@type' => 'Article' ], 'expected_fields' => [ 'keywords' => 'tag1, tag2' ], - 'excerpt_data' => null, - 'body_data' => null, - 'keywords_data' => [ - 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], + 'excerpt_data' => null, + 'body_data' => null, + 'keywords_data' => [ + 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], 'categories_as_keywords' => false, ], ], 'keywords_with_existing_keywords' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => false, - 'keywords' => true, + 'keywords' => true, + ], + 'schema_data' => [ + '@type' => 'Article', + 'keywords' => 'existing, keywords', ], - 'schema_data' => [ '@type' => 'Article', 'keywords' => 'existing, keywords' ], 'expected_fields' => [ 'keywords' => 'existing, keywords' ], - 'excerpt_data' => null, - 'body_data' => null, - 'keywords_data' => [ - 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], + 'excerpt_data' => null, + 'body_data' => null, + 'keywords_data' => [ + 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], 'categories_as_keywords' => false, ], ], 'all_enhancements_enabled' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => true, - 'keywords' => true, + 'keywords' => true, ], - 'schema_data' => [ '@type' => 'Article' ], + 'schema_data' => [ '@type' => 'Article' ], 'expected_fields' => [ 'description' => 'Test excerpt', 'articleBody' => 'Test content', - 'keywords' => 'test-tag', + 'keywords' => 'test-tag', ], - 'excerpt_data' => [ - 'post_excerpt' => 'Test excerpt', + 'excerpt_data' => [ + 'post_excerpt' => 'Test excerpt', 'excerpt_max_length' => 0, ], - 'body_data' => [ - 'post_content' => 'Test content', - 'should_include' => true, + 'body_data' => [ + 'post_content' => 'Test content', + 'should_include' => true, 'strip_shortcodes' => true, - 'strip_html' => true, - 'max_length' => 500, + 'strip_html' => true, + 'max_length' => 500, ], - 'keywords_data' => [ - 'tags' => [ (object) [ 'name' => 'test-tag' ] ], + 'keywords_data' => [ + 'tags' => [ (object) [ 'name' => 'test-tag' ] ], 'categories_as_keywords' => false, ], ], @@ -486,22 +492,21 @@ public function data_provider_for_enhance_schema_piece() { * @covers ::get_article_body * @covers ::get_article_keywords * - * @param array $config Configuration for enhancements. - * @param array $schema_data Input schema data. - * @param array $expected_fields Expected output fields. - * @param array|null $excerpt_data Excerpt mock data. - * @param array|null $body_data Body mock data. - * @param array|null $keywords_data Keywords mock data. + * @param array $config Configuration for enhancements. + * @param array $schema_data Input schema data. + * @param array $expected_fields Expected output fields. + * @param array|null $excerpt_data Excerpt mock data. + * @param array|null $body_data Body mock data. + * @param array|null $keywords_data Keywords mock data. * * @return void */ public function test_enhance_schema_piece_with_different_configurations( $config, $schema_data, $expected_fields, $excerpt_data, $body_data, $keywords_data ) { - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; $schema_piece = new Schema_Piece( [ $schema_data ], 'Article' ); - // Setup config mocks foreach ( $config as $enhancement => $enabled ) { $this->config ->expects( 'is_enhancement_enabled' ) @@ -509,7 +514,6 @@ public function test_enhance_schema_piece_with_different_configurations( $config ->andReturn( $enabled ); } - // Setup excerpt mocks if ( $excerpt_data !== null && $config['use_excerpt'] ) { Functions\expect( 'get_post_field' ) ->with( 'post_excerpt', 123 ) @@ -525,7 +529,6 @@ public function test_enhance_schema_piece_with_different_configurations( $config ->andReturn( $excerpt_data['excerpt_max_length'] ); } - // Setup body mocks if ( $body_data !== null && $config['article_body'] ) { $has_excerpt = $excerpt_data !== null && $config['use_excerpt'] && ! isset( $schema_data['description'] ); @@ -568,7 +571,6 @@ public function test_enhance_schema_piece_with_different_configurations( $config } } - // Setup keywords mocks if ( $keywords_data !== null && $config['keywords'] && ! isset( $schema_data['keywords'] ) ) { Functions\expect( 'get_the_tags' ) ->with( 123 ) @@ -580,17 +582,16 @@ public function test_enhance_schema_piece_with_different_configurations( $config ->andReturn( $keywords_data['categories_as_keywords'] ); } - $result = $this->instance->enhance( $schema_piece, $indexable ); + $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); foreach ( $expected_fields as $field => $expected_value ) { - $this->assertSame( $expected_value, $enhanced_data[0][$field] ); + $this->assertSame( $expected_value, $enhanced_data[0][ $field ] ); } - // Ensure fields that shouldn't be added are not present $all_possible_fields = [ 'description', 'articleBody', 'keywords' ]; foreach ( $all_possible_fields as $field ) { - if ( ! isset( $expected_fields[$field] ) && ! isset( $schema_data[$field] ) ) { + if ( ! isset( $expected_fields[ $field ] ) && ! isset( $schema_data[ $field ] ) ) { $this->assertArrayNotHasKey( $field, $enhanced_data[0] ); } } @@ -604,65 +605,65 @@ public function test_enhance_schema_piece_with_different_configurations( $config public function data_provider_for_edge_cases() { return [ 'empty_excerpt' => [ - 'post_excerpt' => '', + 'post_excerpt' => '', 'excerpt_prefer_manual' => false, - 'post_content' => 'Some content', - 'expected_result' => 'Some content', + 'post_content' => 'Some content', + 'expected_result' => 'Some content', ], 'whitespace_only_excerpt' => [ - 'post_excerpt' => ' ', + 'post_excerpt' => ' ', 'excerpt_prefer_manual' => false, - 'post_content' => 'Some content', - 'expected_result' => 'Some content', + 'post_content' => 'Some content', + 'expected_result' => 'Some content', ], 'empty_excerpt_prefer_manual' => [ - 'post_excerpt' => '', + 'post_excerpt' => '', 'excerpt_prefer_manual' => true, - 'post_content' => 'Some content', - 'expected_result' => null, + 'post_content' => 'Some content', + 'expected_result' => null, ], 'wp_error_excerpt' => [ - 'post_excerpt' => new WP_Error( 'error', 'Error message' ), + 'post_excerpt' => new WP_Error( 'error', 'Error message' ), 'excerpt_prefer_manual' => false, - 'post_content' => 'Some content', - 'expected_result' => 'Some content', + 'post_content' => 'Some content', + 'expected_result' => 'Some content', ], 'wp_error_content' => [ - 'post_excerpt' => '', + 'post_excerpt' => '', 'excerpt_prefer_manual' => false, - 'post_content' => new WP_Error( 'error', 'Error message' ), - 'expected_result' => null, + 'post_content' => new WP_Error( 'error', 'Error message' ), + 'expected_result' => null, ], 'empty_content' => [ - 'post_excerpt' => '', + 'post_excerpt' => '', 'excerpt_prefer_manual' => false, - 'post_content' => '', - 'expected_result' => null, + 'post_content' => '', + 'expected_result' => null, ], 'tags_null' => [ - 'tags' => null, + 'tags' => null, 'categories_as_keywords' => false, - 'expected_keywords' => [], + 'expected_keywords' => [], ], 'tags_false' => [ - 'tags' => false, + 'tags' => false, 'categories_as_keywords' => false, - 'expected_keywords' => [], + 'expected_keywords' => [], ], 'tags_without_name_property' => [ - 'tags' => [ (object) [ 'slug' => 'tag1' ] ], + 'tags' => [ (object) [ 'slug' => 'tag1' ] ], 'categories_as_keywords' => false, - 'expected_keywords' => [], + 'expected_keywords' => [], ], 'categories_with_uncategorized' => [ - 'tags' => [], + 'tags' => [], 'categories_as_keywords' => true, - 'categories' => [ + 'categories' => [ (object) [ 'name' => 'Category1' ], (object) [ 'name' => 'Uncategorized' ], (object) [ 'name' => 'Category2' ], ], - 'expected_keywords' => [ 'Category1', 'Category2' ], + 'expected_keywords' => [ 'Category1', 'Category2' ], ], ]; } @@ -676,10 +677,10 @@ public function data_provider_for_edge_cases() { * @covers ::enhance_schema_piece * @covers ::get_excerpt * - * @param mixed $post_excerpt Post excerpt value. - * @param bool $excerpt_prefer_manual Whether to prefer manual excerpts. - * @param mixed $post_content Post content value. - * @param string|null $expected_result Expected result. + * @param mixed $post_excerpt Post excerpt value. + * @param bool $excerpt_prefer_manual Whether to prefer manual excerpts. + * @param mixed $post_content Post content value. + * @param string|null $expected_result Expected result. * * @return void */ @@ -688,10 +689,10 @@ public function test_get_excerpt_edge_cases( $post_excerpt, $excerpt_prefer_manu $this->markTestSkipped( 'This test case is for keywords, not excerpt' ); } - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; - $schema_data = [ [ '@type' => 'Article' ] ]; + $schema_data = [ [ '@type' => 'Article' ] ]; $schema_piece = new Schema_Piece( $schema_data, 'Article' ); $this->config @@ -743,12 +744,13 @@ public function test_get_excerpt_edge_cases( $post_excerpt, $excerpt_prefer_manu ->with( 'keywords' ) ->andReturn( false ); - $result = $this->instance->enhance( $schema_piece, $indexable ); + $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); if ( $expected_result !== null ) { $this->assertSame( $expected_result, $enhanced_data[0]['description'] ); - } else { + } + else { $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); } } @@ -762,10 +764,10 @@ public function test_get_excerpt_edge_cases( $post_excerpt, $excerpt_prefer_manu * @covers ::enhance_schema_piece * @covers ::get_article_keywords * - * @param mixed $tags Tags data. - * @param bool $categories_as_keywords Whether to include categories. - * @param array|null $categories Categories data. - * @param array $expected_keywords Expected keywords. + * @param mixed $tags Tags data. + * @param bool $categories_as_keywords Whether to include categories. + * @param array|null $categories Categories data. + * @param array $expected_keywords Expected keywords. * * @return void */ @@ -774,10 +776,10 @@ public function test_get_article_keywords_edge_cases( $tags = null, $categories_ $this->markTestSkipped( 'This test case is for excerpt, not keywords' ); } - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; - $schema_data = [ [ '@type' => 'Article' ] ]; + $schema_data = [ [ '@type' => 'Article' ] ]; $schema_piece = new Schema_Piece( $schema_data, 'Article' ); $this->config @@ -810,12 +812,13 @@ public function test_get_article_keywords_edge_cases( $tags = null, $categories_ ->andReturn( $categories ); } - $result = $this->instance->enhance( $schema_piece, $indexable ); + $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); if ( ! empty( $expected_keywords ) ) { $this->assertSame( \implode( ', ', $expected_keywords ), $enhanced_data[0]['keywords'] ); - } else { + } + else { $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); } } @@ -829,10 +832,10 @@ public function test_get_article_keywords_edge_cases( $tags = null, $categories_ * @return void */ public function test_enhance_schema_piece_with_invalid_object_id() { - $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = null; - $schema_data = [ [ '@type' => 'Article' ] ]; + $schema_data = [ [ '@type' => 'Article' ] ]; $schema_piece = new Schema_Piece( $schema_data, 'Article' ); $this->config @@ -854,7 +857,7 @@ public function test_enhance_schema_piece_with_invalid_object_id() { ->with( 'keywords' ) ->andReturn( false ); - $result = $this->instance->enhance( $schema_piece, $indexable ); + $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php index 16a739573dd..fd0a67e0950 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php @@ -1,8 +1,10 @@ instance->set_article_config( $this->config ); } - public function test_enhance_schema_piece_trigger_exception() { - $indexable = new Indexable_Mock(); - $indexable->object_id = 123123123; - $schema_data = [ - '@type' => 'Article', - '@context' => 'https://schema.org', - 'headline' => 'How to Optimize Your WordPress Site for SEO', - 'author' => [ - '@type' => 'Person', - 'name' => 'John Doe' - ], - 'datePublished' => '2024-01-15T10:30:00+00:00', - 'dateModified' => '2024-01-16T14:20:00+00:00', - 'publisher' => [ - '@type' => 'Organization', - 'name' => 'My WordPress Blog', - 'logo' => [ - '@type' => 'ImageObject', - 'url' => 'https://example.com/logo.png' - ] - ], - 'mainEntityOfPage' => [ - '@type' => 'WebPage', - '@id' => 'https://example.com/seo-optimization-guide' - ] - ]; - - $schema_piece = new Schema_Piece($schema_data, 'Article'); - - Functions\expect('get_post_field') - ->once() - ->with('post_excerpt', $indexable->object_id) - ->andThrow(new \Exception('Test exception')); - - $this->config->shouldReceive('is_enhancement_enabled') - ->with('use_excerpt') - ->andReturn(true); - - $result = $this->instance->enhance($schema_piece, $indexable); - - $this->assertEquals($schema_data, $result->get_data()); - } - /** - * Provides data for schema type validation tests. - * - * @return Generator - */ - public static function schema_type_provider(): Generator { - yield 'Article type' => [ - 'schema_data' => [ - [ - '@type' => 'Article', - ], - ], - 'schema_type' => 'Article', - 'should_enhance' => true, - 'expected_type' => 'Article', - 'expected_data_unchanged' => false, - ]; - - yield 'NewsArticle type' => [ - 'schema_data' => [ - [ - '@type' => 'NewsArticle', - ], - ], - 'schema_type' => 'NewsArticle', - 'should_enhance' => true, - 'expected_type' => 'NewsArticle', - 'expected_data_unchanged' => false, - ]; - - yield 'BlogPosting type' => [ - 'schema_data' => [ - [ - '@type' => 'BlogPosting', - ], - ], - 'schema_type' => 'BlogPosting', - 'should_enhance' => true, - 'expected_type' => 'BlogPosting', - 'expected_data_unchanged' => false, - ]; - - yield 'Array type containing Article' => [ - 'schema_data' => [ - [ - '@type' => [ 'Article', 'WebPage' ], - ], - ], - 'schema_type' => 'Article', - 'should_enhance' => true, - 'expected_type' => 'Article', - 'expected_data_unchanged' => false, - ]; - - yield 'Non-article type (WebPage)' => [ - 'schema_data' => [ - [ - '@type' => 'WebPage', - ], - ], - 'schema_type' => 'WebPage', - 'should_enhance' => false, - 'expected_type' => 'WebPage', - 'expected_data_unchanged' => true, - ]; - - yield 'Missing @type' => [ - 'schema_data' => [ - [ - 'name' => 'Some content', - ], - ], - 'schema_type' => 'Unknown', - 'should_enhance' => false, - 'expected_type' => 'Unknown', - 'expected_data_unchanged' => true, - ]; - } - /** * Data provider for enhance_schema_piece edge cases and error conditions. * @@ -165,164 +46,164 @@ public static function schema_type_provider(): Generator { */ public static function enhance_schema_piece_data_provider(): Generator { yield 'all_enhancements_disabled' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => false, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [], ]; yield 'excerpt_enhancement_enabled_with_valid_excerpt' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => false, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [ 'description' => 'Valid excerpt text', ], ]; yield 'excerpt_with_existing_description_should_not_override' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => false, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ - '@type' => 'Article', + 'schema_data' => [ + '@type' => 'Article', 'description' => 'Existing description', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [ 'description' => 'Existing description', ], ]; yield 'article_body_enhancement_enabled' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => true, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [ 'articleBody' => 'Article content without HTML', ], ]; yield 'article_body_with_existing_body_should_not_override' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => true, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ - '@type' => 'Article', + 'schema_data' => [ + '@type' => 'Article', 'articleBody' => 'Existing body', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [ 'articleBody' => 'Existing body', ], ]; yield 'keywords_enhancement_enabled_with_tags' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => false, - 'keywords' => true, + 'keywords' => true, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [ 'keywords' => 'tag1, tag2', ], ]; yield 'keywords_with_existing_keywords_should_not_override' => [ - 'config' => [ - 'use_excerpt' => false, + 'config' => [ + 'use_excerpt' => false, 'article_body' => false, - 'keywords' => true, + 'keywords' => true, ], - 'schema_data' => [ - '@type' => 'Article', + 'schema_data' => [ + '@type' => 'Article', 'keywords' => 'existing, keywords', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [ 'keywords' => 'existing, keywords', ], ]; yield 'all_enhancements_enabled_with_no_existing_fields' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => true, - 'keywords' => true, + 'keywords' => true, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [ 'description' => 'Test excerpt', 'articleBody' => 'Test content', - 'keywords' => 'test-tag', + 'keywords' => 'test-tag', ], ]; yield 'invalid_post_id_null' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => true, - 'keywords' => true, + 'keywords' => true, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => null, + 'post_id' => null, 'expected_fields' => [], ]; yield 'invalid_post_id_zero' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => true, - 'keywords' => true, + 'keywords' => true, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => 0, + 'post_id' => 0, 'expected_fields' => [], ]; yield 'empty_excerpt_with_manual_preference' => [ - 'config' => [ - 'use_excerpt' => true, + 'config' => [ + 'use_excerpt' => true, 'article_body' => false, - 'keywords' => false, + 'keywords' => false, ], - 'schema_data' => [ + 'schema_data' => [ '@type' => 'Article', ], - 'post_id' => 123, + 'post_id' => 123, 'expected_fields' => [], ]; } @@ -338,41 +219,37 @@ public static function enhance_schema_piece_data_provider(): Generator { * @covers ::get_article_body * @covers ::get_article_keywords * - * @param array $config Configuration for enhancements. - * @param array $schema_data Input schema data. - * @param int|null $post_id Post ID for testing. + * @param array $config Configuration for enhancements. + * @param array $schema_data Input schema data. + * @param int|null $post_id Post ID for testing. * @param array $expected_fields Expected output fields. * * @return void */ public function test_enhance_schema_piece_with_different_configurations( $config, $schema_data, $post_id, $expected_fields ) { - $indexable = new Indexable_Mock(); + $indexable = new Indexable_Mock(); $indexable->object_id = $post_id; $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - // Setup configuration mocks foreach ( $config as $enhancement => $enabled ) { $this->config->shouldReceive( 'is_enhancement_enabled' ) ->with( $enhancement ) ->andReturn( $enabled ); } - // Setup WordPress function mocks based on test case $this->setup_wordpress_mocks_for_test_case( $config, $expected_fields, $post_id ); - $result = $this->instance->enhance( $schema_piece, $indexable ); + $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - // Assert expected fields are present with correct values foreach ( $expected_fields as $field => $expected_value ) { - $this->assertSame( $expected_value, $enhanced_data[$field], "Field {$field} should match expected value" ); + $this->assertSame( $expected_value, $enhanced_data[ $field ], "Field {$field} should match expected value" ); } - // Assert fields that shouldn't be added are not present $all_possible_fields = [ 'description', 'articleBody', 'keywords' ]; foreach ( $all_possible_fields as $field ) { - if ( ! isset( $expected_fields[$field] ) && ! isset( $schema_data[$field] ) ) { + if ( ! isset( $expected_fields[ $field ] ) && ! isset( $schema_data[ $field ] ) ) { $this->assertArrayNotHasKey( $field, $enhanced_data, "Field {$field} should not be present" ); } } @@ -385,29 +262,29 @@ public function test_enhance_schema_piece_with_different_configurations( $config */ public static function error_conditions_data_provider(): Generator { yield 'excerpt_wp_error' => [ - 'enhancement' => 'use_excerpt', - 'post_id' => 123, - 'mock_function' => 'get_post_field', - 'mock_params' => [ 'post_excerpt', 123 ], - 'mock_exception' => new \Exception( 'Database error' ), + 'enhancement' => 'use_excerpt', + 'post_id' => 123, + 'mock_function' => 'get_post_field', + 'mock_params' => [ 'post_excerpt', 123 ], + 'mock_exception' => new Exception( 'Database error' ), 'expected_field_absent' => 'description', ]; yield 'article_body_wp_error' => [ - 'enhancement' => 'article_body', - 'post_id' => 456, - 'mock_function' => 'get_post_field', - 'mock_params' => [ 'post_content', 456 ], - 'mock_exception' => new \Exception( 'Content fetch error' ), + 'enhancement' => 'article_body', + 'post_id' => 456, + 'mock_function' => 'get_post_field', + 'mock_params' => [ 'post_content', 456 ], + 'mock_exception' => new Exception( 'Content fetch error' ), 'expected_field_absent' => 'articleBody', ]; yield 'keywords_wp_error' => [ - 'enhancement' => 'keywords', - 'post_id' => 789, - 'mock_function' => 'get_the_tags', - 'mock_params' => [ 789 ], - 'mock_exception' => new \Exception( 'Tags fetch error' ), + 'enhancement' => 'keywords', + 'post_id' => 789, + 'mock_function' => 'get_the_tags', + 'mock_params' => [ 789 ], + 'mock_exception' => new Exception( 'Tags fetch error' ), 'expected_field_absent' => 'keywords', ]; } @@ -423,17 +300,17 @@ public static function error_conditions_data_provider(): Generator { * @covers ::get_article_body * @covers ::get_article_keywords * - * @param string $enhancement Enhancement to test. - * @param int $post_id Post ID for testing. - * @param string $mock_function Function to mock. - * @param array $mock_params Parameters for the mock function. - * @param \Exception $mock_exception Exception to throw. - * @param string $expected_field_absent Field that should not be present. + * @param string $enhancement Enhancement to test. + * @param int $post_id Post ID for testing. + * @param string $mock_function Function to mock. + * @param array $mock_params Parameters for the mock function. + * @param Exception $mock_exception Exception to throw. + * @param string $expected_field_absent Field that should not be present. * * @return void */ public function test_enhance_schema_piece_error_handling( $enhancement, $post_id, $mock_function, $mock_params, $mock_exception, $expected_field_absent ) { - $indexable = new Indexable_Mock(); + $indexable = new Indexable_Mock(); $indexable->object_id = $post_id; $schema_data = [ @@ -442,7 +319,6 @@ public function test_enhance_schema_piece_error_handling( $enhancement, $post_id $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - // Setup config to only enable the enhancement being tested $enhancements = [ 'use_excerpt', 'article_body', 'keywords' ]; foreach ( $enhancements as $enh ) { $this->config->shouldReceive( 'is_enhancement_enabled' ) @@ -450,38 +326,33 @@ public function test_enhance_schema_piece_error_handling( $enhancement, $post_id ->andReturn( $enh === $enhancement ); } - // Setup the failing WordPress function Functions\expect( $mock_function ) ->with( ...$mock_params ) ->andThrow( $mock_exception ); - // Setup additional mocks for article body enhancement if ( $enhancement === 'article_body' ) { $this->config->shouldReceive( 'should_include_article_body' ) ->with( false ) ->andReturn( true ); } - $result = $this->instance->enhance( $schema_piece, $indexable ); + $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - // Assert the field is not added due to the error $this->assertArrayNotHasKey( $expected_field_absent, $enhanced_data ); - // Assert original schema data is preserved $this->assertSame( 'Article', $enhanced_data['@type'] ); } /** * Sets up WordPress function mocks for specific test cases. * - * @param array $config Configuration settings. + * @param array $config Configuration settings. * @param array $expected_fields Expected output fields. - * @param int|null $post_id Post ID. + * @param int|null $post_id Post ID. * * @return void */ private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, $post_id ) { - // Handle excerpt mocks if ( $config['use_excerpt'] && isset( $expected_fields['description'] ) ) { Functions\expect( 'get_post_field' ) ->with( 'post_excerpt', $post_id ) @@ -494,13 +365,14 @@ private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, $this->config->shouldReceive( 'get_config_value' ) ->with( 'excerpt_max_length', 0 ) ->andReturn( 0 ); - } elseif ( $config['use_excerpt'] && ! isset( $expected_fields['description'] ) ) { + } + elseif ( $config['use_excerpt'] && ! isset( $expected_fields['description'] ) ) { if ( $post_id === null || $post_id === 0 ) { Functions\expect( 'get_post_field' ) ->with( 'post_excerpt', $post_id ) ->andReturn( null ); - } else { - // Test case for empty excerpt with manual preference + } + else { Functions\expect( 'get_post_field' ) ->with( 'post_excerpt', $post_id ) ->andReturn( '' ); @@ -511,7 +383,6 @@ private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, } } - // Handle article body mocks if ( $config['article_body'] && isset( $expected_fields['articleBody'] ) ) { $has_excerpt = isset( $expected_fields['description'] ); @@ -542,7 +413,8 @@ private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, $this->config->shouldReceive( 'get_config_value' ) ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) ->andReturn( 500 ); - } elseif ( $config['article_body'] && ! isset( $expected_fields['articleBody'] ) ) { + } + elseif ( $config['article_body'] && ! isset( $expected_fields['articleBody'] ) ) { $has_excerpt = isset( $expected_fields['description'] ); $this->config->shouldReceive( 'should_include_article_body' ) @@ -556,9 +428,8 @@ private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, } } - // Handle keywords mocks if ( $config['keywords'] && isset( $expected_fields['keywords'] ) ) { - $keywords = explode( ', ', $expected_fields['keywords'] ); + $keywords = \explode( ', ', $expected_fields['keywords'] ); $tag_objects = []; foreach ( $keywords as $keyword ) { $tag_objects[] = (object) [ 'name' => $keyword ]; @@ -571,7 +442,8 @@ private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, $this->config->shouldReceive( 'get_config_value' ) ->with( 'categories_as_keywords', false ) ->andReturn( false ); - } elseif ( $config['keywords'] && ! isset( $expected_fields['keywords'] ) ) { + } + elseif ( $config['keywords'] && ! isset( $expected_fields['keywords'] ) ) { if ( $post_id === null || $post_id === 0 ) { Functions\expect( 'get_the_tags' ) ->with( $post_id ) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php index 98154ff38b3..5d2a6731bab 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php @@ -1,16 +1,11 @@ config = Mockery::mock( Article_Config::class ); + $this->config = Mockery::mock( Article_Config::class ); $this->instance->set_article_config( $this->config ); } From c775d1181aa131664d78e43d0ec4c258b3dbfb5b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 24 Dec 2025 16:54:55 +0100 Subject: [PATCH 212/319] Fix cs --- .../Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php index c6c59079551..d3706f8b61a 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Abstract_Schema_Enhancer/Trim_Content_To_Max_Length_Test.php @@ -1,4 +1,3 @@ - Date: Wed, 7 Jan 2026 22:56:00 +0100 Subject: [PATCH 213/319] Change method visibility for testing purposes --- .../application/enhancement/article-schema-enhancer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php index e4cde46f919..581b5f1ff5a 100644 --- a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php @@ -75,7 +75,7 @@ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Sch * * @return array The enhanced schema data. */ - private function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { + protected function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { try { $has_excerpt = false; From d88c55923d8b4c0ce37b142024ecd2d64cbbd22c Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 7 Jan 2026 22:56:08 +0100 Subject: [PATCH 214/319] Add test double --- .../Article_Schema_Enhancer_Double.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/Unit/Doubles/Schema_Aggregator/Article_Schema_Enhancer_Double.php diff --git a/tests/Unit/Doubles/Schema_Aggregator/Article_Schema_Enhancer_Double.php b/tests/Unit/Doubles/Schema_Aggregator/Article_Schema_Enhancer_Double.php new file mode 100644 index 00000000000..2936b9b1a07 --- /dev/null +++ b/tests/Unit/Doubles/Schema_Aggregator/Article_Schema_Enhancer_Double.php @@ -0,0 +1,24 @@ + $schema_data The schema data to enhance. + * @param Indexable $indexable The indexable object that is the source of the schema piece. + * + * @return array The enhanced schema data. + */ + public function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { + return parent::enhance_schema_piece( $schema_data, $indexable ); + } +} From ff4439abed9cf1d5a9bfec670aac2374ee629d32 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 7 Jan 2026 23:14:30 +0100 Subject: [PATCH 215/319] Add tests for Article_Schema_Enhancer --- .../Abstract_Article_Schema_Enhancer_Test.php | 14 +- .../Article_Schema_Enhancer_Test.php | 867 ------------------ .../Enhance_Schema_Piece_Test.php | 777 +++++++++------- .../Article_Schema_Enhancer/Enhance_Test.php | 96 ++ 4 files changed, 534 insertions(+), 1220 deletions(-) delete mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Abstract_Article_Schema_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Abstract_Article_Schema_Enhancer_Test.php index ccef802755a..a2ce01e44e0 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Abstract_Article_Schema_Enhancer_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Abstract_Article_Schema_Enhancer_Test.php @@ -4,10 +4,9 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Enhancement\Article_Schema_Enhancer; -require_once __DIR__ . '/../../../../../../src/schema-aggregator/application/enhancement/abstract-schema-enhancer.php'; -require_once __DIR__ . '/../../../../../../src/schema-aggregator/application/enhancement/article-schema-enhancer.php'; - +use Mockery; use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Article_Schema_Enhancer; +use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Article_Config; use Yoast\WP\SEO\Tests\Unit\TestCase; /** @@ -22,6 +21,13 @@ abstract class Abstract_Article_Schema_Enhancer_Test extends TestCase { */ protected $instance; + /** + * The Article_Config mock. + * + * @var Article_Config|Mockery\MockInterface + */ + protected $config; + /** * Sets up the test fixtures. * @@ -31,5 +37,7 @@ protected function set_up() { parent::set_up(); $this->instance = new Article_Schema_Enhancer(); + $this->config = Mockery::mock( Article_Config::class ); + $this->instance->set_article_config( $this->config ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php deleted file mode 100644 index ba69086c818..00000000000 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Article_Schema_Enhancer_Test.php +++ /dev/null @@ -1,867 +0,0 @@ -instance = new Article_Schema_Enhancer(); - $this->config = Mockery::mock( Article_Config::class ); - $this->instance->set_article_config( $this->config ); - } - - /** - * Tests exception handling in enhance_schema_piece method. - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * - * @return void - */ - public function test_enhance_schema_piece_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_data = [ - [ - '@type' => 'Article', - ], - ]; - - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andThrow( new Exception( 'Test exception' ) ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - - $enhanced_data = $result->get_data(); - $this->assertSame( $schema_data[0], $enhanced_data[0] ); - } - - /** - * Tests exception handling in get_article_keywords method. - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * @covers ::get_article_keywords - * - * @return void - */ - public function test_get_article_keywords_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_data = [ - [ - '@type' => 'Article', - ], - ]; - - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - Functions\expect( 'get_the_tags' ) - ->with( 123 ) - ->andThrow( new Exception( 'Test exception' ) ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'article_body' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'keywords' ) - ->andReturn( true ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - - $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); - } - - /** - * Tests exception handling in get_excerpt method. - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * @covers ::get_excerpt - * - * @return void - */ - public function test_get_excerpt_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_data = [ - [ - '@type' => 'Article', - ], - ]; - - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', 123 ) - ->andThrow( new Exception( 'Test exception' ) ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andReturn( true ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'article_body' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'keywords' ) - ->andReturn( false ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - - $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); - } - - /** - * Tests exception handling in get_article_body method. - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * @covers ::get_article_body - * - * @return void - */ - public function test_get_article_body_handles_exception() { - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_data = [ - [ - '@type' => 'Article', - ], - ]; - - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - Functions\expect( 'get_post_field' ) - ->with( 'post_content', 123 ) - ->andThrow( new Exception( 'Test exception' ) ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'article_body' ) - ->andReturn( true ); - - $this->config - ->expects( 'should_include_article_body' ) - ->with( false ) - ->andReturn( true ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'keywords' ) - ->andReturn( false ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - - $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'articleBody', $enhanced_data[0] ); - } - - /** - * Tests enhance() with all enhancements enabled at once. - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * @covers ::get_excerpt - * @covers ::get_article_body - * @covers ::get_article_keywords - * - * @return void - */ - public function test_enhance_with_all_enhancements_enabled() { - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_data = [ - [ - '@type' => 'Article', - ], - ]; - - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', 123 ) - ->andReturn( 'This is an excerpt' ); - - Functions\expect( 'wp_strip_all_tags' ) - ->with( 'This is an excerpt' ) - ->andReturn( 'This is an excerpt' ); - - Functions\expect( 'get_post_field' ) - ->with( 'post_content', 123 ) - ->andReturn( 'This is the full article content' ); - - Functions\expect( 'strip_shortcodes' ) - ->with( 'This is the full article content' ) - ->andReturn( 'This is the full article content' ); - - Functions\expect( 'wp_strip_all_tags' ) - ->with( 'This is the full article content' ) - ->andReturn( 'This is the full article content' ); - - $tag1 = (object) [ 'name' => 'tag1' ]; - $tags_array = [ $tag1 ]; - - Functions\expect( 'get_the_tags' ) - ->with( 123 ) - ->andReturn( $tags_array ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andReturn( true ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'excerpt_max_length', 0 ) - ->andReturn( 0 ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'article_body' ) - ->andReturn( true ); - - $this->config - ->expects( 'should_include_article_body' ) - ->with( true ) - ->andReturn( true ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'strip_shortcodes_from_body', true ) - ->andReturn( true ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'strip_html_from_body', true ) - ->andReturn( true ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) - ->andReturn( 500 ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'keywords' ) - ->andReturn( true ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'categories_as_keywords', false ) - ->andReturn( false ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - - $enhanced_data = $result->get_data(); - $this->assertSame( 'This is an excerpt', $enhanced_data[0]['description'] ); - $this->assertSame( 'This is the full article content', $enhanced_data[0]['articleBody'] ); - $this->assertSame( 'tag1', $enhanced_data[0]['keywords'] ); - } - - /** - * Data provider for enhance_schema_piece testing. - * - * @return array> - */ - public function data_provider_for_enhance_schema_piece() { - return [ - 'excerpt_enhancement_disabled' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => false, - 'keywords' => false, - ], - 'schema_data' => [ '@type' => 'Article' ], - 'expected_fields' => [], - 'excerpt_data' => null, - 'body_data' => null, - 'keywords_data' => null, - ], - 'excerpt_enhancement_enabled_with_valid_excerpt' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => false, - 'keywords' => false, - ], - 'schema_data' => [ '@type' => 'Article' ], - 'expected_fields' => [ 'description' => 'Valid excerpt text' ], - 'excerpt_data' => [ - 'post_excerpt' => 'Valid excerpt text', - 'excerpt_max_length' => 0, - ], - 'body_data' => null, - 'keywords_data' => null, - ], - 'excerpt_enhancement_with_existing_description' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => false, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - 'description' => 'Existing description', - ], - 'expected_fields' => [ 'description' => 'Existing description' ], - 'excerpt_data' => [ - 'post_excerpt' => 'Valid excerpt text', - 'excerpt_max_length' => 0, - ], - 'body_data' => null, - 'keywords_data' => null, - ], - 'article_body_enhancement_enabled' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => true, - 'keywords' => false, - ], - 'schema_data' => [ '@type' => 'Article' ], - 'expected_fields' => [ 'articleBody' => 'Article content' ], - 'excerpt_data' => null, - 'body_data' => [ - 'post_content' => 'Article content', - 'should_include' => true, - 'strip_shortcodes' => true, - 'strip_html' => true, - 'max_length' => 500, - ], - 'keywords_data' => null, - ], - 'article_body_with_existing_body' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => true, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - 'articleBody' => 'Existing body', - ], - 'expected_fields' => [ 'articleBody' => 'Existing body' ], - 'excerpt_data' => null, - 'body_data' => [ - 'post_content' => 'Article content', - 'should_include' => true, - 'strip_shortcodes' => true, - 'strip_html' => true, - 'max_length' => 500, - ], - 'keywords_data' => null, - ], - 'keywords_enhancement_enabled' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => false, - 'keywords' => true, - ], - 'schema_data' => [ '@type' => 'Article' ], - 'expected_fields' => [ 'keywords' => 'tag1, tag2' ], - 'excerpt_data' => null, - 'body_data' => null, - 'keywords_data' => [ - 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], - 'categories_as_keywords' => false, - ], - ], - 'keywords_with_existing_keywords' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => false, - 'keywords' => true, - ], - 'schema_data' => [ - '@type' => 'Article', - 'keywords' => 'existing, keywords', - ], - 'expected_fields' => [ 'keywords' => 'existing, keywords' ], - 'excerpt_data' => null, - 'body_data' => null, - 'keywords_data' => [ - 'tags' => [ (object) [ 'name' => 'tag1' ], (object) [ 'name' => 'tag2' ] ], - 'categories_as_keywords' => false, - ], - ], - 'all_enhancements_enabled' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => true, - 'keywords' => true, - ], - 'schema_data' => [ '@type' => 'Article' ], - 'expected_fields' => [ - 'description' => 'Test excerpt', - 'articleBody' => 'Test content', - 'keywords' => 'test-tag', - ], - 'excerpt_data' => [ - 'post_excerpt' => 'Test excerpt', - 'excerpt_max_length' => 0, - ], - 'body_data' => [ - 'post_content' => 'Test content', - 'should_include' => true, - 'strip_shortcodes' => true, - 'strip_html' => true, - 'max_length' => 500, - ], - 'keywords_data' => [ - 'tags' => [ (object) [ 'name' => 'test-tag' ] ], - 'categories_as_keywords' => false, - ], - ], - ]; - } - - /** - * Tests enhance_schema_piece method with various configurations. - * - * @dataProvider data_provider_for_enhance_schema_piece - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * @covers ::get_excerpt - * @covers ::get_article_body - * @covers ::get_article_keywords - * - * @param array $config Configuration for enhancements. - * @param array $schema_data Input schema data. - * @param array $expected_fields Expected output fields. - * @param array|null $excerpt_data Excerpt mock data. - * @param array|null $body_data Body mock data. - * @param array|null $keywords_data Keywords mock data. - * - * @return void - */ - public function test_enhance_schema_piece_with_different_configurations( $config, $schema_data, $expected_fields, $excerpt_data, $body_data, $keywords_data ) { - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_piece = new Schema_Piece( [ $schema_data ], 'Article' ); - - foreach ( $config as $enhancement => $enabled ) { - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( $enhancement ) - ->andReturn( $enabled ); - } - - if ( $excerpt_data !== null && $config['use_excerpt'] ) { - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', 123 ) - ->andReturn( $excerpt_data['post_excerpt'] ); - - Functions\expect( 'wp_strip_all_tags' ) - ->with( $excerpt_data['post_excerpt'] ) - ->andReturn( $excerpt_data['post_excerpt'] ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'excerpt_max_length', 0 ) - ->andReturn( $excerpt_data['excerpt_max_length'] ); - } - - if ( $body_data !== null && $config['article_body'] ) { - $has_excerpt = $excerpt_data !== null && $config['use_excerpt'] && ! isset( $schema_data['description'] ); - - $this->config - ->expects( 'should_include_article_body' ) - ->with( $has_excerpt ) - ->andReturn( $body_data['should_include'] ); - - if ( $body_data['should_include'] && ! isset( $schema_data['articleBody'] ) ) { - Functions\expect( 'get_post_field' ) - ->with( 'post_content', 123 ) - ->andReturn( $body_data['post_content'] ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'strip_shortcodes_from_body', true ) - ->andReturn( $body_data['strip_shortcodes'] ); - - if ( $body_data['strip_shortcodes'] ) { - Functions\expect( 'strip_shortcodes' ) - ->with( $body_data['post_content'] ) - ->andReturn( $body_data['post_content'] ); - } - - $this->config - ->expects( 'get_config_value' ) - ->with( 'strip_html_from_body', true ) - ->andReturn( $body_data['strip_html'] ); - - if ( $body_data['strip_html'] ) { - Functions\expect( 'wp_strip_all_tags' ) - ->with( $body_data['post_content'] ) - ->andReturn( $body_data['post_content'] ); - } - - $this->config - ->expects( 'get_config_value' ) - ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) - ->andReturn( $body_data['max_length'] ); - } - } - - if ( $keywords_data !== null && $config['keywords'] && ! isset( $schema_data['keywords'] ) ) { - Functions\expect( 'get_the_tags' ) - ->with( 123 ) - ->andReturn( $keywords_data['tags'] ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'categories_as_keywords', false ) - ->andReturn( $keywords_data['categories_as_keywords'] ); - } - - $result = $this->instance->enhance( $schema_piece, $indexable ); - $enhanced_data = $result->get_data(); - - foreach ( $expected_fields as $field => $expected_value ) { - $this->assertSame( $expected_value, $enhanced_data[0][ $field ] ); - } - - $all_possible_fields = [ 'description', 'articleBody', 'keywords' ]; - foreach ( $all_possible_fields as $field ) { - if ( ! isset( $expected_fields[ $field ] ) && ! isset( $schema_data[ $field ] ) ) { - $this->assertArrayNotHasKey( $field, $enhanced_data[0] ); - } - } - } - - /** - * Data provider for testing edge cases and error conditions. - * - * @return array> - */ - public function data_provider_for_edge_cases() { - return [ - 'empty_excerpt' => [ - 'post_excerpt' => '', - 'excerpt_prefer_manual' => false, - 'post_content' => 'Some content', - 'expected_result' => 'Some content', - ], - 'whitespace_only_excerpt' => [ - 'post_excerpt' => ' ', - 'excerpt_prefer_manual' => false, - 'post_content' => 'Some content', - 'expected_result' => 'Some content', - ], - 'empty_excerpt_prefer_manual' => [ - 'post_excerpt' => '', - 'excerpt_prefer_manual' => true, - 'post_content' => 'Some content', - 'expected_result' => null, - ], - 'wp_error_excerpt' => [ - 'post_excerpt' => new WP_Error( 'error', 'Error message' ), - 'excerpt_prefer_manual' => false, - 'post_content' => 'Some content', - 'expected_result' => 'Some content', - ], - 'wp_error_content' => [ - 'post_excerpt' => '', - 'excerpt_prefer_manual' => false, - 'post_content' => new WP_Error( 'error', 'Error message' ), - 'expected_result' => null, - ], - 'empty_content' => [ - 'post_excerpt' => '', - 'excerpt_prefer_manual' => false, - 'post_content' => '', - 'expected_result' => null, - ], - 'tags_null' => [ - 'tags' => null, - 'categories_as_keywords' => false, - 'expected_keywords' => [], - ], - 'tags_false' => [ - 'tags' => false, - 'categories_as_keywords' => false, - 'expected_keywords' => [], - ], - 'tags_without_name_property' => [ - 'tags' => [ (object) [ 'slug' => 'tag1' ] ], - 'categories_as_keywords' => false, - 'expected_keywords' => [], - ], - 'categories_with_uncategorized' => [ - 'tags' => [], - 'categories_as_keywords' => true, - 'categories' => [ - (object) [ 'name' => 'Category1' ], - (object) [ 'name' => 'Uncategorized' ], - (object) [ 'name' => 'Category2' ], - ], - 'expected_keywords' => [ 'Category1', 'Category2' ], - ], - ]; - } - - /** - * Tests get_excerpt method with edge cases. - * - * @dataProvider data_provider_for_edge_cases - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * @covers ::get_excerpt - * - * @param mixed $post_excerpt Post excerpt value. - * @param bool $excerpt_prefer_manual Whether to prefer manual excerpts. - * @param mixed $post_content Post content value. - * @param string|null $expected_result Expected result. - * - * @return void - */ - public function test_get_excerpt_edge_cases( $post_excerpt, $excerpt_prefer_manual, $post_content, $expected_result ) { - if ( ! \in_array( 'expected_result', \array_keys( \func_get_args() ), true ) ) { - $this->markTestSkipped( 'This test case is for keywords, not excerpt' ); - } - - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_data = [ [ '@type' => 'Article' ] ]; - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andReturn( true ); - - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', 123 ) - ->andReturn( $post_excerpt ); - - if ( ! \is_wp_error( $post_excerpt ) ) { - $this->config - ->expects( 'get_config_value' ) - ->with( 'excerpt_prefer_manual', false ) - ->andReturn( $excerpt_prefer_manual ); - - if ( ( empty( $post_excerpt ) || \trim( $post_excerpt ) === '' ) && ! $excerpt_prefer_manual ) { - Functions\expect( 'get_post_field' ) - ->with( 'post_content', 123 ) - ->andReturn( $post_content ); - - if ( ! \is_wp_error( $post_content ) && ! empty( $post_content ) ) { - Functions\expect( 'wp_trim_excerpt' ) - ->with( $post_content, 123 ) - ->andReturn( $expected_result ); - } - } - - if ( $expected_result !== null ) { - Functions\expect( 'wp_strip_all_tags' ) - ->with( $expected_result ) - ->andReturn( $expected_result ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'excerpt_max_length', 0 ) - ->andReturn( 0 ); - } - } - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'article_body' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'keywords' ) - ->andReturn( false ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - $enhanced_data = $result->get_data(); - - if ( $expected_result !== null ) { - $this->assertSame( $expected_result, $enhanced_data[0]['description'] ); - } - else { - $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); - } - } - - /** - * Tests get_article_keywords method with edge cases. - * - * @dataProvider data_provider_for_edge_cases - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * @covers ::get_article_keywords - * - * @param mixed $tags Tags data. - * @param bool $categories_as_keywords Whether to include categories. - * @param array|null $categories Categories data. - * @param array $expected_keywords Expected keywords. - * - * @return void - */ - public function test_get_article_keywords_edge_cases( $tags = null, $categories_as_keywords = false, $categories = null, $expected_keywords = [] ) { - if ( ! \in_array( 'expected_keywords', \array_keys( \func_get_args() ), true ) ) { - $this->markTestSkipped( 'This test case is for excerpt, not keywords' ); - } - - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = 123; - - $schema_data = [ [ '@type' => 'Article' ] ]; - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'article_body' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'keywords' ) - ->andReturn( true ); - - Functions\expect( 'get_the_tags' ) - ->with( 123 ) - ->andReturn( $tags ); - - $this->config - ->expects( 'get_config_value' ) - ->with( 'categories_as_keywords', false ) - ->andReturn( $categories_as_keywords ); - - if ( $categories_as_keywords && $categories !== null ) { - Functions\expect( 'get_the_category' ) - ->with( 123 ) - ->andReturn( $categories ); - } - - $result = $this->instance->enhance( $schema_piece, $indexable ); - $enhanced_data = $result->get_data(); - - if ( ! empty( $expected_keywords ) ) { - $this->assertSame( \implode( ', ', $expected_keywords ), $enhanced_data[0]['keywords'] ); - } - else { - $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); - } - } - - /** - * Tests enhance_schema_piece with null and invalid indexable object_id. - * - * @covers ::enhance - * @covers ::enhance_schema_piece - * - * @return void - */ - public function test_enhance_schema_piece_with_invalid_object_id() { - $indexable = Mockery::mock( Indexable_Mock::class ); - $indexable->object_id = null; - - $schema_data = [ [ '@type' => 'Article' ] ]; - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'use_excerpt' ) - ->andReturn( true ); - - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', null ) - ->andReturn( null ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'article_body' ) - ->andReturn( false ); - - $this->config - ->expects( 'is_enhancement_enabled' ) - ->with( 'keywords' ) - ->andReturn( false ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - $enhanced_data = $result->get_data(); - - $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); - $this->assertArrayNotHasKey( 'articleBody', $enhanced_data[0] ); - $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); - } -} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php index fd0a67e0950..31d77ce83ce 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php @@ -5,11 +5,10 @@ use Brain\Monkey\Functions; use Exception; -use Generator; use Mockery; -use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Article_Config; use Yoast\WP\SEO\Tests\Unit\Doubles\Models\Indexable_Mock; +use Yoast\WP\SEO\Tests\Unit\Doubles\Schema_Aggregator\Article_Schema_Enhancer_Double; /** * Tests the Article_Schema_Enhancer class enhance method. @@ -21,11 +20,11 @@ final class Enhance_Schema_Piece_Test extends Abstract_Article_Schema_Enhancer_Test { /** - * The Article_Config mock. + * The Article_Schema_Enhancer_Double * - * @var Article_Config|Mockery\MockInterface + * @var Article_Schema_Enhancer_Double */ - private $config; + private $article_schema_enhancer_double; /** * Sets up the test fixtures. @@ -34,425 +33,503 @@ final class Enhance_Schema_Piece_Test extends Abstract_Article_Schema_Enhancer_T */ protected function set_up() { parent::set_up(); - - $this->config = Mockery::mock( Article_Config::class ); - $this->instance->set_article_config( $this->config ); + $this->article_schema_enhancer_double = new Article_Schema_Enhancer_Double(); + $this->article_schema_enhancer_double->set_article_config( $this->config ); } /** - * Data provider for enhance_schema_piece edge cases and error conditions. + * Tests that enhance_schema_piece correctly handles exceptions. + * + * @covers ::enhance_schema_piece * - * @return Generator + * @return void */ - public static function enhance_schema_piece_data_provider(): Generator { - yield 'all_enhancements_disabled' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => false, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - ], - 'post_id' => 123, - 'expected_fields' => [], - ]; - - yield 'excerpt_enhancement_enabled_with_valid_excerpt' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => false, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - ], - 'post_id' => 123, - 'expected_fields' => [ - 'description' => 'Valid excerpt text', - ], - ]; - - yield 'excerpt_with_existing_description_should_not_override' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => false, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - 'description' => 'Existing description', - ], - 'post_id' => 123, - 'expected_fields' => [ - 'description' => 'Existing description', - ], - ]; - - yield 'article_body_enhancement_enabled' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => true, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - ], - 'post_id' => 123, - 'expected_fields' => [ - 'articleBody' => 'Article content without HTML', - ], - ]; - - yield 'article_body_with_existing_body_should_not_override' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => true, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - 'articleBody' => 'Existing body', + public function test_enhance_schema_piece_handles_exception() { + $schema_data = [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'http://example.com/vision-oriented-systematic-toolset/#article', + 'author' => [ + 'name' => 'Myron Welch', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', ], - 'post_id' => 123, - 'expected_fields' => [ - 'articleBody' => 'Existing body', + 'headline' => 'Vision-oriented systematic toolset', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'wordCount' => 184, + 'commentCount' => 0, + 'publisher' => [ + '@id' => 'http://example.com/#organization', ], - ]; - - yield 'keywords_enhancement_enabled_with_tags' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => false, - 'keywords' => true, + 'image' => [ + '@id' => 'http://example.com/vision-oriented-systematic-toolset/#primaryimage', ], - 'schema_data' => [ - '@type' => 'Article', + 'thumbnailUrl' => 'http://example.com/wp-content/uploads/2026/01/WordPress1.jpg', + 'keywords' => [ + 'Focused executive artificial intelligence', + 'Open-source bifurcated matrix', ], - 'post_id' => 123, - 'expected_fields' => [ - 'keywords' => 'tag1, tag2', + 'articleSection' => [ + 'Assimilated disintermediate moratorium', + 'Organized needs-based circuit', ], + 'inLanguage' => 'en-US', + 'description' => 'Test description', ]; - yield 'keywords_with_existing_keywords_should_not_override' => [ - 'config' => [ - 'use_excerpt' => false, - 'article_body' => false, - 'keywords' => true, - ], - 'schema_data' => [ - '@type' => 'Article', - 'keywords' => 'existing, keywords', - ], - 'post_id' => 123, - 'expected_fields' => [ - 'keywords' => 'existing, keywords', - ], - ]; + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; - yield 'all_enhancements_enabled_with_no_existing_fields' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => true, - 'keywords' => true, - ], - 'schema_data' => [ - '@type' => 'Article', - ], - 'post_id' => 123, - 'expected_fields' => [ - 'description' => 'Test excerpt', - 'articleBody' => 'Test content', - 'keywords' => 'test-tag', - ], - ]; + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( true ); - yield 'invalid_post_id_null' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => true, - 'keywords' => true, - ], - 'schema_data' => [ - '@type' => 'Article', - ], - 'post_id' => null, - 'expected_fields' => [], - ]; + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', $indexable->object_id ) + ->andThrow( new Exception( 'Dummy exception' ) ); - yield 'invalid_post_id_zero' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => true, - 'keywords' => true, - ], - 'schema_data' => [ - '@type' => 'Article', - ], - 'post_id' => 0, - 'expected_fields' => [], - ]; + $data = $this->article_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); - yield 'empty_excerpt_with_manual_preference' => [ - 'config' => [ - 'use_excerpt' => true, - 'article_body' => false, - 'keywords' => false, - ], - 'schema_data' => [ - '@type' => 'Article', - ], - 'post_id' => 123, - 'expected_fields' => [], - ]; + $this->assertEquals( $schema_data, $data ); } /** - * Tests enhance_schema_piece method with various configurations using data provider. - * - * @dataProvider enhance_schema_piece_data_provider + * Tests the enhance_schema_piece method in case use_excerpt is true. * - * @covers ::enhance * @covers ::enhance_schema_piece - * @covers ::get_excerpt - * @covers ::get_article_body - * @covers ::get_article_keywords * - * @param array $config Configuration for enhancements. - * @param array $schema_data Input schema data. - * @param int|null $post_id Post ID for testing. - * @param array $expected_fields Expected output fields. + * @dataProvider enhance_schema_piece_use_excerpt_data_provider + * + * @param array $schema_data The schema piece data. + * @param string $expected_result The expected behavior. + * @param string $post_excerpt The post excerpt. * * @return void */ - public function test_enhance_schema_piece_with_different_configurations( $config, $schema_data, $post_id, $expected_fields ) { - $indexable = new Indexable_Mock(); - $indexable->object_id = $post_id; + public function test_enhance_schema_piece_use_excerpt( array $schema_data, string $expected_result, string $post_excerpt ) { - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; - foreach ( $config as $enhancement => $enabled ) { - $this->config->shouldReceive( 'is_enhancement_enabled' ) - ->with( $enhancement ) - ->andReturn( $enabled ); - } + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( true ); - $this->setup_wordpress_mocks_for_test_case( $config, $expected_fields, $post_id ); + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); - $result = $this->instance->enhance( $schema_piece, $indexable ); - $enhanced_data = $result->get_data(); + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( false ); - foreach ( $expected_fields as $field => $expected_value ) { - $this->assertSame( $expected_value, $enhanced_data[ $field ], "Field {$field} should match expected value" ); - } + Functions\expect( 'get_post_field' ) + ->with( 'post_excerpt', $indexable->object_id ) + ->andReturn( $post_excerpt ); - $all_possible_fields = [ 'description', 'articleBody', 'keywords' ]; - foreach ( $all_possible_fields as $field ) { - if ( ! isset( $expected_fields[ $field ] ) && ! isset( $schema_data[ $field ] ) ) { - $this->assertArrayNotHasKey( $field, $enhanced_data, "Field {$field} should not be present" ); - } - } + Functions\expect( 'wp_strip_all_tags' ) + ->with( 'The post excerpt' ) + ->andReturn( $post_excerpt ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'excerpt_max_length', 0 ) + ->andReturn( 0 ); + + $data = $this->article_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + $this->assertSame( $expected_result, $data ); } /** - * Data provider for testing error conditions. + * Data provider for test_enhance_schema_piece_use_excerpt * - * @return Generator + * @return array> */ - public static function error_conditions_data_provider(): Generator { - yield 'excerpt_wp_error' => [ - 'enhancement' => 'use_excerpt', - 'post_id' => 123, - 'mock_function' => 'get_post_field', - 'mock_params' => [ 'post_excerpt', 123 ], - 'mock_exception' => new Exception( 'Database error' ), - 'expected_field_absent' => 'description', + public function enhance_schema_piece_use_excerpt_data_provider(): array { + return [ + 'with_existing_description' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'description' => 'Existing description', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'description' => 'Existing description', + ], + 'post_excerpt' => 'The post excerpt', + ], + 'without_existing_description' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'description' => 'The post excerpt', + ], + 'post_excerpt' => 'The post excerpt', + ], ]; + } - yield 'article_body_wp_error' => [ - 'enhancement' => 'article_body', - 'post_id' => 456, - 'mock_function' => 'get_post_field', - 'mock_params' => [ 'post_content', 456 ], - 'mock_exception' => new Exception( 'Content fetch error' ), - 'expected_field_absent' => 'articleBody', + /** + * Tests the enhance_schema_piece method when article_body should be included. + * + * @covers ::enhance_schema_piece + * + * @return void + */ + public function test_enhance_schema_piece_article_body_should_include() { + $schema_data = [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', ]; - yield 'keywords_wp_error' => [ - 'enhancement' => 'keywords', - 'post_id' => 789, - 'mock_function' => 'get_the_tags', - 'mock_params' => [ 789 ], - 'mock_exception' => new Exception( 'Tags fetch error' ), - 'expected_field_absent' => 'keywords', + $expected_result = [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'articleBody' => 'This is the full article body content.', ]; + + $post_content = 'This is the full article body content.'; + + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( true ); + + $this->config + ->expects( 'should_include_article_body' ) + ->with( false ) + ->andReturn( true ); + + Functions\expect( 'get_post_field' ) + ->with( 'post_content', $indexable->object_id ) + ->andReturn( $post_content ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'strip_shortcodes_from_body', true ) + ->andReturn( true ); + + Functions\expect( 'strip_shortcodes' ) + ->with( $post_content ) + ->andReturn( $post_content ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'strip_html_from_body', true ) + ->andReturn( true ); + + Functions\expect( 'wp_strip_all_tags' ) + ->with( $post_content ) + ->andReturn( $post_content ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) + ->andReturn( 0 ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( false ); + + $data = $this->article_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + $this->assertSame( $expected_result, $data ); } /** - * Tests error handling in enhance_schema_piece method. - * - * @dataProvider error_conditions_data_provider + * Tests the enhance_schema_piece method when article_body should not be included. * - * @covers ::enhance * @covers ::enhance_schema_piece - * @covers ::get_excerpt - * @covers ::get_article_body - * @covers ::get_article_keywords * - * @param string $enhancement Enhancement to test. - * @param int $post_id Post ID for testing. - * @param string $mock_function Function to mock. - * @param array $mock_params Parameters for the mock function. - * @param Exception $mock_exception Exception to throw. - * @param string $expected_field_absent Field that should not be present. + * @dataProvider enhance_schema_piece_article_body_skip_data_provider + * + * @param array $schema_data The schema piece data. + * @param array $expected_result The expected result. + * @param bool $has_existing_article_body Whether the schema already has articleBody. * * @return void */ - public function test_enhance_schema_piece_error_handling( $enhancement, $post_id, $mock_function, $mock_params, $mock_exception, $expected_field_absent ) { - $indexable = new Indexable_Mock(); - $indexable->object_id = $post_id; - - $schema_data = [ - '@type' => 'Article', - ]; + public function test_enhance_schema_piece_article_body_skip( $schema_data, $expected_result, $has_existing_article_body ) { - $schema_piece = new Schema_Piece( $schema_data, 'Article' ); + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; - $enhancements = [ 'use_excerpt', 'article_body', 'keywords' ]; - foreach ( $enhancements as $enh ) { - $this->config->shouldReceive( 'is_enhancement_enabled' ) - ->with( $enh ) - ->andReturn( $enh === $enhancement ); - } + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( false ); - Functions\expect( $mock_function ) - ->with( ...$mock_params ) - ->andThrow( $mock_exception ); + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( true ); - if ( $enhancement === 'article_body' ) { - $this->config->shouldReceive( 'should_include_article_body' ) + if ( ! $has_existing_article_body ) { + $this->config + ->expects( 'should_include_article_body' ) ->with( false ) - ->andReturn( true ); + ->andReturn( false ); } - $result = $this->instance->enhance( $schema_piece, $indexable ); - $enhanced_data = $result->get_data(); + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( false ); - $this->assertArrayNotHasKey( $expected_field_absent, $enhanced_data ); - $this->assertSame( 'Article', $enhanced_data['@type'] ); + $data = $this->article_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + $this->assertSame( $expected_result, $data ); } /** - * Sets up WordPress function mocks for specific test cases. + * Data provider for test_enhance_schema_piece_article_body_skip * - * @param array $config Configuration settings. - * @param array $expected_fields Expected output fields. - * @param int|null $post_id Post ID. + * @return array> + */ + public function enhance_schema_piece_article_body_skip_data_provider(): array { + return [ + 'with_existing_article_body' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'articleBody' => 'Existing article body', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'articleBody' => 'Existing article body', + ], + 'has_existing_article_body' => true, + ], + 'without_existing_article_body_and_should_not_include' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + ], + 'has_existing_article_body' => false, + ], + ]; + } + + /** + * Tests the enhance_schema_piece method when keywords are already set. + * + * @covers ::enhance_schema_piece * * @return void */ - private function setup_wordpress_mocks_for_test_case( $config, $expected_fields, $post_id ) { - if ( $config['use_excerpt'] && isset( $expected_fields['description'] ) ) { - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', $post_id ) - ->andReturn( $expected_fields['description'] ); - - Functions\expect( 'wp_strip_all_tags' ) - ->with( $expected_fields['description'] ) - ->andReturn( $expected_fields['description'] ); - - $this->config->shouldReceive( 'get_config_value' ) - ->with( 'excerpt_max_length', 0 ) - ->andReturn( 0 ); - } - elseif ( $config['use_excerpt'] && ! isset( $expected_fields['description'] ) ) { - if ( $post_id === null || $post_id === 0 ) { - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', $post_id ) - ->andReturn( null ); - } - else { - Functions\expect( 'get_post_field' ) - ->with( 'post_excerpt', $post_id ) - ->andReturn( '' ); - - $this->config->shouldReceive( 'get_config_value' ) - ->with( 'excerpt_prefer_manual', false ) - ->andReturn( true ); - } - } - - if ( $config['article_body'] && isset( $expected_fields['articleBody'] ) ) { - $has_excerpt = isset( $expected_fields['description'] ); + public function test_enhance_schema_piece_keywords_already_set() { + $schema_data = [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'keywords' => 'Existing keywords', + ]; - $this->config->shouldReceive( 'should_include_article_body' ) - ->with( $has_excerpt ) - ->andReturn( true ); + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; - Functions\expect( 'get_post_field' ) - ->with( 'post_content', $post_id ) - ->andReturn( 'Article content with

HTML

' ); + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( false ); - $this->config->shouldReceive( 'get_config_value' ) - ->with( 'strip_shortcodes_from_body', true ) - ->andReturn( true ); + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); - Functions\expect( 'strip_shortcodes' ) - ->with( 'Article content with

HTML

' ) - ->andReturn( 'Article content with

HTML

' ); + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( true ); - $this->config->shouldReceive( 'get_config_value' ) - ->with( 'strip_html_from_body', true ) - ->andReturn( true ); + $data = $this->article_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + $this->assertSame( $schema_data, $data ); + } - Functions\expect( 'wp_strip_all_tags' ) - ->with( 'Article content with

HTML

' ) - ->andReturn( $expected_fields['articleBody'] ); + /** + * Tests the enhance_schema_piece method for keywords enhancement. + * + * @covers ::enhance_schema_piece + * + * @dataProvider enhance_schema_piece_keywords_data_provider + * + * @param array $tags The tags assigned to the post. + * @param bool $categories_as_keywords Whether to include categories as keywords. + * @param array $categories The categories assigned to the post. + * @param array $expected_data The expected enhanced schema data. + * + * @return void + */ + public function test_enhance_schema_piece_keywords( $tags, $categories_as_keywords, $categories, $expected_data ) { + $schema_data = [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + ]; - $this->config->shouldReceive( 'get_config_value' ) - ->with( 'article_body_max_length', Article_Config::DEFAULT_MAX_ARTICLE_BODY_LENGTH ) - ->andReturn( 500 ); - } - elseif ( $config['article_body'] && ! isset( $expected_fields['articleBody'] ) ) { - $has_excerpt = isset( $expected_fields['description'] ); - - $this->config->shouldReceive( 'should_include_article_body' ) - ->with( $has_excerpt ) - ->andReturn( true ); - - if ( $post_id === null || $post_id === 0 ) { - Functions\expect( 'get_post_field' ) - ->with( 'post_content', $post_id ) - ->andReturn( null ); - } + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'use_excerpt' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'article_body' ) + ->andReturn( false ); + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'keywords' ) + ->andReturn( true ); + + Functions\expect( 'get_the_tags' ) + ->with( $indexable->object_id ) + ->andReturn( $tags ); + + $this->config + ->expects( 'get_config_value' ) + ->with( 'categories_as_keywords', false ) + ->andReturn( $categories_as_keywords ); + + if ( $categories_as_keywords ) { + Functions\expect( 'get_the_category' ) + ->with( $indexable->object_id ) + ->andReturn( $categories ); } - if ( $config['keywords'] && isset( $expected_fields['keywords'] ) ) { - $keywords = \explode( ', ', $expected_fields['keywords'] ); - $tag_objects = []; - foreach ( $keywords as $keyword ) { - $tag_objects[] = (object) [ 'name' => $keyword ]; - } - - Functions\expect( 'get_the_tags' ) - ->with( $post_id ) - ->andReturn( $tag_objects ); + $data = $this->article_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + $this->assertSame( $expected_data, $data ); + } - $this->config->shouldReceive( 'get_config_value' ) - ->with( 'categories_as_keywords', false ) - ->andReturn( false ); - } - elseif ( $config['keywords'] && ! isset( $expected_fields['keywords'] ) ) { - if ( $post_id === null || $post_id === 0 ) { - Functions\expect( 'get_the_tags' ) - ->with( $post_id ) - ->andReturn( null ); - - $this->config->shouldReceive( 'get_config_value' ) - ->with( 'categories_as_keywords', false ) - ->andReturn( false ); - } - } + /** + * Data provider for test_enhance_schema_piece_keywords + * + * @return array> + */ + public function enhance_schema_piece_keywords_data_provider(): array { + return [ + 'with_tags_and_categories_as_keywords' => [ + 'tags' => [ + (object) [ 'name' => 'Tag1' ], + (object) [ 'name' => 'Tag2' ], + ], + 'categories_as_keywords' => true, + 'categories' => [ + (object) [ 'name' => 'Category1' ], + (object) [ 'name' => 'Category2' ], + ], + 'expected_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'keywords' => 'Tag1, Tag2, Category1, Category2', + ], + ], + 'with_tags_and_without_categories_as_keywords' => [ + 'tags' => [ + (object) [ 'name' => 'Tag1' ], + (object) [ 'name' => 'Tag2' ], + ], + 'categories_as_keywords' => false, + 'categories' => [], + 'expected_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'keywords' => 'Tag1, Tag2', + ], + ], + 'without_tags_and_with_categories_as_keywords' => [ + 'tags' => [], + 'categories_as_keywords' => true, + 'categories' => [ + (object) [ 'name' => 'Category1' ], + (object) [ 'name' => 'Category2' ], + ], + 'expected_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + 'keywords' => 'Category1, Category2', + ], + ], + 'without_tags_and_categories_as_keywords' => [ + 'tags' => [], + 'categories_as_keywords' => false, + 'categories' => [], + 'expected_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Article', + '@id' => 'https://example.com/article/#article', + 'headline' => 'Test Article', + 'datePublished' => '2025-08-31T14:47:54+00:00', + ], + ], + ]; } } diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php new file mode 100644 index 00000000000..545c0a9fc6b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php @@ -0,0 +1,96 @@ +> $schema_data The schema piece data. + * + * @phpcs :enable + * + * @return void + */ + public function test_enhance( $schema_data ) { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->object_id = 123; + + $schema_piece = new Schema_Piece( $schema_data, 'Test' ); + $schema = $this->instance->enhance( $schema_piece, $indexable ); + + $this->assertEquals( $schema_data, $schema->get_data() ); + } + + /** + * Data provider for enhance_schema_piece testing. + * + * @return array> + */ + public function enhance_data_provider(): array { + return [ + 'Type not set' => [ + [ + 'url' => 'https://example.com', + 'articleBody' => 'Article content', + ], + ], + 'Wrong simple type' => [ + [ + 'url' => 'https://example.com', + 'articleBody' => 'Article content', + '@type' => 'Article', + ], + ], + 'Type not allowed' => [ + [ + 'url' => 'https://example.com', + 'articleBody' => 'Article content', + '@type' => 'Author', + ], + ], + 'Wrong array type' => [ + [ + 'url' => 'https://example.com', + 'articleBody' => 'Article content', + '@type' => [ true, true, false ], + ], + ], + 'Array type not allowed' => [ + [ + 'url' => 'https://example.com', + 'articleBody' => 'Article content', + '@type' => [ 'Author', 'Dummy' ], + ], + ], + ]; + } +} From fbc70058bf3312159e415cac2a97ec9aae017afb Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 8 Jan 2026 09:55:47 +0100 Subject: [PATCH 216/319] Fix wrong visibility --- .../Article_Schema_Enhancer/Set_Article_Config_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php index 5d2a6731bab..e0ee28447da 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php @@ -21,7 +21,7 @@ final class Set_Article_Config_Test extends Abstract_Article_Schema_Enhancer_Tes * * @var Article_Config|Mockery\MockInterface */ - private $config; + protected $config; /** * Sets up the test fixtures. From 1e75a564213c87ed044189100e09b0683f65a4e6 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 8 Jan 2026 09:56:02 +0100 Subject: [PATCH 217/319] Remove useless setup method --- .../Enhancement/Article_Schema_Enhancer/Enhance_Test.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php index 545c0a9fc6b..5b333414b1a 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php @@ -16,15 +16,6 @@ */ final class Enhance_Test extends Abstract_Article_Schema_Enhancer_Test { - /** - * Sets up the test fixtures. - * - * @return void - */ - protected function set_up() { - parent::set_up(); - } - /** * Test. * From 038a6bb087d6782463dc770e6e2800bbba846989 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 8 Jan 2026 09:56:21 +0100 Subject: [PATCH 218/319] Fix param annotation --- .../Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php index 31d77ce83ce..654e0ef7f20 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Schema_Piece_Test.php @@ -101,12 +101,12 @@ public function test_enhance_schema_piece_handles_exception() { * @dataProvider enhance_schema_piece_use_excerpt_data_provider * * @param array $schema_data The schema piece data. - * @param string $expected_result The expected behavior. + * @param array $expected_result The expected behavior. * @param string $post_excerpt The post excerpt. * * @return void */ - public function test_enhance_schema_piece_use_excerpt( array $schema_data, string $expected_result, string $post_excerpt ) { + public function test_enhance_schema_piece_use_excerpt( array $schema_data, array $expected_result, string $post_excerpt ) { $indexable = Mockery::mock( Indexable_Mock::class ); $indexable->object_id = 123; From ffc4e5f0f97080812596a2b200f58fd407c20af4 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 8 Jan 2026 12:11:10 +0100 Subject: [PATCH 219/319] Fix integration tests --- .../Article_Schema_Enhancer_Test.php | 159 ++++++------------ .../Person_Schema_Enhancer_Test.php | 112 +++--------- 2 files changed, 71 insertions(+), 200 deletions(-) diff --git a/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php index 2ef0594f4a9..ab41e31f152 100644 --- a/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php +++ b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php @@ -91,18 +91,16 @@ public function test_enhance_adds_description_from_excerpt_for_article() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - ], + '@type' => 'Article', + 'name' => 'Test Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'description', $enhanced_data[0] ); - $this->assertSame( 'This is a test excerpt for the article.', $enhanced_data[0]['description'] ); + $this->assertArrayHasKey( 'description', $enhanced_data ); + $this->assertSame( 'This is a test excerpt for the article.', $enhanced_data['description'] ); } /** @@ -144,19 +142,17 @@ public function test_enhance_adds_article_body_when_no_excerpt() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - ], + '@type' => 'Article', + 'name' => 'Test Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'description', $enhanced_data[0] ); - $this->assertArrayHasKey( 'articleBody', $enhanced_data[0] ); - $this->assertSame( 'This is the full article content that should appear as articleBody.', $enhanced_data[0]['articleBody'] ); + $this->assertArrayHasKey( 'description', $enhanced_data ); + $this->assertArrayHasKey( 'articleBody', $enhanced_data ); + $this->assertSame( 'This is the full article content that should appear as articleBody.', $enhanced_data['articleBody'] ); // Clean up filter. \remove_filter( 'wpseo_article_enhance_body_when_excerpt_exists', '__return_true' ); @@ -184,18 +180,16 @@ public function test_enhance_adds_keywords_from_tags() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - ], + '@type' => 'Article', + 'name' => 'Test Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'keywords', $enhanced_data[0] ); - $this->assertSame( 'SEO, WordPress', $enhanced_data[0]['keywords'] ); + $this->assertArrayHasKey( 'keywords', $enhanced_data ); + $this->assertSame( 'SEO, WordPress', $enhanced_data['keywords'] ); } /** @@ -222,18 +216,16 @@ public function test_enhance_adds_keywords_from_categories_when_enabled() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - ], + '@type' => 'Article', + 'name' => 'Test Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'keywords', $enhanced_data[0] ); - $this->assertStringContainsString( 'Technology', $enhanced_data[0]['keywords'] ); + $this->assertArrayHasKey( 'keywords', $enhanced_data ); + $this->assertStringContainsString( 'Technology', $enhanced_data['keywords'] ); // Clean up filter. \remove_filter( 'wpseo_article_enhance_config_categories_as_keywords', '__return_true' ); @@ -257,18 +249,16 @@ public function test_enhance_works_with_news_article_type() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'NewsArticle', - 'name' => 'Test News Article', - ], + '@type' => 'NewsArticle', + 'name' => 'Test News Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'description', $enhanced_data[0] ); - $this->assertSame( 'Breaking news excerpt.', $enhanced_data[0]['description'] ); + $this->assertArrayHasKey( 'description', $enhanced_data ); + $this->assertSame( 'Breaking news excerpt.', $enhanced_data['description'] ); } /** @@ -289,18 +279,16 @@ public function test_enhance_works_with_blog_posting_type() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'BlogPosting', - 'name' => 'Test Blog Post', - ], + '@type' => 'BlogPosting', + 'name' => 'Test Blog Post', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'description', $enhanced_data[0] ); - $this->assertSame( 'Blog post excerpt.', $enhanced_data[0]['description'] ); + $this->assertArrayHasKey( 'description', $enhanced_data ); + $this->assertSame( 'Blog post excerpt.', $enhanced_data['description'] ); } /** @@ -321,18 +309,16 @@ public function test_enhance_works_with_article_in_type_array() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => [ 'Article', 'WebPage' ], - 'name' => 'Test Article', - ], + '@type' => [ 'Article', 'WebPage' ], + 'name' => 'Test Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'description', $enhanced_data[0] ); - $this->assertSame( 'Article with multiple types.', $enhanced_data[0]['description'] ); + $this->assertArrayHasKey( 'description', $enhanced_data ); + $this->assertSame( 'Article with multiple types.', $enhanced_data['description'] ); } /** @@ -353,18 +339,16 @@ public function test_enhance_does_not_override_existing_description() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - 'description' => 'Existing description', - ], + '@type' => 'Article', + 'name' => 'Test Article', + 'description' => 'Existing description', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertSame( 'Existing description', $enhanced_data[0]['description'] ); + $this->assertSame( 'Existing description', $enhanced_data['description'] ); } /** @@ -385,18 +369,16 @@ public function test_enhance_does_not_override_existing_article_body() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - 'articleBody' => 'Existing article body', - ], + '@type' => 'Article', + 'name' => 'Test Article', + 'articleBody' => 'Existing article body', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertSame( 'Existing article body', $enhanced_data[0]['articleBody'] ); + $this->assertSame( 'Existing article body', $enhanced_data['articleBody'] ); } /** @@ -420,11 +402,9 @@ public function test_enhance_does_not_override_existing_keywords() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - 'keywords' => 'Existing, Keywords', - ], + '@type' => 'Article', + 'name' => 'Test Article', + 'keywords' => 'Existing, Keywords', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); @@ -451,10 +431,8 @@ public function test_enhance_returns_unchanged_when_no_enhancements_possible() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'WebPage', - 'name' => 'Test Article', - ], + '@type' => 'WebPage', + 'name' => 'Test Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); @@ -492,64 +470,21 @@ public function test_enhance_respects_disabled_enhancements() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article', - ], + '@type' => 'Article', + 'name' => 'Test Article', ]; $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'description', $enhanced_data[0] ); - $this->assertArrayNotHasKey( 'articleBody', $enhanced_data[0] ); - $this->assertArrayNotHasKey( 'keywords', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'description', $enhanced_data ); + $this->assertArrayNotHasKey( 'articleBody', $enhanced_data ); + $this->assertArrayNotHasKey( 'keywords', $enhanced_data ); // Clean up filters. \remove_filter( 'wpseo_article_enhance_use_excerpt', '__return_false' ); \remove_filter( 'wpseo_article_enhance_article_body', '__return_false' ); \remove_filter( 'wpseo_article_enhance_keywords', '__return_false' ); } - - /** - * Tests enhance() with multiple schema pieces. - * - * @return void - */ - public function test_enhance_processes_multiple_schema_pieces() { - $post = $this->factory()->post->create_and_get( - [ - 'post_title' => 'Test Article', - 'post_type' => 'post', - 'post_status' => 'publish', - 'post_excerpt' => 'Test excerpt.', - ] - ); - - $indexable = \current( $this->get_indexables_for( $post ) ); - - $schema_data = [ - [ - '@type' => 'Article', - 'name' => 'Test Article 1', - ], - [ - '@type' => 'WebPage', - 'name' => 'Test Page', - ], - [ - '@type' => 'NewsArticle', - 'name' => 'Test Article 2', - ], - ]; - $schema_piece = new Schema_Piece( $schema_data, 'mainEntity' ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - - $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'description', $enhanced_data[0] ); - $this->assertArrayNotHasKey( 'description', $enhanced_data[1] ); - $this->assertArrayHasKey( 'description', $enhanced_data[2] ); - } } diff --git a/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php b/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php index 8208204b58b..3020fb2c46c 100644 --- a/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php +++ b/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php @@ -98,18 +98,16 @@ public function test_enhance_adds_job_title_from_user_meta() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Person', - 'name' => 'Test Author', - ], + '@type' => 'Person', + 'name' => 'Test Author', ]; $schema_piece = new Schema_Piece( $schema_data, 'author' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'jobTitle', $enhanced_data[0] ); - $this->assertSame( 'Senior Developer', $enhanced_data[0]['jobTitle'] ); + $this->assertArrayHasKey( 'jobTitle', $enhanced_data ); + $this->assertSame( 'Senior Developer', $enhanced_data['jobTitle'] ); } /** @@ -139,18 +137,16 @@ public function test_enhance_does_not_override_existing_job_title() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Person', - 'name' => 'Test Author', - 'jobTitle' => 'Existing Job Title', - ], + '@type' => 'Person', + 'name' => 'Test Author', + 'jobTitle' => 'Existing Job Title', ]; $schema_piece = new Schema_Piece( $schema_data, 'author' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertSame( 'Existing Job Title', $enhanced_data[0]['jobTitle'] ); + $this->assertSame( 'Existing Job Title', $enhanced_data['jobTitle'] ); } /** @@ -181,17 +177,15 @@ public function test_enhance_does_not_add_job_title_when_empty() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Person', - 'name' => 'Test Author', - ], + '@type' => 'Person', + 'name' => 'Test Author', ]; $schema_piece = new Schema_Piece( $schema_data, 'author' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data ); } /** @@ -219,17 +213,15 @@ public function test_enhance_does_not_add_job_title_when_meta_not_exists() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Person', - 'name' => 'Test Author', - ], + '@type' => 'Person', + 'name' => 'Test Author', ]; $schema_piece = new Schema_Piece( $schema_data, 'author' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data ); } /** @@ -259,18 +251,16 @@ public function test_enhance_trims_whitespace_from_job_title() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Person', - 'name' => 'Test Author', - ], + '@type' => 'Person', + 'name' => 'Test Author', ]; $schema_piece = new Schema_Piece( $schema_data, 'author' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'jobTitle', $enhanced_data[0] ); - $this->assertSame( 'Senior Developer', $enhanced_data[0]['jobTitle'] ); + $this->assertArrayHasKey( 'jobTitle', $enhanced_data ); + $this->assertSame( 'Senior Developer', $enhanced_data['jobTitle'] ); } /** @@ -300,17 +290,15 @@ public function test_enhance_ignores_non_person_types() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Organization', - 'name' => 'Test Org', - ], + '@type' => 'Organization', + 'name' => 'Test Org', ]; $schema_piece = new Schema_Piece( $schema_data, 'publisher' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data ); } /** @@ -343,72 +331,20 @@ public function test_enhance_respects_disabled_enhancement() { $indexable = \current( $this->get_indexables_for( $post ) ); $schema_data = [ - [ - '@type' => 'Person', - 'name' => 'Test Author', - ], + '@type' => 'Person', + 'name' => 'Test Author', ]; $schema_piece = new Schema_Piece( $schema_data, 'author' ); $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[0] ); + $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data ); // Clean up filter. \remove_filter( 'wpseo_person_enhance_person_job_title', '__return_false' ); } - /** - * Tests enhance() processes multiple schema pieces. - * - * @return void - */ - public function test_enhance_processes_multiple_schema_pieces() { - $user_id = $this->factory()->user->create( - [ - 'user_login' => 'testauthor', - 'role' => 'author', - ] - ); - - \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); - - $post = $this->factory()->post->create_and_get( - [ - 'post_title' => 'Test Post', - 'post_type' => 'post', - 'post_status' => 'publish', - 'post_author' => $user_id, - ] - ); - - $indexable = \current( $this->get_indexables_for( $post ) ); - - $schema_data = [ - [ - '@type' => 'Person', - 'name' => 'Test Author 1', - ], - [ - '@type' => 'Organization', - 'name' => 'Test Org', - ], - [ - '@type' => 'Person', - 'name' => 'Test Author 2', - ], - ]; - $schema_piece = new Schema_Piece( $schema_data, 'author' ); - - $result = $this->instance->enhance( $schema_piece, $indexable ); - - $enhanced_data = $result->get_data(); - $this->assertArrayHasKey( 'jobTitle', $enhanced_data[0] ); - $this->assertArrayNotHasKey( 'jobTitle', $enhanced_data[1] ); - $this->assertArrayHasKey( 'jobTitle', $enhanced_data[2] ); - } - /** * Gets all indexable records for a post. * From f59537c80fb26e2699106671037996b819f1593d Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 8 Jan 2026 12:21:15 +0100 Subject: [PATCH 220/319] Fix test --- .../Application/Enhancement/Article_Schema_Enhancer_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php index ab41e31f152..5c203a0a10e 100644 --- a/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php +++ b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php @@ -411,7 +411,7 @@ public function test_enhance_does_not_override_existing_keywords() { $result = $this->instance->enhance( $schema_piece, $indexable ); $enhanced_data = $result->get_data(); - $this->assertSame( 'Existing, Keywords', $enhanced_data[0]['keywords'] ); + $this->assertSame( 'Existing, Keywords', $enhanced_data['keywords'] ); } /** From 355552ff64845c808989d0c5818a951d54a2373f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 12 Jan 2026 14:30:08 +0100 Subject: [PATCH 221/319] Change visibility to allow testing --- .../application/enhancement/person-schema-enhancer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php index 130acbeabb4..81b714ae10a 100644 --- a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php @@ -56,7 +56,7 @@ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Sch * * @return array The enhanced schema data. */ - private function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { + protected function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { try { // Add jobTitle if enabled and not already present. if ( $this->config->is_enhancement_enabled( 'person_job_title' ) && ! isset( $schema_data['jobTitle'] ) ) { From ee28ed491a15c6e2ad6ed568af3ed53fb248fc25 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 12 Jan 2026 14:30:23 +0100 Subject: [PATCH 222/319] Person enhancer test double --- .../Person_Schema_Enhancer_Double.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php diff --git a/tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php b/tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php new file mode 100644 index 00000000000..72a4da43b6a --- /dev/null +++ b/tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php @@ -0,0 +1,24 @@ + $schema_data The schema data to enhance. + * @param Indexable $indexable The indexable object that is the source of the schema piece. + * + * @return array The enhanced schema data. + */ + public function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { + return parent::enhance_schema_piece( $schema_data, $indexable ); + } +} \ No newline at end of file From ce95082d1e7cfbdf9a29e43b04b1f4ec2705679f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 12 Jan 2026 14:30:40 +0100 Subject: [PATCH 223/319] Unit tests for the person piece schema enhancer --- .../Abstract_Person_Schema_Enhancer_Test.php | 43 ++++ .../Enhance_Schema_Piece_Test.php | 239 ++++++++++++++++++ .../Person_Schema_Enhancer/Enhance_Test.php | 87 +++++++ .../Set_Person_Config_Test.php | 53 ++++ 4 files changed, 422 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Abstract_Person_Schema_Enhancer_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Abstract_Person_Schema_Enhancer_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Abstract_Person_Schema_Enhancer_Test.php new file mode 100644 index 00000000000..3c81f675ba8 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Abstract_Person_Schema_Enhancer_Test.php @@ -0,0 +1,43 @@ +instance = new Person_Schema_Enhancer(); + $this->config = Mockery::mock( Person_Config::class ); + $this->instance->set_person_config( $this->config ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php new file mode 100644 index 00000000000..6aef09dda94 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php @@ -0,0 +1,239 @@ +person_schema_enhancer_double = new Person_Schema_Enhancer_Double(); + $this->person_schema_enhancer_double->set_person_config( $this->config ); + } + + /** + * Tests that enhance_schema_piece correctly handles exceptions. + * + * @covers ::enhance_schema_piece + * + * @return void + */ + public function test_enhance_schema_piece_handles_exception() { + $schema_data = [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ]; + + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->author_id = 123; + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'person_job_title' ) + ->andReturn( true ); + + Functions\expect( 'get_user_meta' ) + ->with( $indexable->author_id, 'job_title', true ) + ->andThrow( new Exception( 'Dummy exception' ) ); + + $data = $this->person_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + + $this->assertEquals( $schema_data, $data ); + } + + /** + * Tests the enhance_schema_piece method when jobTitle enhancement is disabled. + * + * @covers ::enhance_schema_piece + * + * @return void + */ + public function test_enhance_schema_piece_job_title_enhancement_disabled() { + $schema_data = [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ]; + + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->author_id = 123; + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'person_job_title' ) + ->andReturn( false ); + + $data = $this->person_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + + $this->assertEquals( $schema_data, $data ); + } + + /** + * Tests the enhance_schema_piece method when jobTitle already exists. + * + * @covers ::enhance_schema_piece + * + * @return void + */ + public function test_enhance_schema_piece_job_title_already_exists() { + $schema_data = [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + 'jobTitle' => 'Existing job title', + ]; + + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->author_id = 123; + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'person_job_title' ) + ->andReturn( true ); + + $data = $this->person_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + + $this->assertEquals( $schema_data, $data ); + } + + /** + * Tests the enhance_schema_piece method for jobTitle enhancement scenarios. + * + * @covers ::enhance_schema_piece + * + * @dataProvider enhance_schema_piece_job_title_data_provider + * + * @param array $schema_data The schema piece data. + * @param array $expected_result The expected enhanced schema data. + * @param string $job_title The job title from user meta. + * + * @return void + */ + public function test_enhance_schema_piece_job_title( array $schema_data, array $expected_result, string $job_title ) { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->author_id = 123; + + $this->config + ->expects( 'is_enhancement_enabled' ) + ->with( 'person_job_title' ) + ->andReturn( true ); + + Functions\expect( 'get_user_meta' ) + ->with( $indexable->author_id, 'job_title', true ) + ->andReturn( $job_title ); + + $data = $this->person_schema_enhancer_double->enhance_schema_piece( $schema_data, $indexable ); + $this->assertSame( $expected_result, $data ); + } + + /** + * Data provider for test_enhance_schema_piece_job_title + * + * @return array> + */ + public function enhance_schema_piece_job_title_data_provider(): array { + return [ + 'with_valid_job_title' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + 'jobTitle' => 'Senior Developer', + ], + 'job_title' => ' Senior Developer ', + ], + 'with_empty_job_title' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ], + 'job_title' => '', + ], + 'with_null_job_title' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ], + 'job_title' => '', + ], + 'with_whitespace_only_job_title' => [ + 'schema_data' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ], + 'expected_result' => [ + '@context' => 'https://schema.org', + '@type' => 'Person', + '@id' => 'http://example.com/#/schema/person/16d528091339c598c98aa254707c9b6b', + 'name' => 'John Doe', + 'description' => 'Test person description', + ], + 'job_title' => ' ', + ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php new file mode 100644 index 00000000000..256ede9e39e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php @@ -0,0 +1,87 @@ +> $schema_data The schema piece data. + * + * @phpcs :enable + * + * @return void + */ + public function test_enhance( $schema_data ) { + $indexable = Mockery::mock( Indexable_Mock::class ); + $indexable->author_id = 123; + + $schema_piece = new Schema_Piece( $schema_data, 'Test' ); + $schema = $this->instance->enhance( $schema_piece, $indexable ); + + $this->assertEquals( $schema_data, $schema->get_data() ); + } + + /** + * Data provider for enhance_schema_piece testing. + * + * @return array> + */ + public function enhance_data_provider(): array { + return [ + 'Type not set' => [ + [ + 'name' => 'John Doe', + 'description' => 'Person description', + ], + ], + 'Wrong simple type' => [ + [ + 'name' => 'John Doe', + 'description' => 'Person description', + '@type' => 'Person', + ], + ], + 'Type not allowed' => [ + [ + 'name' => 'John Doe', + 'description' => 'Person description', + '@type' => 'Article', + ], + ], + 'Wrong array type' => [ + [ + 'name' => 'John Doe', + 'description' => 'Person description', + '@type' => [ true, true, false ], + ], + ], + 'Array type not allowed' => [ + [ + 'name' => 'John Doe', + 'description' => 'Person description', + '@type' => [ 'Article', 'Dummy' ], + ], + ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php new file mode 100644 index 00000000000..ab3cab3797a --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php @@ -0,0 +1,53 @@ +config = Mockery::mock( Person_Config::class ); + $this->instance->set_person_config( $this->config ); + } + + /** + * Tests set_person_config() method. + * + * @covers ::set_person_config + * + * @return void + */ + public function test_set_person_config() { + $config = Mockery::mock( Person_Config::class ); + $instance = new Person_Schema_Enhancer(); + + $instance->set_person_config( $config ); + + $this->assertInstanceOf( Person_Schema_Enhancer::class, $instance ); + } +} From 76aa12d64529a894f6a39759dd17588ea44be107 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 12 Jan 2026 14:41:59 +0100 Subject: [PATCH 224/319] Fix cs --- .../Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php b/tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php index 72a4da43b6a..525a85c735d 100644 --- a/tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php +++ b/tests/Unit/Doubles/Schema_Aggregator/Person_Schema_Enhancer_Double.php @@ -21,4 +21,4 @@ final class Person_Schema_Enhancer_Double extends Person_Schema_Enhancer { public function enhance_schema_piece( array $schema_data, Indexable $indexable ): array { return parent::enhance_schema_piece( $schema_data, $indexable ); } -} \ No newline at end of file +} From feb9e666c8bc3d9c6507b0c226e9f38e43828467 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 12 Jan 2026 15:15:14 +0100 Subject: [PATCH 225/319] Add EDD and events compatibility for the schema aggregator. --- .../third-party/edd-conditional.php | 20 +++++ .../edd-schema-piece-repository.php | 77 ++++++++++++++++++ .../schema-pieces/schema-piece-repository.php | 33 +++++++- .../wordpress-global-state-adapter.php | 81 +++++++++++++++++++ 4 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/conditionals/third-party/edd-conditional.php create mode 100644 src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php create mode 100644 src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php diff --git a/src/conditionals/third-party/edd-conditional.php b/src/conditionals/third-party/edd-conditional.php new file mode 100644 index 00000000000..7bdd8ee5583 --- /dev/null +++ b/src/conditionals/third-party/edd-conditional.php @@ -0,0 +1,20 @@ +edd_conditional = $edd_conditional; + $this->meta = $meta; + } + + /** + * Collect Product schema for EDD downloads. + * + * ## How it Works + * + * Hooks into 'wpseo_schema_product' filter to capture enriched Product schema + * Triggers EDD's schema generation + * Returns the captured Product entity + * + * @param int $post_id Download post ID. + * + * @return array>|null Product schema entity or null if unavailable. + */ + public function collect_download_schema( int $post_id ): ?array { + + if ( ! $this->edd_conditional->is_met() ) { + return null; + } + + try { + $structured_data = new Structured_Data(); + $structured_data->generate_download_data( $post_id ); + $schema_output = $structured_data->get_data(); + + if ( ! \is_array( $schema_output ) ) { + return null; + } + + if ( ! isset( $schema_output[0]['@id'] ) ) { + $schema_output[0]['@id'] = $this->meta->for_current_page()->canonical . '#/schema/edd-product/' . \get_the_ID(); + } + + return $schema_output; + } catch ( Exception $e ) { + return null; + } + } +} diff --git a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index 1973d496284..c6d28ecff5b 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -66,6 +66,20 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { */ private $woo_schema_piece_repository; + /** + * The EDD schema piece repository. + * + * @var Edd_Schema_Piece_Repository + */ + private $edd_schema_piece_repository; + + /** + * The WordPress global state adapter. + * + * @var WordPress_Global_State_Adapter + */ + private $global_state_adapter; + /** * Constructor. * @@ -76,6 +90,8 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { * @param Schema_Enhancement_Factory $enhancement_factory The schema enhancement factory. * @param Indexable_Repository_Factory $indexable_repository_factory The indexable repository factory. * @param Woo_Schema_Piece_Repository $woo_schema_piece_repository The woo schema piece repository. + * @param Edd_Schema_Piece_Repository $edd_schema_piece_repository The EDD schema piece repository. + * @param WordPress_Global_State_Adapter $global_state_adapter The global state adapter. */ public function __construct( Meta_Tags_Context_Memoizer $memoizer, @@ -84,7 +100,9 @@ public function __construct( Aggregator_Config $config, Schema_Enhancement_Factory $enhancement_factory, Indexable_Repository_Factory $indexable_repository_factory, - Woo_Schema_Piece_Repository $woo_schema_piece_repository + Woo_Schema_Piece_Repository $woo_schema_piece_repository, + Edd_Schema_Piece_Repository $edd_schema_piece_repository, + WordPress_Global_State_Adapter $global_state_adapter ) { $this->memoizer = $memoizer; $this->indexable_helper = $indexable_helper; @@ -93,6 +111,8 @@ public function __construct( $this->enhancement_factory = $enhancement_factory; $this->indexable_repository_factory = $indexable_repository_factory; $this->woo_schema_piece_repository = $woo_schema_piece_repository; + $this->edd_schema_piece_repository = $edd_schema_piece_repository; + $this->global_state_adapter = $global_state_adapter; } /** @@ -112,6 +132,8 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { continue; } + + $this->global_state_adapter->set_global_state( $indexable ); $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); $context = $this->memoizer->get( $indexable, $page_type ); $context_array = $this->adapter->meta_tags_context_to_array( $context ); @@ -123,6 +145,12 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec $pieces_data[] = $product_schema; } } + if ( $post_type === 'download' ) { + $download_schema = $this->edd_schema_piece_repository->collect_download_schema( $indexable->object_id ); + if ( $download_schema !== null ) { + $pieces_data[] = $download_schema[0]; + } + } foreach ( $pieces_data as $piece_data ) { $schema_piece = new Schema_Piece( $piece_data, $piece_data['@type'] ); @@ -132,7 +160,10 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec } $schema_pieces[] = $schema_piece; } + + $this->global_state_adapter->reset_global_state(); } + return new Schema_Piece_Collection( $schema_pieces ); } diff --git a/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php b/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php new file mode 100644 index 00000000000..22477e97c80 --- /dev/null +++ b/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php @@ -0,0 +1,81 @@ +queried_object + * + * @var WP_Post|null + */ + private $previous_queried_object; + + /** + * Previous global $wp_query->queried_object_id + * + * @var int|string|null + */ + private $previous_queried_object_id; + + /** + * Set WordPress global state + * + * Helper method to set $post and $wp_query globals based on the given indexable. + * This is critical to ensure that schema pieces relying on global state function correctly. + * + * @param Indexable $indexable The indexable to set the global state for. + * + * @return void + */ + public function set_global_state( Indexable $indexable ): void { + global $post, $wp_query; + $this->previous_post = $post; + $this->previous_queried_object = ( $wp_query->queried_object ?? null ); + $this->previous_queried_object_id = ( $wp_query->queried_object_id ?? null ); + + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- To setup the post we need to do this explicitly. + $post = \get_post( $indexable->object_id ); + $wp_query->queried_object = \get_post( $indexable->object_id ); + $wp_query->queried_object_id = $indexable->object_id; + $wp_query->is_single = true; + $wp_query->is_singular = true; + \setup_postdata( $post ); + } + + /** + * Restore WordPress global state + * + * Helper method to restore $post and $wp_query globals after schema collection. + * This is critical to prevent side effects that could corrupt WordPress's global context. + * + * @return void + */ + public function reset_global_state(): void { + global $post, $wp_query; + + \wp_reset_postdata(); + + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- To reset the post we need to do this explicitly. + $post = $this->previous_post; + + if ( isset( $wp_query ) && \is_object( $wp_query ) ) { + $wp_query->queried_object = $this->previous_queried_object; + $wp_query->queried_object_id = $this->previous_queried_object_id; + $wp_query->is_single = false; + $wp_query->is_singular = false; + } + } +} From f657c14197c4cb700431b9b77936d6afd0d41f3a Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Mon, 12 Jan 2026 15:42:30 +0100 Subject: [PATCH 226/319] Add unit tests for the wordpress global state adapter. --- ...ct_WordPress_Global_State_Adapter_Test.php | 35 ++ ..._State_Adapter_Reset_Global_State_Test.php | 327 ++++++++++++++++++ ...al_State_Adapter_Set_Global_State_Test.php | 253 ++++++++++++++ 3 files changed, 615 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Abstract_WordPress_Global_State_Adapter_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Abstract_WordPress_Global_State_Adapter_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Abstract_WordPress_Global_State_Adapter_Test.php new file mode 100644 index 00000000000..c88082ba89b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Abstract_WordPress_Global_State_Adapter_Test.php @@ -0,0 +1,35 @@ +instance = new WordPress_Global_State_Adapter(); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php new file mode 100644 index 00000000000..fb1b6107a4b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php @@ -0,0 +1,327 @@ +ID = 456; + $post = $initial_post; + $wp_query = (object) [ + 'queried_object' => $initial_post, + 'queried_object_id' => 456, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( $new_post, $post ); + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + + $this->assertSame( $initial_post, $post ); + } + + /** + * Tests that reset_global_state restores the previous queried_object. + * + * @return void + */ + public function test_reset_global_state_restores_previous_queried_object() { + global $post, $wp_query; + + $initial_queried_object = Mockery::mock( WP_Post::class ); + $initial_queried_object->ID = 789; + + $post = null; + $wp_query = (object) [ + 'queried_object' => $initial_queried_object, + 'queried_object_id' => 789, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( $new_post, $wp_query->queried_object ); + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + + $this->assertSame( $initial_queried_object, $wp_query->queried_object ); + } + + /** + * Tests that reset_global_state restores the previous queried_object_id. + * + * @return void + */ + public function test_reset_global_state_restores_previous_queried_object_id() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => 789, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( 123, $wp_query->queried_object_id ); + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + + $this->assertSame( 789, $wp_query->queried_object_id ); + } + + /** + * Tests that reset_global_state resets is_single and is_singular flags. + * + * @return void + */ + public function test_reset_global_state_resets_is_single_and_is_singular() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => null, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertTrue( $wp_query->is_single ); + $this->assertTrue( $wp_query->is_singular ); + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + + $this->assertFalse( $wp_query->is_single ); + $this->assertFalse( $wp_query->is_singular ); + } + + /** + * Tests reset_global_state with null previous values. + * + * @return void + */ + public function test_reset_global_state_with_null_previous_values() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => null, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( $new_post, $post ); + $this->assertSame( $new_post, $wp_query->queried_object ); + $this->assertSame( 123, $wp_query->queried_object_id ); + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + + $this->assertNull( $post ); + $this->assertNull( $wp_query->queried_object ); + $this->assertNull( $wp_query->queried_object_id ); + } + + /** + * Tests reset_global_state with missing wp_query. + * + * @return void + */ + public function test_reset_global_state_with_missing_wp_query() { + global $post, $wp_query; + + $initial_post = Mockery::mock( WP_Post::class ); + $initial_post->ID = 456; + $post = $initial_post; + + $wp_query = (object) []; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $wp_query = null; + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + + $this->assertSame( $initial_post, $post ); + } + + /** + * Tests that reset_global_state calls wp_reset_postdata. + * + * @return void + */ + public function test_reset_global_state_calls_wp_reset_postdata() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => null, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php new file mode 100644 index 00000000000..4607d332f20 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php @@ -0,0 +1,253 @@ +ID = 999; + $post = $initial_post; + $wp_query = (object) [ + 'queried_object' => $initial_post, + 'queried_object_id' => 999, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $mock_post = Mockery::mock( WP_Post::class ); + $mock_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $mock_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $mock_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( $mock_post, $post ); + $this->assertSame( $mock_post, $wp_query->queried_object ); + $this->assertSame( 123, $wp_query->queried_object_id ); + $this->assertTrue( $wp_query->is_single ); + $this->assertTrue( $wp_query->is_singular ); + $this->assertSame( $initial_post, $this->getPropertyValue( $this->instance, 'previous_post' ) ); + $this->assertSame( $initial_post, $this->getPropertyValue( $this->instance, 'previous_queried_object' ) ); + $this->assertSame( 999, $this->getPropertyValue( $this->instance, 'previous_queried_object_id' ) ); + } + + /** + * Tests that set_global_state stores the previous post. + * + * @return void + */ + public function test_set_global_state_stores_previous_post() { + global $post, $wp_query; + + $previous_post = Mockery::mock( WP_Post::class ); + $previous_post->ID = 456; + $post = $previous_post; + + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => null, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( $previous_post, $this->getPropertyValue( $this->instance, 'previous_post' ) ); + } + + /** + * Tests that set_global_state stores the previous queried_object. + * + * @return void + */ + public function test_set_global_state_stores_previous_queried_object() { + global $post, $wp_query; + + $previous_queried_object = Mockery::mock( WP_Post::class ); + $previous_queried_object->ID = 789; + + $post = null; + $wp_query = (object) [ + 'queried_object' => $previous_queried_object, + 'queried_object_id' => 789, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( $previous_queried_object, $this->getPropertyValue( $this->instance, 'previous_queried_object' ) ); + } + + /** + * Tests that set_global_state stores the previous queried_object_id. + * + * @return void + */ + public function test_set_global_state_stores_previous_queried_object_id() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => 456, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( 456, $this->getPropertyValue( $this->instance, 'previous_queried_object_id' ) ); + } + + /** + * Tests set_global_state with null previous values. + * + * @return void + */ + public function test_set_global_state_with_null_previous_values() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => null, + 'is_single' => false, + 'is_singular' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_post' ) ); + $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_queried_object' ) ); + $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_queried_object_id' ) ); + } + + /** + * Tests set_global_state with missing wp_query properties. + * + * @return void + */ + public function test_set_global_state_with_missing_wp_query_properties() { + global $post, $wp_query; + + $post = null; + + $wp_query = new stdClass(); + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_post' ) ); + $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_queried_object' ) ); + $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_queried_object_id' ) ); + } +} From 8d3c725b15b91eadc9bb51592979dbfa82b29116 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 13 Jan 2026 16:43:47 +0100 Subject: [PATCH 227/319] Implement feedbacks --- .../Article_Schema_Enhancer/Enhance_Test.php | 8 +------- .../Set_Article_Config_Test.php | 4 +--- .../Enhance_Schema_Piece_Test.php | 10 ++++------ .../Person_Schema_Enhancer/Enhance_Test.php | 8 +++----- .../Person_Schema_Enhancer/Set_Person_Config_Test.php | 4 +--- 5 files changed, 10 insertions(+), 24 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php index 5b333414b1a..92fe770e300 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Enhance_Test.php @@ -11,24 +11,18 @@ * Tests the Article_Schema_Enhancer class enhance_schema_piece method. * * @group schema-aggregator - * - * @coversDefaultClass \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Article_Schema_Enhancer */ final class Enhance_Test extends Abstract_Article_Schema_Enhancer_Test { /** * Test. * - * @covers ::enhance + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Article_Schema_Enhancer::enhance * * @dataProvider enhance_data_provider * - * @phpcs :disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification - * * @param array> $schema_data The schema piece data. * - * @phpcs :enable - * * @return void */ public function test_enhance( $schema_data ) { diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php index e0ee28447da..13a4b387338 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer/Set_Article_Config_Test.php @@ -11,8 +11,6 @@ * Tests the Article_Schema_Enhancer class. * * @group schema-aggregator - * - * @coversDefaultClass \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Article_Schema_Enhancer */ final class Set_Article_Config_Test extends Abstract_Article_Schema_Enhancer_Test { @@ -38,7 +36,7 @@ protected function set_up() { /** * Tests set_article_config() method. * - * @covers ::set_article_config + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Article_Schema_Enhancer::set_article_config * * @return void */ diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php index 6aef09dda94..4526674145d 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Schema_Piece_Test.php @@ -13,8 +13,6 @@ * Tests the Person_Schema_Enhancer class enhance method. * * @group schema-aggregator - * - * @coversDefaultClass \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer */ final class Enhance_Schema_Piece_Test extends Abstract_Person_Schema_Enhancer_Test { @@ -39,7 +37,7 @@ protected function set_up() { /** * Tests that enhance_schema_piece correctly handles exceptions. * - * @covers ::enhance_schema_piece + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer::enhance_schema_piece * * @return void */ @@ -72,7 +70,7 @@ public function test_enhance_schema_piece_handles_exception() { /** * Tests the enhance_schema_piece method when jobTitle enhancement is disabled. * - * @covers ::enhance_schema_piece + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer::enhance_schema_piece * * @return void */ @@ -101,7 +99,7 @@ public function test_enhance_schema_piece_job_title_enhancement_disabled() { /** * Tests the enhance_schema_piece method when jobTitle already exists. * - * @covers ::enhance_schema_piece + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer::enhance_schema_piece * * @return void */ @@ -131,7 +129,7 @@ public function test_enhance_schema_piece_job_title_already_exists() { /** * Tests the enhance_schema_piece method for jobTitle enhancement scenarios. * - * @covers ::enhance_schema_piece + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer::enhance_schema_piece * * @dataProvider enhance_schema_piece_job_title_data_provider * diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php index 256ede9e39e..fa4134632a4 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php @@ -11,23 +11,21 @@ * Tests the Person_Schema_Enhancer class enhance_schema_piece method. * * @group schema-aggregator - * - * @coversDefaultClass \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer */ final class Enhance_Test extends Abstract_Person_Schema_Enhancer_Test { /** * Test. * - * @covers ::enhance + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer::enhance * * @dataProvider enhance_data_provider * - * @phpcs :disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification + * @phpcs :disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification * * @param array> $schema_data The schema piece data. * - * @phpcs :enable + * @phpcs :enable * * @return void */ diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php index ab3cab3797a..3a705e13ec2 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Set_Person_Config_Test.php @@ -11,8 +11,6 @@ * Tests the Person_Schema_Enhancer class. * * @group schema-aggregator - * - * @coversDefaultClass \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer */ final class Set_Person_Config_Test extends Abstract_Person_Schema_Enhancer_Test { @@ -38,7 +36,7 @@ protected function set_up() { /** * Tests set_person_config() method. * - * @covers ::set_person_config + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Person_Schema_Enhancer::set_person_config * * @return void */ From 3dd721829f7566be9629f54b3afba0b6cf19580f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 13 Jan 2026 16:52:27 +0100 Subject: [PATCH 228/319] Remove unused annotation --- .../Enhancement/Person_Schema_Enhancer/Enhance_Test.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php index fa4134632a4..e21780022bd 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer/Enhance_Test.php @@ -21,12 +21,8 @@ final class Enhance_Test extends Abstract_Person_Schema_Enhancer_Test { * * @dataProvider enhance_data_provider * - * @phpcs :disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification - * * @param array> $schema_data The schema piece data. * - * @phpcs :enable - * * @return void */ public function test_enhance( $schema_data ) { From c8fa0e9855486ae7fd8ce4938a1503a52dd79beb Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 14 Jan 2026 12:12:06 +0100 Subject: [PATCH 229/319] Add unit test for generate_array_of_size function in Config_Get_Expiration_Test --- .../Config/Config_Get_Expiration_Test.php | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php index f3023cf446b..2b2e691f32b 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php @@ -131,13 +131,22 @@ public static function get_expiration_data() { * @return array An array with approximately the specified serialized size. */ private static function generate_array_of_size( $target_bytes ) { - $data = []; - $key = 0; + if ( $target_bytes === 0 ) { + return []; + } + + // Calculate approximate size per entry by creating a sample. + $sample_key = 'key_0'; + $sample_value = \str_repeat( 'x', 100 ); + $sample_array = [ $sample_key => $sample_value ]; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- This is just a test. - $length = \strlen( \serialize( $data ) ); - while ( $length < $target_bytes ) { - $data[ 'key_' . $key ] = \str_repeat( 'x', 100 ); - ++$key; + $bytes_per_entry = \strlen( \serialize( $sample_array ) ); + + $estimated_entries = (int) \ceil( $target_bytes / $bytes_per_entry ); + + $data = []; + for ( $i = 0; $i < $estimated_entries; $i++ ) { + $data[ 'key_' . $i ] = \str_repeat( 'x', 100 ); } return $data; From 8361c1000f760219a1430feb094cb2326da3fbb6 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 14 Jan 2026 14:25:59 +0100 Subject: [PATCH 230/319] Add test to cover the exception branch --- .../Config/Config_Get_Expiration_Test.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php index 2b2e691f32b..022b5a5bb0a 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php @@ -123,6 +123,21 @@ public static function get_expiration_data() { ]; } + /** + * Tests that an exception during serialization results in the default expiration being returned. + * + * @return void + */ + public function test_get_expiration_handles_exception() { + $unserializable_data = static function () { + return 'test'; + }; + + $result = $this->instance->get_expiration( [ $unserializable_data ] ); + + $this->assertEquals( 3600, $result ); + } + /** * Helper method to generate an array of approximately the specified serialized size. * From 042fa10ffd9160f1f735b700f7dfff8ef70cd3aa Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 14 Jan 2026 14:26:50 +0100 Subject: [PATCH 231/319] This shouldn't be needed as serialize() either returns a string or raises an exception --- src/schema-aggregator/infrastructure/config.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index 97a75bbf3ed..ee97b1d13de 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -87,10 +87,6 @@ public function get_expiration( array $data ): int { try { $serialized = \serialize( $data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- Needed for size calculation. - if ( $serialized === false ) { - return self::DEFAULT_CACHE_TTL; - } - $size = \strlen( $serialized ); // Large payloads: cache longer. From 7bdd8fba81dac6779dab4d43873347a1b45b9059 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 15 Jan 2026 10:49:09 +0100 Subject: [PATCH 232/319] Add cover annotation for private method --- ...Indexables_Update_Listener_Integration_Reset_Cache_Test.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php index 0af5b5c789d..ab416c75e44 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php @@ -12,7 +12,8 @@ * @group Indexables_Update_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\Indexables_Update_Listener_Integration::reset_cache - * + * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\Abstract_Cache_Listener_Integration::get_page_number + * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded */ final class Indexables_Update_Listener_Integration_Reset_Cache_Test extends Abstract_Indexables_Update_Listener_Integration_Test { From 16d2fc0b8be144e0e8a975f9cd55e1be85916c18 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 15 Jan 2026 10:49:19 +0100 Subject: [PATCH 233/319] Add constructor test --- ...stract_Cache_Listener_Integration_Test.php | 61 +++++++++++++ ..._Listener_Integration_Constructor_Test.php | 88 +++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Abstract_Cache_Listener_Integration_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Abstract_Cache_Listener_Integration_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Abstract_Cache_Listener_Integration_Test.php new file mode 100644 index 00000000000..4d84ea18814 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Abstract_Cache_Listener_Integration_Test.php @@ -0,0 +1,61 @@ +indexable_repository = Mockery::mock( Indexable_Repository::class ); + $this->config = Mockery::mock( Config::class ); + $this->manager = Mockery::mock( Manager::class ); + $this->xml_manager = Mockery::mock( Xml_Manager::class ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php new file mode 100644 index 00000000000..74ef135c60d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php @@ -0,0 +1,88 @@ +instance = new class( + $this->indexable_repository, + $this->config, + $this->manager, + $this->xml_manager + ) extends Abstract_Cache_Listener_Integration { + + /** + * Registers hooks for the integration. + * + * @return void + */ + public function register_hooks() { + // Empty implementation for testing. + } + + /** + * Gets the conditionals for the integration. + * + * @return array The conditionals. + */ + public static function get_conditionals(): array { + return []; + } + }; + } + + /** + * Tests if the constructor sets properties correctly. + * + * @return void + */ + public function test_constructor() { + $this->assertInstanceOf( + Indexable_Repository::class, + $this->getPropertyValue( $this->instance, 'indexable_repository' ) + ); + $this->assertInstanceOf( + Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + $this->assertInstanceOf( + Manager::class, + $this->getPropertyValue( $this->instance, 'manager' ) + ); + $this->assertInstanceOf( + Xml_Manager::class, + $this->getPropertyValue( $this->instance, 'xml_manager' ) + ); + } +} From 0b7c7ec545da649955d7ddb5bb33f852f20e67bc Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 15 Jan 2026 11:28:55 +0100 Subject: [PATCH 234/319] Use $post_id instead of the `get_the_ID()` function. --- .../schema-pieces/edd-schema-piece-repository.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php index c130a508a9f..b9100edeb73 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php @@ -40,9 +40,6 @@ public function __construct( EDD_Conditional $edd_conditional, Meta_Surface $met /** * Collect Product schema for EDD downloads. * - * ## How it Works - * - * Hooks into 'wpseo_schema_product' filter to capture enriched Product schema * Triggers EDD's schema generation * Returns the captured Product entity * @@ -66,7 +63,7 @@ public function collect_download_schema( int $post_id ): ?array { } if ( ! isset( $schema_output[0]['@id'] ) ) { - $schema_output[0]['@id'] = $this->meta->for_current_page()->canonical . '#/schema/edd-product/' . \get_the_ID(); + $schema_output[0]['@id'] = $this->meta->for_current_page()->canonical . '#/schema/edd-product/' . $post_id; } return $schema_output; From 76f44977ab1880aff98f0afd2ecdec593cbe586b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 15 Jan 2026 12:07:00 +0100 Subject: [PATCH 235/319] Add tests to cover the exception case --- .../Application/Cache/Get_Test.php | 18 ++++++++++++++ .../Application/Cache/Invalidate_All_Test.php | 24 +++++++++++++++++++ .../Application/Cache/Set_Test.php | 18 ++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php index 5e7025c08f5..f6d607f77d1 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php @@ -182,4 +182,22 @@ public static function get_cache_data_provider() { 'cached_data' => [ 'data100' ], ]; } + + /** + * Tests get() handles exceptions gracefully and returns null. + * + * @return void + */ + public function test_get_handles_exceptions_gracefully() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->andThrow( new \Exception( 'Simulated exception' ) ); + + $result = $this->instance->get( 1, 10 ); + + $this->assertNull( $result ); + } } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php index 5f8434c6ec0..fa7b75dba98 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php @@ -80,4 +80,28 @@ public function test_invalidate_all_returns_false_when_query_fails() { $this->assertFalse( $result ); } + + /** + * Tests invalidate_all() handles exceptions gracefully. + * + * @return void + */ + public function test_invalidate_all_handles_exception_gracefully() { + global $wpdb; + $wpdb = Mockery::mock( 'wpdb' ); + $wpdb->options = 'wp_options'; + + $wpdb->expects( 'prepare' ) + ->once() + ->andReturn( 'PREPARED_QUERY' ); + + $wpdb->expects( 'query' ) + ->once() + ->with( 'PREPARED_QUERY' ) + ->andThrow( new \Exception( 'Database error' ) ); + + $result = $this->instance->invalidate_all(); + + $this->assertFalse( $result ); + } } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php index 5c35ac3f199..16737b115c1 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php @@ -135,4 +135,22 @@ public static function set_cache_data_provider() { 'expected_key' => 'yoast_schema_aggregator_page_2_per_50_v1', ]; } + + /** + * Tests set() handles exceptions gracefully. + * + * @return void + */ + public function test_set_handles_exception_gracefully() { + $data = []; + + $this->config->expects( 'get_expiration' ) + ->once() + ->with( $data ) + ->andThrow( new \Exception( 'Test exception' ) ); + + $result = $this->instance->set( 1, 10, $data ); + + $this->assertFalse( $result ); + } } From 9be9fcf0f5acae50345dfa5ae2f07f468bbfec62 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 15 Jan 2026 14:17:40 +0100 Subject: [PATCH 236/319] Fix tests --- .../Application/Cache/Get_Test.php | 33 ++++++++++--------- .../Application/Cache/Invalidate_All_Test.php | 3 +- .../Application/Cache/Invalidate_Test.php | 10 +++--- .../Application/Cache/Set_Test.php | 19 ++++++----- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php index f6d607f77d1..2a1fa6d24dc 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Get_Test.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Cache; use Brain\Monkey; +use Exception; use Generator; /** @@ -24,7 +25,7 @@ final class Get_Test extends Abstract_Manager_Test { public function test_get_returns_null_when_cache_disabled() { $this->config->expects( 'cache_enabled' )->once()->andReturn( false ); - $result = $this->instance->get( 1, 10 ); + $result = $this->instance->get( 'post', 1, 10 ); $this->assertNull( $result ); } @@ -42,7 +43,7 @@ public function test_get_returns_null_when_cache_disabled() { public function test_get_returns_null_with_invalid_parameters( $page, $per_page ) { $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); - $result = $this->instance->get( $page, $per_page ); + $result = $this->instance->get( 'post', $page, $per_page ); $this->assertNull( $result ); } @@ -81,10 +82,10 @@ public function test_get_returns_null_on_cache_miss() { Monkey\Functions\expect( 'get_transient' ) ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->with( 'yoast_schema_aggregator_page_1_per_10_type_post_v1' ) ->andReturn( false ); - $result = $this->instance->get( 1, 10 ); + $result = $this->instance->get( 'post', 1, 10 ); $this->assertNull( $result ); } @@ -99,15 +100,15 @@ public function test_get_returns_null_and_deletes_corrupted_cache() { Monkey\Functions\expect( 'get_transient' ) ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->with( 'yoast_schema_aggregator_page_1_per_10_type_post_v1' ) ->andReturn( 'invalid_data' ); Monkey\Functions\expect( 'delete_transient' ) ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->with( 'yoast_schema_aggregator_page_1_per_10_type_post_v1' ) ->andReturn( true ); - $result = $this->instance->get( 1, 10 ); + $result = $this->instance->get( 'post', 1, 10 ); $this->assertNull( $result ); } @@ -124,10 +125,10 @@ public function test_get_returns_cached_data() { Monkey\Functions\expect( 'get_transient' ) ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->with( 'yoast_schema_aggregator_page_1_per_10_type_post_v1' ) ->andReturn( $cached_data ); - $result = $this->instance->get( 1, 10 ); + $result = $this->instance->get( 'post', 1, 10 ); $this->assertSame( $cached_data, $result ); } @@ -152,7 +153,7 @@ public function test_get_with_various_parameters( $page, $per_page, $expected_ke ->with( $expected_key ) ->andReturn( $cached_data ); - $result = $this->instance->get( $page, $per_page ); + $result = $this->instance->get( 'post', $page, $per_page ); $this->assertSame( $cached_data, $result ); } @@ -166,19 +167,19 @@ public static function get_cache_data_provider() { yield 'First page, 10 items' => [ 'page' => 1, 'per_page' => 10, - 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', + 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_type_post_v1', 'cached_data' => [ 'data1' ], ]; yield 'Second page, 20 items' => [ 'page' => 2, 'per_page' => 20, - 'expected_key' => 'yoast_schema_aggregator_page_2_per_20_v1', + 'expected_key' => 'yoast_schema_aggregator_page_2_per_20_type_post_v1', 'cached_data' => [ 'data2', 'data3' ], ]; yield 'Large page number' => [ 'page' => 100, 'per_page' => 50, - 'expected_key' => 'yoast_schema_aggregator_page_100_per_50_v1', + 'expected_key' => 'yoast_schema_aggregator_page_100_per_50_type_post_v1', 'cached_data' => [ 'data100' ], ]; } @@ -193,10 +194,10 @@ public function test_get_handles_exceptions_gracefully() { Monkey\Functions\expect( 'get_transient' ) ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) - ->andThrow( new \Exception( 'Simulated exception' ) ); + ->with( 'yoast_schema_aggregator_page_1_per_10_type_post_v1' ) + ->andThrow( new Exception( 'Simulated exception' ) ); - $result = $this->instance->get( 1, 10 ); + $result = $this->instance->get( 'post', 1, 10 ); $this->assertNull( $result ); } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php index fa7b75dba98..93efb8d706a 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php @@ -3,6 +3,7 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Cache; +use Exception; use Mockery; /** @@ -98,7 +99,7 @@ public function test_invalidate_all_handles_exception_gracefully() { $wpdb->expects( 'query' ) ->once() ->with( 'PREPARED_QUERY' ) - ->andThrow( new \Exception( 'Database error' ) ); + ->andThrow( new Exception( 'Database error' ) ); $result = $this->instance->invalidate_all(); diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php index 1dd30751995..b9742f798ce 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php @@ -24,10 +24,10 @@ final class Invalidate_Test extends Abstract_Manager_Test { public function test_invalidate_deletes_specific_entry() { Monkey\Functions\expect( 'delete_transient' ) ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1' ) + ->with( 'yoast_schema_aggregator_page_1_per_10_type_post_v1' ) ->andReturn( true ); - $result = $this->instance->invalidate( 1, 10 ); + $result = $this->instance->invalidate( 'post', 1, 10 ); $this->assertTrue( $result ); } @@ -56,7 +56,7 @@ public function test_invalidate_clears_all_per_page_variations_for_page() { ->with( 'PREPARED_QUERY' ) ->andReturn( 5 ); - $result = $this->instance->invalidate( 1, null ); + $result = $this->instance->invalidate( 'post', 1, null ); $this->assertTrue( $result ); } @@ -70,7 +70,7 @@ public function test_invalidate_returns_false_when_wpdb_not_available() { global $wpdb; $wpdb = null; - $result = $this->instance->invalidate( 1, null ); + $result = $this->instance->invalidate( 'post', 1, null ); $this->assertFalse( $result ); } @@ -94,7 +94,7 @@ public function test_invalidate_with_no_parameters_calls_invalidate_all() { ->with( 'PREPARED_QUERY' ) ->andReturn( 10 ); - $result = $this->instance->invalidate( null, null ); + $result = $this->instance->invalidate( 'post', null, null ); $this->assertTrue( $result ); } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php index 16737b115c1..e0e138eb143 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Cache; use Brain\Monkey; +use Exception; use Generator; /** @@ -28,7 +29,7 @@ final class Set_Test extends Abstract_Manager_Test { * @return void */ public function test_set_returns_false_with_invalid_parameters( $page, $per_page, $data ) { - $result = $this->instance->set( $page, $per_page, $data ); + $result = $this->instance->set( 'post', $page, $per_page, $data ); $this->assertFalse( $result ); } @@ -77,10 +78,10 @@ public function test_set_caches_data_successfully() { Monkey\Functions\expect( 'set_transient' ) ->once() - ->with( 'yoast_schema_aggregator_page_1_per_10_v1', $data, $expiration ) + ->with( 'yoast_schema_aggregator_page_1_per_10_type_post_v1', $data, $expiration ) ->andReturn( true ); - $result = $this->instance->set( 1, 10, $data ); + $result = $this->instance->set( 'post', 1, 10, $data ); $this->assertTrue( $result ); } @@ -109,7 +110,7 @@ public function test_set_with_various_parameters( $page, $per_page, $data, $expi ->with( $expected_key, $data, $expiration ) ->andReturn( true ); - $result = $this->instance->set( $page, $per_page, $data ); + $result = $this->instance->set( 'post', $page, $per_page, $data ); $this->assertTrue( $result ); } @@ -125,14 +126,14 @@ public static function set_cache_data_provider() { 'per_page' => 10, 'data' => [ 'small' ], 'expiration' => 1800, - 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_v1', + 'expected_key' => 'yoast_schema_aggregator_page_1_per_10_type_post_v1', ]; yield 'Large data, long expiration' => [ 'page' => 2, 'per_page' => 50, 'data' => \array_fill( 0, 100, 'large_data' ), 'expiration' => 21600, - 'expected_key' => 'yoast_schema_aggregator_page_2_per_50_v1', + 'expected_key' => 'yoast_schema_aggregator_page_2_per_50_type_post_v1', ]; } @@ -142,14 +143,14 @@ public static function set_cache_data_provider() { * @return void */ public function test_set_handles_exception_gracefully() { - $data = []; + $data = [ 'test_data' ]; $this->config->expects( 'get_expiration' ) ->once() ->with( $data ) - ->andThrow( new \Exception( 'Test exception' ) ); + ->andThrow( new Exception( 'Test exception' ) ); - $result = $this->instance->set( 1, 10, $data ); + $result = $this->instance->set( 'post', 1, 10, $data ); $this->assertFalse( $result ); } From b497caf5fa52e4db011ed21971f2e7bbca93a983 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 15 Jan 2026 16:18:17 +0100 Subject: [PATCH 237/319] Add tests covering exceptions --- .../Cache/Xml_Manager/Get_Test.php | 19 +++++++++++++++++++ .../Cache/Xml_Manager/Set_Test.php | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php index 2096d8ae7f1..4ca9e70fa5a 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Get_Test.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Cache\Xml_Manager; use Brain\Monkey; +use Exception; use Generator; /** @@ -155,4 +156,22 @@ public static function xml_data_provider() { 'xml_data' => \str_repeat( 'content', 100 ), ]; } + + /** + * Tests get() handles exceptions gracefully and returns null. + * + * @return void + */ + public function test_get_handles_exception_gracefully() { + $this->config->expects( 'cache_enabled' )->once()->andReturn( true ); + + Monkey\Functions\expect( 'get_transient' ) + ->once() + ->with( 'yoast_schema_aggregator_xml_sitemap_v1' ) + ->andThrow( new Exception( 'Simulated exception' ) ); + + $result = $this->instance->get(); + + $this->assertNull( $result ); + } } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php index 4c207d87e5f..bae7fc1b622 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Application\Cache\Xml_Manager; use Brain\Monkey; +use Exception; use Generator; /** @@ -118,4 +119,22 @@ public static function set_data_provider() { 'expected' => true, ]; } + + /** + * Tests set() handles exceptions gracefully. + * + * @return void + */ + public function test_set_handles_exception_gracefully() { + $data = 'test'; + + $this->config->expects( 'get_expiration' ) + ->once() + ->with( [ $data ] ) + ->andThrow( new Exception( 'Test exception' ) ); + + $result = $this->instance->set( $data ); + + $this->assertFalse( $result ); + } } From 99997a52d1d89cac967f0a0f83a1244fa8ced564 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Fri, 16 Jan 2026 14:14:49 +0100 Subject: [PATCH 238/319] Abstract external schema piece repos --- ...rnal-schema-piece-repository-interface.php | 29 +++++ .../edd-schema-piece-repository.php | 42 ++++--- .../schema-pieces/schema-piece-repository.php | 81 ++++++------- .../woo-schema-piece-repository.php | 40 ++++--- ...tract_Edd_Schema_Piece_Repository_Test.php | 58 +++++++++ ...d_Schema_Piece_Repository_Collect_Test.php | 32 +++++ ..._Schema_Piece_Repository_Supports_Test.php | 112 ++++++++++++++++++ ...tract_Woo_Schema_Piece_Repository_Test.php | 48 ++++++++ ...o_Schema_Piece_Repository_Collect_Test.php | 76 ++++++++++++ ..._Schema_Piece_Repository_Supports_Test.php | 112 ++++++++++++++++++ 10 files changed, 561 insertions(+), 69 deletions(-) create mode 100644 src/schema-aggregator/domain/external-schema-piece-repository-interface.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Collect_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Supports_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Supports_Test.php diff --git a/src/schema-aggregator/domain/external-schema-piece-repository-interface.php b/src/schema-aggregator/domain/external-schema-piece-repository-interface.php new file mode 100644 index 00000000000..cb38ff84b94 --- /dev/null +++ b/src/schema-aggregator/domain/external-schema-piece-repository-interface.php @@ -0,0 +1,29 @@ +> The schema pieces (always an array, may be empty). + */ + public function collect( int $post_id ): array; +} diff --git a/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php index b9100edeb73..af3915f2836 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php @@ -5,12 +5,13 @@ use EDD\Structured_Data; use Exception; use Yoast\WP\SEO\Conditionals\Third_Party\EDD_Conditional; +use Yoast\WP\SEO\Schema_Aggregator\Domain\External_Schema_Piece_Repository_Interface; use Yoast\WP\SEO\Surfaces\Meta_Surface; /** - * The Schema_Piece repository. + * The EDD schema piece repository. */ -class Edd_Schema_Piece_Repository { +class Edd_Schema_Piece_Repository implements External_Schema_Piece_Repository_Interface { /** * The EDD Conditional. @@ -38,19 +39,29 @@ public function __construct( EDD_Conditional $edd_conditional, Meta_Surface $met } /** - * Collect Product schema for EDD downloads. + * Checks if this repository supports the given post type. * - * Triggers EDD's schema generation - * Returns the captured Product entity + * @param string $post_type The post type to check. + * + * @return bool True if this repository can provide schema for the post type. + */ + public function supports( string $post_type ): bool { + return $this->edd_conditional->is_met() && $post_type === 'download'; + } + + /** + * Collects download schema pieces for EDD downloads. + * + * Triggers EDD's schema generation. + * Returns the captured Product entity. * * @param int $post_id Download post ID. * - * @return array>|null Product schema entity or null if unavailable. + * @return array> Product schema pieces (empty array if unavailable). */ - public function collect_download_schema( int $post_id ): ?array { - + public function collect( int $post_id ): array { if ( ! $this->edd_conditional->is_met() ) { - return null; + return []; } try { @@ -58,17 +69,20 @@ public function collect_download_schema( int $post_id ): ?array { $structured_data->generate_download_data( $post_id ); $schema_output = $structured_data->get_data(); - if ( ! \is_array( $schema_output ) ) { - return null; + if ( ! \is_array( $schema_output ) || empty( $schema_output ) ) { + return []; } - if ( ! isset( $schema_output[0]['@id'] ) ) { - $schema_output[0]['@id'] = $this->meta->for_current_page()->canonical . '#/schema/edd-product/' . $post_id; + // Ensure each piece has an @id. + foreach ( $schema_output as $key => $piece ) { + if ( ! isset( $piece['@id'] ) ) { + $schema_output[ $key ]['@id'] = $this->meta->for_current_page()->canonical . '#/schema/edd-product/' . $post_id; + } } return $schema_output; } catch ( Exception $e ) { - return null; + return []; } } } diff --git a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index c6d28ecff5b..0143938ce61 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -5,6 +5,7 @@ use Yoast\WP\SEO\Helpers\Indexable_Helper; use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer; use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Schema_Enhancement_Factory; +use Yoast\WP\SEO\Schema_Aggregator\Domain\External_Schema_Piece_Repository_Interface; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface; @@ -60,38 +61,30 @@ class Schema_Piece_Repository implements Schema_Piece_Repository_Interface { private $indexable_repository_factory; /** - * The woo schema piece repository. + * The WordPress global state adapter. * - * @var Woo_Schema_Piece_Repository + * @var WordPress_Global_State_Adapter */ - private $woo_schema_piece_repository; + private $global_state_adapter; /** - * The EDD schema piece repository. + * External schema piece repositories. * - * @var Edd_Schema_Piece_Repository + * @var array */ - private $edd_schema_piece_repository; - - /** - * The WordPress global state adapter. - * - * @var WordPress_Global_State_Adapter - */ - private $global_state_adapter; + private $external_repositories; /** * Constructor. * - * @param Meta_Tags_Context_Memoizer $memoizer The meta tags context memoizer. - * @param Indexable_Helper $indexable_helper The indexable helper. - * @param Meta_Tags_Context_Memoizer_Adapter $adapter The adapter factory. - * @param Aggregator_Config $config The configuration provider. - * @param Schema_Enhancement_Factory $enhancement_factory The schema enhancement factory. - * @param Indexable_Repository_Factory $indexable_repository_factory The indexable repository factory. - * @param Woo_Schema_Piece_Repository $woo_schema_piece_repository The woo schema piece repository. - * @param Edd_Schema_Piece_Repository $edd_schema_piece_repository The EDD schema piece repository. - * @param WordPress_Global_State_Adapter $global_state_adapter The global state adapter. + * @param Meta_Tags_Context_Memoizer $memoizer The meta tags context memoizer. + * @param Indexable_Helper $indexable_helper The indexable helper. + * @param Meta_Tags_Context_Memoizer_Adapter $adapter The adapter factory. + * @param Aggregator_Config $config The configuration provider. + * @param Schema_Enhancement_Factory $enhancement_factory The schema enhancement factory. + * @param Indexable_Repository_Factory $indexable_repository_factory The indexable repository factory. + * @param WordPress_Global_State_Adapter $global_state_adapter The global state adapter. + * @param External_Schema_Piece_Repository_Interface ...$external_repositories The external schema piece repositories. */ public function __construct( Meta_Tags_Context_Memoizer $memoizer, @@ -100,9 +93,8 @@ public function __construct( Aggregator_Config $config, Schema_Enhancement_Factory $enhancement_factory, Indexable_Repository_Factory $indexable_repository_factory, - Woo_Schema_Piece_Repository $woo_schema_piece_repository, - Edd_Schema_Piece_Repository $edd_schema_piece_repository, - WordPress_Global_State_Adapter $global_state_adapter + WordPress_Global_State_Adapter $global_state_adapter, + External_Schema_Piece_Repository_Interface ...$external_repositories ) { $this->memoizer = $memoizer; $this->indexable_helper = $indexable_helper; @@ -110,9 +102,8 @@ public function __construct( $this->config = $config; $this->enhancement_factory = $enhancement_factory; $this->indexable_repository_factory = $indexable_repository_factory; - $this->woo_schema_piece_repository = $woo_schema_piece_repository; - $this->edd_schema_piece_repository = $edd_schema_piece_repository; $this->global_state_adapter = $global_state_adapter; + $this->external_repositories = $external_repositories; } /** @@ -128,6 +119,7 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec $indexable_repository = $this->indexable_repository_factory->get_repository( $this->indexable_helper->should_index_indexables() ); $indexables = $indexable_repository->get( $page, $page_size, $post_type ); $schema_pieces = []; + foreach ( $indexables as $indexable ) { if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { continue; @@ -139,18 +131,8 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec $context_array = $this->adapter->meta_tags_context_to_array( $context ); $pieces_data = $context_array['@graph']; - if ( $post_type === 'product' ) { - $product_schema = $this->woo_schema_piece_repository->collect_product_schema( $indexable->object_id ); - if ( $product_schema !== null ) { - $pieces_data[] = $product_schema; - } - } - if ( $post_type === 'download' ) { - $download_schema = $this->edd_schema_piece_repository->collect_download_schema( $indexable->object_id ); - if ( $download_schema !== null ) { - $pieces_data[] = $download_schema[0]; - } - } + // Collect external schema pieces from all supporting repositories. + $pieces_data = $this->collect_external_schema( $pieces_data, $post_type, $indexable->object_id ); foreach ( $pieces_data as $piece_data ) { $schema_piece = new Schema_Piece( $piece_data, $piece_data['@type'] ); @@ -167,6 +149,26 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec return new Schema_Piece_Collection( $schema_pieces ); } + /** + * Collects external schema pieces from all supporting repositories. + * + * @param array> $pieces_data The existing schema pieces. + * @param string $post_type The post type. + * @param int $post_id The post ID. + * + * @return array> The schema pieces with external pieces added. + */ + private function collect_external_schema( array $pieces_data, string $post_type, int $post_id ): array { + foreach ( $this->external_repositories as $repository ) { + if ( $repository->supports( $post_type ) ) { + $external_pieces = $repository->collect( $post_id ); + $pieces_data = \array_merge( $pieces_data, $external_pieces ); + } + } + + return $pieces_data; + } + /** * All schema types present in the schema piece. * @@ -186,7 +188,6 @@ private function get_all_schema_types( array $graph ): array { continue; } $schema_types[ $value ] = $value; - } } } diff --git a/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php index ccf049bc199..c9d6e4b8ac6 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/woo-schema-piece-repository.php @@ -2,13 +2,15 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces; +use Exception; use WC_Structured_Data; use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional; +use Yoast\WP\SEO\Schema_Aggregator\Domain\External_Schema_Piece_Repository_Interface; /** - * The Schema_Piece repository. + * The WooCommerce schema piece repository. */ -class Woo_Schema_Piece_Repository { +class Woo_Schema_Piece_Repository implements External_Schema_Piece_Repository_Interface { /** * The WooCommerce Conditional. @@ -27,29 +29,37 @@ public function __construct( WooCommerce_Conditional $woocommerce_conditional ) } /** - * Collect Product schema for WooCommerce products. + * Checks if this repository supports the given post type. * - * ## How it Works + * @param string $post_type The post type to check. * - * Hooks into 'wpseo_schema_product' filter to capture enriched Product schema - * Triggers WooCommerce's schema generation via WC_Structured_Data - * Returns the captured Product entity + * @return bool True if this repository can provide schema for the post type. + */ + public function supports( string $post_type ): bool { + return $this->woocommerce_conditional->is_met() && $post_type === 'product'; + } + + /** + * Collects product schema pieces for WooCommerce products. + * + * Hooks into 'wpseo_schema_product' filter to capture enriched Product schema. + * Triggers WooCommerce's schema generation via WC_Structured_Data. + * Returns the captured Product entity. * * @param int $post_id Product post ID. * - * @return array>|null Product schema entity or null if unavailable. + * @return array> Product schema pieces (empty array if unavailable). */ - public function collect_product_schema( int $post_id ): ?array { - + public function collect( int $post_id ): array { if ( ! $this->woocommerce_conditional->is_met() ) { - return null; + return []; } try { $product = \wc_get_product( $post_id ); if ( ! $product || ! \is_a( $product, 'WC_Product' ) ) { - return null; + return []; } $captured_schema = null; @@ -71,12 +81,12 @@ public function collect_product_schema( int $post_id ): ?array { \remove_filter( 'wpseo_schema_product', $capture_filter, 999 ); if ( ! \is_array( $captured_schema ) ) { - return null; + return []; } - return $captured_schema; + return [ $captured_schema ]; } catch ( Exception $e ) { - return null; + return []; } } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php new file mode 100644 index 00000000000..008a9cc2612 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php @@ -0,0 +1,58 @@ +edd_conditional = Mockery::mock( EDD_Conditional::class ); + $this->meta = Mockery::mock( Meta_Surface::class ); + + $this->instance = new Edd_Schema_Piece_Repository( + $this->edd_conditional, + $this->meta + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Collect_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Collect_Test.php new file mode 100644 index 00000000000..73c50a0b4ee --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Collect_Test.php @@ -0,0 +1,32 @@ +edd_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->collect( 123 ); + + $this->assertSame( [], $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Supports_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Supports_Test.php new file mode 100644 index 00000000000..d088f4937d3 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Edd_Schema_Piece_Repository_Supports_Test.php @@ -0,0 +1,112 @@ +edd_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + $result = $this->instance->supports( 'download' ); + + $this->assertTrue( $result ); + } + + /** + * Tests that supports returns false for download post type when EDD is not active. + * + * @return void + */ + public function test_supports_returns_false_for_download_when_edd_not_active() { + $this->edd_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->supports( 'download' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for non-download post types when EDD is active. + * + * @return void + */ + public function test_supports_returns_false_for_non_download_post_type_when_edd_active() { + $this->edd_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + $result = $this->instance->supports( 'post' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for non-download post types when EDD is not active. + * + * @return void + */ + public function test_supports_returns_false_for_non_download_post_type_when_edd_not_active() { + $this->edd_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->supports( 'post' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for product post type when EDD is active. + * + * @return void + */ + public function test_supports_returns_false_for_product_post_type_when_edd_active() { + $this->edd_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + $result = $this->instance->supports( 'product' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for product post type when EDD is not active. + * + * @return void + */ + public function test_supports_returns_false_for_product_post_type_when_edd_not_active() { + $this->edd_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->supports( 'product' ); + + $this->assertFalse( $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php new file mode 100644 index 00000000000..e996f10d3d4 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php @@ -0,0 +1,48 @@ +woocommerce_conditional = Mockery::mock( WooCommerce_Conditional::class ); + + $this->instance = new Woo_Schema_Piece_Repository( + $this->woocommerce_conditional + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php new file mode 100644 index 00000000000..b898a0a9fe6 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php @@ -0,0 +1,76 @@ +woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->collect( 123 ); + + $this->assertSame( [], $result ); + } + + /** + * Tests that collect returns empty array when product is not found. + * + * @return void + */ + public function test_collect_returns_empty_array_when_product_not_found() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + Functions\expect( 'wc_get_product' ) + ->once() + ->with( 123 ) + ->andReturn( false ); + + $result = $this->instance->collect( 123 ); + + $this->assertSame( [], $result ); + } + + /** + * Tests that collect returns empty array when product is null. + * + * @return void + */ + public function test_collect_returns_empty_array_when_product_is_null() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + Functions\expect( 'wc_get_product' ) + ->once() + ->with( 123 ) + ->andReturn( null ); + + $result = $this->instance->collect( 123 ); + + $this->assertSame( [], $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Supports_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Supports_Test.php new file mode 100644 index 00000000000..5145be80132 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Supports_Test.php @@ -0,0 +1,112 @@ +woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + $result = $this->instance->supports( 'product' ); + + $this->assertTrue( $result ); + } + + /** + * Tests that supports returns false for product post type when WooCommerce is not active. + * + * @return void + */ + public function test_supports_returns_false_for_product_when_woocommerce_not_active() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->supports( 'product' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for non-product post types when WooCommerce is active. + * + * @return void + */ + public function test_supports_returns_false_for_non_product_post_type_when_woocommerce_active() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + $result = $this->instance->supports( 'post' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for non-product post types when WooCommerce is not active. + * + * @return void + */ + public function test_supports_returns_false_for_non_product_post_type_when_woocommerce_not_active() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->supports( 'post' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for download post type when WooCommerce is active. + * + * @return void + */ + public function test_supports_returns_false_for_download_post_type_when_woocommerce_active() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + $result = $this->instance->supports( 'download' ); + + $this->assertFalse( $result ); + } + + /** + * Tests that supports returns false for download post type when WooCommerce is not active. + * + * @return void + */ + public function test_supports_returns_false_for_download_post_type_when_woocommerce_not_active() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( false ); + + $result = $this->instance->supports( 'download' ); + + $this->assertFalse( $result ); + } +} From 0c2cf6de5875ee5408740dc577cb7f66cc27c578 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 19 Jan 2026 17:10:38 +0100 Subject: [PATCH 239/319] Add schema node filters unit tests --- .../WebPage_Schema_Node_Filter_Test.php | 107 ++++++++++++++++++ ...stract_WebSite_Schema_Node_Filter_Test.php | 42 +++++++ .../Constructor_Test.php | 29 +++++ .../Filter_Test.php | 101 +++++++++++++++++ 4 files changed, 279 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php new file mode 100644 index 00000000000..5d140963ad2 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php @@ -0,0 +1,107 @@ +instance = new WebPage_Schema_Node_Filter(); + } + + /** + * Tests the filter method of WebPage_Schema_Node_Filter. + * + * @dataProvider filter_data_provider + * + * @param array> $schema_data The full schema data. + * @param array $schema_piece_data The schema piece data to be filtered. + * @param bool $expected Expected result. + * + * @return void + */ + public function test_filter( array $schema_data, array $schema_piece_data, bool $expected ): void { + $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); + $schema = new Schema_Piece_Collection(); + foreach ( $schema_data as $data ) { + $schema->add( new Schema_Piece( $data, $data['@type'] ) ); + } + $result = $this->instance->filter( $schema, $schema_piece ); + + $this->assertSame( $expected, $result ); + } + + /** + * Data provider for test_filter. + * + * @return array>, array, bool>> + */ + public function filter_data(): array { + return [ + 'WebPage without Article references' => [ + [ + [ + '@type' => 'WebPage', + '@id' => 'https://example.com/#webpage', + ], + [ + '@type' => 'Article', + '@id' => 'https://example.com/#article', + ], + ], + [ + '@type' => 'WebPage', + '@id' => 'https://example.com/#webpage', + ], + true, + ], + 'WebPage with Article reference' => [ + [ + [ + '@type' => 'WebPage', + '@id' => 'https://example.com/#webpage', + ], + [ + '@type' => 'Article', + '@id' => 'https://example.com/#article', + ], + [ + '@type' => 'Article', + '@id' => 'https://example.com/#webpage-article', + ], + ], + [ + '@type' => 'WebPage', + '@id' => 'https://example.com/#webpage-article', + ], + false, + ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php new file mode 100644 index 00000000000..41a58220adb --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php @@ -0,0 +1,42 @@ +current_site_url_provider = Mockery::mock( WordPress_Current_Site_URL_Provider::class ); + + $this->instance = new WebSite_Schema_Node_Filter(); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php new file mode 100644 index 00000000000..1bae4e8ceb9 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php @@ -0,0 +1,29 @@ +assertInstanceOf( + WordPress_Current_Site_URL_Provider::class, + $this->getPropertyValue( $this->instance, 'current_site_url_provider' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php new file mode 100644 index 00000000000..12c8fe4b575 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php @@ -0,0 +1,101 @@ +> $schema_data The full schema data. + * @param array $schema_piece_data The schema piece data to be filtered. + * @param bool $expected Expected result. + * + * @return void + */ + public function test_filter( array $schema_data, array $schema_piece_data, bool $expected ): void { + $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); + $schema = new Schema_Piece_Collection(); + foreach ( $schema_data as $data ) { + $schema->add( new Schema_Piece( $data, $data['@type'] ) ); + } + + Functions\expect( 'get_current_blog_id' ) + ->once() + ->andReturn( 1 ); + Functions\expect( 'get_home_url' ) + ->once() + ->with( 1 ) + ->andReturn( 'https://example.com' ); + Functions\expect( 'trailingslashit' ) + ->once() + ->andReturnFirstArg(); + + $result = $this->instance->filter( $schema, $schema_piece ); + + $this->assertSame( $expected, $result ); + } + + /** + * Data provider for test_filter. + * + * @return array>, array, bool>> + */ + public function filter_data(): array { + return [ + 'WebSite with matching current site URL' => [ + [ + [ + '@type' => 'WebSite', + '@id' => 'https://example.com/#website', + 'url' => 'https://example.com', + ], + ], + [ + '@type' => 'WebSite', + '@id' => 'https://example.com/#website', + 'url' => 'https://example.com', + ], + false, + ], + 'WebSite with different URL than current site' => [ + [ + [ + '@type' => 'WebSite', + '@id' => 'https://other.com/#website', + 'url' => 'https://other.com', + ], + ], + [ + '@type' => 'WebSite', + '@id' => 'https://other.com/#website', + 'url' => 'https://other.com', + ], + true, + ], + 'WebSite with current site URL as subdirectory' => [ + [], + [ + '@type' => 'WebSite', + '@id' => 'https://example.com/blog/#website', + 'url' => 'https://example.com/blog', + ], + true, + ], + ]; + } +} From e61a90f8781eb2f5fe269a7ecb6cbaca2c1c1980 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 19 Jan 2026 17:10:53 +0100 Subject: [PATCH 240/319] Ignore private method for code coverage --- .../filtering/schema-node-filter/webpage-schema-node-filter.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php index 75cafce2ab6..1e03b9f4434 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/webpage-schema-node-filter.php @@ -45,6 +45,8 @@ public function filter( Schema_Piece_Collection $schema, Schema_Piece $schema_pi * * @param Schema_Piece_Collection $schema The full schema. * + * @codeCoverageIgnore + * * @return array The IDs of the Article schema pieces. */ private function get_articles_ids( Schema_Piece_Collection $schema ): array { From fbb7899a8e872dba9400785c5576c1578967392c Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 19 Jan 2026 17:11:27 +0100 Subject: [PATCH 241/319] Add the schema-aggregator @group annotation --- .../Aggregator_Config_Get_Allowed_Post_Types_Test.php | 1 + .../Infrastructure/Config/Config_Cache_Enabled_Test.php | 1 + .../Config/Config_Get_Big_Per_Post_Type_Test.php | 1 + .../Config/Config_Get_Default_Per_Post_Type_Test.php | 1 + .../Infrastructure/Config/Config_Get_Expiration_Test.php | 1 + .../Infrastructure/Config/Config_Get_Max_Per_Page_Test.php | 1 + .../Infrastructure/Config/Config_Get_Per_Page_Test.php | 1 + .../Article_Config/Article_Config_Get_Config_Value_Test.php | 1 + .../Article_Config_Is_Enhancement_Enabled_Test.php | 1 + .../Article_Config_Should_Include_Article_Body_Test.php | 1 + .../Person_Config/Person_Config_Get_Config_Value_Test.php | 3 ++- .../Person_Config_Is_Enhancement_Enabled_Test.php | 3 ++- .../Abstract_Cache_Listener_Integration_Constructor_Test.php | 1 + ...ables_Update_Listener_Integration_Get_Conditionals_Test.php | 1 + ...exables_Update_Listener_Integration_Register_Hooks_Test.php | 1 + ...Indexables_Update_Listener_Integration_Reset_Cache_Test.php | 1 + ..._Type_Change_Listener_Integration_Get_Conditionals_Test.php | 1 + ...ct_Type_Change_Listener_Integration_Register_Hooks_Test.php | 1 + ...oduct_Type_Change_Listener_Integration_Reset_Cache_Test.php | 1 + ...ite_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php | 1 + ...ma_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php | 1 + .../Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php | 1 + 22 files changed, 24 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php index b1ec7d6ce25..898f5f6dd4b 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php @@ -10,6 +10,7 @@ /** * Test class for the get_allowed_post_types method. * + * @group schema-aggregator * @group Aggregator_Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config::get_allowed_post_types diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php index 86a3da4b54c..bd0d2b40021 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Cache_Enabled_Test.php @@ -10,6 +10,7 @@ /** * Test class for the cache_enabled method. * + * @group schema-aggregator * @group Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config::cache_enabled diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php index 2bd0fe138ff..744ef2b59cc 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Big_Per_Post_Type_Test.php @@ -9,6 +9,7 @@ /** * Test class for the get_big_per_post_type method. * + * @group schema-aggregator * @group Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config::get_big_per_post_type diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php index 9297fde3951..5918c31d086 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Default_Per_Post_Type_Test.php @@ -9,6 +9,7 @@ /** * Test class for the get_default_per_post_type method. * + * @group schema-aggregator * @group Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config::get_default_per_post_type diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php index 022b5a5bb0a..e8cf93c9842 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php @@ -10,6 +10,7 @@ /** * Test class for the get_expiration method. * + * @group schema-aggregator * @group Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config::get_expiration diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php index 8dafc7d671f..cd2707a41fc 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Max_Per_Page_Test.php @@ -6,6 +6,7 @@ /** * Test class for the get_max_per_page method. * + * @group schema-aggregator * @group Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config::get_max_per_page diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php index 9f2ab88c316..0c7ef33b639 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Per_Page_Test.php @@ -9,6 +9,7 @@ /** * Test class for the get_per_page method. * + * @group schema-aggregator * @group Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config::get_per_page diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php index f0cd7e32a96..be143acccb6 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Get_Config_Value_Test.php @@ -9,6 +9,7 @@ /** * Test class for the get_config_value method. * + * @group schema-aggregator * @group Article_Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Article_Config::get_config_value diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php index 1e929051dfd..81b5c693d4f 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Is_Enhancement_Enabled_Test.php @@ -9,6 +9,7 @@ /** * Test class for the is_enhancement_enabled method. * + * @group schema-aggregator * @group Article_Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Article_Config::is_enhancement_enabled diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php index d16a3ad26aa..233ac862e8d 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Article_Config/Article_Config_Should_Include_Article_Body_Test.php @@ -9,6 +9,7 @@ /** * Test class for the should_include_article_body method. * + * @group schema-aggregator * @group Article_Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Article_Config::should_include_article_body diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php index 0ebf1ea187b..84eabd30dc9 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Get_Config_Value_Test.php @@ -9,7 +9,8 @@ /** * Test class for the get_config_value method. * - * @group Person_Config + * @group schema-aggregator + * @group Article_Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Person_Config::get_config_value * diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php index 95c737b36d9..8913daba4e1 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Enhancement/Person_Config/Person_Config_Is_Enhancement_Enabled_Test.php @@ -9,7 +9,8 @@ /** * Test class for the is_enhancement_enabled method. * - * @group Person_Config + * @group schema-aggregator + * @group Article_Config * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Enhancement\Person_Config::is_enhancement_enabled * diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php index 74ef135c60d..85967787e92 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php @@ -12,6 +12,7 @@ /** * Test class for the Abstract_Cache_Listener_Integration constructor. * + * @group schema-aggregator * @group Abstract_Cache_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\Abstract_Cache_Listener_Integration::__construct diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php index 8b72409a97b..3045c6722df 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php @@ -9,6 +9,7 @@ /** * Test class for the get_conditionals method. * + * @group schema-aggregator * @group Indexables_Update_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\Indexables_Update_Listener_Integration::get_conditionals diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php index 293b1e07364..62cea7f9aea 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php @@ -8,6 +8,7 @@ /** * Test class for the register_hooks method. * + * @group schema-aggregator * @group Indexables_Update_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\Indexables_Update_Listener_Integration::register_hooks diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php index ab416c75e44..244bff86e03 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Reset_Cache_Test.php @@ -9,6 +9,7 @@ /** * Test class for the reset_cache method. * + * @group schema-aggregator * @group Indexables_Update_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\Indexables_Update_Listener_Integration::reset_cache diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php index 877e9c3a7e5..20efdad89c9 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Get_Conditionals_Test.php @@ -9,6 +9,7 @@ /** * Test class for the get_conditionals method. * + * @group schema-aggregator * @group WooCommerce_Product_Type_Change_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\WooCommerce_Product_Type_Change_Listener_Integration::get_conditionals diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php index ddffd85b3d5..e01f4769e96 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php @@ -8,6 +8,7 @@ /** * Test class for the register_hooks method. * + * @group schema-aggregator * @group WooCommerce_Product_Type_Change_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\WooCommerce_Product_Type_Change_Listener_Integration::register_hooks diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php index 241c8851d88..f45533c2bf6 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Reset_Cache_Test.php @@ -9,6 +9,7 @@ /** * Test class for the reset_cache method. * + * @group schema-aggregator * @group WooCommerce_Product_Type_Change_Listener_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Cache\WooCommerce_Product_Type_Change_Listener_Integration::reset_cache diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php index 790fbbdf18a..34d2945ce10 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php @@ -9,6 +9,7 @@ /** * Test class for the get_conditionals method. * + * @group schema-aggregator * @group Site_Schema_Robots_Txt_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Site_Schema_Robots_Txt_Integration::get_conditionals diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php index e51f3e4d0bb..f445e60472c 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Maybe_Add_Xml_Schema_Map_Test.php @@ -13,6 +13,7 @@ /** * Test class for the maybe_add_xml_schema_map method. * + * @group schema-aggregator * @group Site_Schema_Robots_Txt_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Site_Schema_Robots_Txt_Integration::maybe_add_xml_schema_map diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php index b2722f8634d..5d4565ec84d 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php @@ -8,6 +8,7 @@ /** * Test class for the register_hooks method. * + * @group schema-aggregator * @group Site_Schema_Robots_Txt_Integration * * @covers Yoast\WP\SEO\Schema_Aggregator\User_Interface\Site_Schema_Robots_Txt_Integration::register_hooks From 088ececd3949a05fdd0819c5aace5090766d0dd3 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 20 Jan 2026 14:05:36 +0100 Subject: [PATCH 242/319] Add integration test for xml route --- .../site-schema-aggregator-xml-route.php | 22 ---- .../Site_Schema_Aggregator_Xml_Route_Test.php | 122 ++++++++++++++++++ 2 files changed, 122 insertions(+), 22 deletions(-) create mode 100644 tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php index 6b7ff13eb89..7004c4d3e20 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -4,7 +4,6 @@ use WP_Error; use WP_REST_Response; -use Yoast\WP\SEO\Helpers\Capability_Helper; use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Routes\Route_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Map_Command; @@ -34,20 +33,6 @@ class Site_Schema_Aggregator_Xml_Route implements Route_Interface { */ public const GET_SCHEMA_ROUTE = self::ROUTE_PREFIX . '/get-xml'; - /** - * The configuration instance. - * - * @var Config - */ - private $config; - - /** - * The capability helper instance. - * - * @var Capability_Helper - */ - private $capability_helper; - /** * The command handler instance. * @@ -81,9 +66,6 @@ public static function get_conditionals() { /** * Site_Schema_Aggregator_Route constructor. * - * @param Config $config The config object. - * @param Capability_Helper $capability_helper The capability - * helper. * @param Aggregate_Site_Schema_Map_Command_Handler $aggregate_site_schema_map_command_handler The command handler. * @param Xml_Manager $xml_cache_manager The XML cache * manager. @@ -91,14 +73,10 @@ public static function get_conditionals() { * configuration. */ public function __construct( - Config $config, - Capability_Helper $capability_helper, Aggregate_Site_Schema_Map_Command_Handler $aggregate_site_schema_map_command_handler, Xml_Manager $xml_cache_manager, Aggregator_Config $aggregator_config ) { - $this->config = $config; - $this->capability_helper = $capability_helper; $this->aggregate_site_schema_map_command_handler = $aggregate_site_schema_map_command_handler; $this->xml_cache_manager = $xml_cache_manager; $this->aggregator_config = $aggregator_config; diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php new file mode 100644 index 00000000000..bea00a265ce --- /dev/null +++ b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php @@ -0,0 +1,122 @@ +aggregate_site_schema_map_command_handler = Mockery::mock( Aggregate_Site_Schema_Map_Command_Handler::class ); + $this->xml_cache_manager = Mockery::mock( Xml_Manager::class ); + $this->aggregator_config = Mockery::mock( Aggregator_Config::class ); + $this->instance = new Site_Schema_Aggregator_Xml_Route( $this->aggregate_site_schema_map_command_handler, $this->xml_cache_manager, $this->aggregator_config ); + } + + /** + * Tests the xml map without cache. + * + * @return void + */ + public function test_render_schema_xml_no_cache() { + \YoastSEO()->helpers->options->set( 'enable_schema_aggregation_endpoint', true ); + $this->xml_cache_manager->expects( 'get' ) + ->once() + ->andReturn( false ); + $this->aggregator_config->expects( 'get_allowed_post_types' ) + ->once() + ->andReturn( [ 'page' ] ); + $this->xml_cache_manager->expects( 'set' ) + ->once(); + + $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-xml' ); + $response = \rest_get_server()->dispatch( $request ); + + $this->assertInstanceOf( WP_REST_Response::class, $response ); + + $response_data = $response->get_data(); + + $this->assertSame( 200, $response->status ); + $this->assertStringContainsString( 'assertSame( 'application/xml; charset=UTF-8', $response->get_headers()['Content-Type'] ); + $this->assertSame( 'public, max-age=300', $response->get_headers()['Cache-Control'] ); + } + + /** + * Tests the xml map with cache. + * + * @return void + */ + public function test_render_schema_xml_with_cache() { + \YoastSEO()->helpers->options->set( 'enable_schema_aggregation_endpoint', true ); + $this->xml_cache_manager->expects( 'get' ) + ->once() + ->andReturn( '' ); + $this->aggregator_config->expects( 'get_allowed_post_types' ) + ->once() + ->andReturn( [ 'page' ] ); + $this->xml_cache_manager->expects( 'set' ) + ->never(); + + $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-xml' ); + $response = \rest_get_server()->dispatch( $request ); + + $this->assertInstanceOf( WP_REST_Response::class, $response ); + + $response_data = $response->get_data(); + + $this->assertSame( 200, $response->status ); + $this->assertStringContainsString( 'assertSame( 'application/xml; charset=UTF-8', $response->get_headers()['Content-Type'] ); + $this->assertSame( 'public, max-age=300', $response->get_headers()['Cache-Control'] ); + } +} From dca27922b09a092fb5670c6e8ccd75514c2f6ab7 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 16:58:14 +0100 Subject: [PATCH 243/319] Add tests --- .../Filtering/Default_Filter_Test.php | 389 ++++++++++++++++++ .../WebPage_Schema_Node_Filter_Test.php | 2 +- ...stract_WebSite_Schema_Node_Filter_Test.php | 2 +- .../Base_Schema_Node_Property_Filter_Test.php | 176 ++++++++ ...bPage_Schema_Node_Property_Filter_Test.php | 176 ++++++++ 5 files changed, 743 insertions(+), 2 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter_Test.php new file mode 100644 index 00000000000..8ee266c474b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter_Test.php @@ -0,0 +1,389 @@ +elements_context_map_repository = Mockery::mock( Elements_Context_Map_Repository::class ); + $this->instance = new Default_Filter( $this->elements_context_map_repository ); + } + + /** + * Tests the filter method of Default_Filter. + * + * @dataProvider filter_data + * + * @param array> $elements_context_map The elements context map. + * @param array> $schema_pieces_data The schema pieces data. + * @param array> $expected_data The expected filtered data. + * @param int $expected_wp_function_calls The expected number of WordPress function calls. + * + * @return void + */ + public function test_schema_pieces_filter( array $elements_context_map, array $schema_pieces_data, array $expected_data, int $expected_wp_function_calls ): void { + $this->elements_context_map_repository + ->shouldReceive( 'get_map' ) + ->andReturn( $elements_context_map ); + + $schema_pieces = []; + foreach ( $schema_pieces_data as $data ) { + $schema_pieces[] = new Schema_Piece( $data, $data['@type'] ); + } + $schema = new Schema_Piece_Collection( $schema_pieces ); + + Functions\expect( 'get_current_blog_id' ) + ->times( $expected_wp_function_calls ) + ->andReturn( 1 ); + Functions\expect( 'get_home_url' ) + ->times( $expected_wp_function_calls ) + ->with( 1 ) + ->andReturn( 'https://example.com' ); + Functions\expect( 'trailingslashit' ) + ->times( $expected_wp_function_calls ) + ->andReturnFirstArg(); + + $result = $this->instance->filter( $schema ); + $result_data = \array_map( + static function ( $piece ) { + return $piece->get_data(); + }, + $result->to_array() + ); + + $this->assertSame( $expected_data, $result_data ); + } + + /** + * Tests that specific property filters are used when available. + * + * @dataProvider schema_piece_properties_filter_data + * + * @param array> $elements_context_map The elements context map. + * @param array $schema_piece_data The schema piece data. + * @param array $expected_data The expected filtered data. + * + * @return void + */ + public function test_schema_piece_properties_filter( array $elements_context_map, array $schema_piece_data, array $expected_data ): void { + $this->elements_context_map_repository + ->shouldReceive( 'get_map' ) + ->andReturn( $elements_context_map ); + + $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); + $schema = new Schema_Piece_Collection( [ $schema_piece ] ); + + $result = $this->instance->filter( $schema ); + $result_data = \array_map( + static function ( $piece ) { + return $piece->get_data(); + }, + $result->to_array() + ); + + $this->assertCount( 1, $result_data ); + $this->assertSame( $expected_data, $result_data[0] ); + } + + /** + * Data provider for test_schema_piece_properties_filter. + * + * @return array>, array, array>> + */ + public function schema_piece_properties_filter_data(): array { + return [ + 'WebPage with specific property filter (removes breadcrumb and base properties)' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + '@type' => 'WebPage', + 'name' => 'Test Page', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'primaryImageOfPage' => [ '@id' => 'https://example.com/image.jpg' ], + 'url' => 'https://example.com/page', + 'description' => 'Page description', + ], + [ + '@type' => 'WebPage', + 'name' => 'Test Page', + 'url' => 'https://example.com/page', + 'description' => 'Page description', + ], + ], + 'Article with base property filter only (removes base properties, no specific filter)' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'primaryImageOfPage' => [ '@id' => 'https://example.com/image.jpg' ], + 'author' => 'John Doe', + 'datePublished' => '2023-01-01', + ], + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'author' => 'John Doe', + 'datePublished' => '2023-01-01', + ], + ], + 'Person with no properties to filter (no specific or base filters needed)' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + 'jobTitle' => 'Writer', + 'email' => 'jane@example.com', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + 'jobTitle' => 'Writer', + 'email' => 'jane@example.com', + ], + ], + ]; + } + + /** + * Data provider for test_filter. + * + * @return array>, array>, array>, int>> + */ + public function filter_data(): array { + return [ + 'Schema pieces with no filterable categories' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'author' => 'John Doe', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'author' => 'John Doe', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + 0, + ], + 'Schema pieces with filterable categories but no existing filters' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => 'ReadAction', + 'target' => 'https://example.com', + ], + [ + '@type' => 'Article', + 'headline' => 'Test Article', + ], + ], + [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + ], + ], + 0, + ], + 'Schema pieces with properties to be filtered' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'author' => 'John Doe', + ], + [ + '@type' => 'WebPage', + 'name' => 'Test Page', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/page', + ], + ], + [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'author' => 'John Doe', + ], + [ + '@type' => 'WebPage', + 'name' => 'Test Page', + 'url' => 'https://example.com/page', + ], + ], + 0, + ], + 'Mixed schema pieces with both node and property filtering' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [ 'MetaTags' ], + 'website' => [], + ], + [ + [ + '@type' => 'ReadAction', + 'target' => 'https://example.com', + ], + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'author' => 'John Doe', + ], + [ + '@type' => 'MetaTags', + 'content' => 'Meta content', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'author' => 'John Doe', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + 0, + ], + 'Empty schema collection' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [], + [], + 0, + ], + 'Schema pieces with multiple filterable categories' => [ + [ + 'action' => [ 'ReadAction', 'WriteAction' ], + 'enumeration' => [ 'EventStatusType' ], + 'meta' => [], + 'website' => [ 'WebSite' ], + ], + [ + [ + '@type' => 'ReadAction', + 'target' => 'https://example.com', + ], + [ + '@type' => 'WebSite', + 'name' => 'Example Site', + 'url' => 'https://example.com', + ], + [ + '@type' => 'Article', + 'headline' => 'Test Article', + ], + [ + '@type' => 'EventStatusType', + 'name' => 'EventScheduled', + ], + ], + [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + ], + ], + 1, + ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php index 5d140963ad2..6ea95926d80 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php @@ -38,7 +38,7 @@ public function setUp(): void { /** * Tests the filter method of WebPage_Schema_Node_Filter. * - * @dataProvider filter_data_provider + * @dataProvider filter_data * * @param array> $schema_data The full schema data. * @param array $schema_piece_data The schema piece data to be filtered. diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php index 41a58220adb..fc3f12fa3d8 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php @@ -11,7 +11,7 @@ /** * Base class for WebSite_Schema_Node_Filter tests. */ -final class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { +class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { /** * The WordPress_Current_Site_URL_Provider mock. diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php new file mode 100644 index 00000000000..0e06c45a4d3 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php @@ -0,0 +1,176 @@ +instance = new Base_Schema_Node_Property_Filter(); + } + + /** + * Tests the filter_properties method of Base_Schema_Node_Property_Filter. + * + * @dataProvider filter_properties_data + * + * @param array $schema_piece_data The schema piece data to be filtered. + * @param array $expected_data The expected filtered schema piece data. + * + * @return void + */ + public function test_filter_properties( array $schema_piece_data, array $expected_data ): void { + $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); + + $result = $this->instance->filter_properties( $schema_piece ); + $this->assertSame( $expected_data, $result->get_data() ); + } + + /** + * Data provider for test_filter_properties. + * + * @return array, array>> + */ + public function filter_properties_data(): array { + return [ + 'Schema piece with all properties to be removed' => [ + [ + '@type' => 'Article', + 'headline' => 'An example headline', + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'primaryImageOfPage' => [ '@id' => 'https://example.com/image.jpg' ], + 'author' => 'John Doe', + ], + [ + '@type' => 'Article', + 'headline' => 'An example headline', + 'author' => 'John Doe', + ], + ], + 'Schema piece with some properties to be removed' => [ + [ + '@type' => 'WebPage', + 'name' => 'Example Page', + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'description' => 'A sample page', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'url' => 'https://example.com/page', + ], + [ + '@type' => 'WebPage', + 'name' => 'Example Page', + 'description' => 'A sample page', + 'url' => 'https://example.com/page', + ], + ], + 'Schema piece without properties to be removed' => [ + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + 'jobTitle' => 'Writer', + 'email' => 'jane@example.com', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + 'jobTitle' => 'Writer', + 'email' => 'jane@example.com', + ], + ], + 'Empty schema piece except @type' => [ + [ + '@type' => 'Organization', + ], + [ + '@type' => 'Organization', + ], + ], + 'Schema piece with null values for avoided properties' => [ + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'potentialAction' => null, + 'mainEntityOfPage' => null, + 'author' => 'Test Author', + ], + [ + '@type' => 'Article', + 'headline' => 'Test Article', + 'author' => 'Test Author', + ], + ], + 'Schema piece with empty arrays for avoided properties' => [ + [ + '@type' => 'WebSite', + 'name' => 'Example Site', + 'potentialAction' => [], + 'isPartOf' => [], + 'primaryImageOfPage' => [], + 'url' => 'https://example.com', + ], + [ + '@type' => 'WebSite', + 'name' => 'Example Site', + 'url' => 'https://example.com', + ], + ], + 'Schema piece with mixed data types for avoided properties' => [ + [ + '@type' => 'Product', + 'name' => 'Test Product', + 'potentialAction' => 'string value', + 'price' => 99.99, + 'isPartOf' => 123, + 'inStock' => true, + 'mainEntityOfPage' => false, + ], + [ + '@type' => 'Product', + 'name' => 'Test Product', + 'price' => 99.99, + 'inStock' => true, + ], + ], + 'Schema piece with only one avoided property' => [ + [ + '@type' => 'BlogPosting', + 'headline' => 'Blog Post', + 'isPartOf' => [ '@type' => 'Blog' ], + 'datePublished' => '2023-01-01', + ], + [ + '@type' => 'BlogPosting', + 'headline' => 'Blog Post', + 'datePublished' => '2023-01-01', + ], + ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php new file mode 100644 index 00000000000..12702d39e96 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php @@ -0,0 +1,176 @@ +instance = new WebPage_Schema_Node_Property_Filter(); + } + + /** + * Tests the filter_properties method of WebPage_Schema_Node_Property_Filter. + * + * @dataProvider filter_properties_data + * + * @param array $schema_piece_data The schema piece data to be filtered. + * @param array $expected_data The expected filtered schema piece data. + * + * @return void + */ + public function test_filter_properties( array $schema_piece_data, array $expected_data ): void { + $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); + + $result = $this->instance->filter_properties( $schema_piece ); + $this->assertSame( $expected_data, $result->get_data() ); + } + + /** + * Data provider for test_filter_properties. + * + * @return array, array>> + */ + public function filter_properties_data(): array { + return [ + 'WebPage with all properties to be removed' => [ + [ + '@type' => 'WebPage', + 'name' => 'Example Page', + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'primaryImageOfPage' => [ '@id' => 'https://example.com/image.jpg' ], + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/page', + ], + [ + '@type' => 'WebPage', + 'name' => 'Example Page', + 'url' => 'https://example.com/page', + ], + ], + 'WebPage with some base properties and breadcrumb to be removed' => [ + [ + '@type' => 'WebPage', + 'name' => 'Sample Page', + 'potentialAction' => [ '@type' => 'ReadAction' ], + 'description' => 'A sample page', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/sample', + ], + [ + '@type' => 'WebPage', + 'name' => 'Sample Page', + 'description' => 'A sample page', + 'url' => 'https://example.com/sample', + ], + ], + 'WebPage with only breadcrumb to be removed' => [ + [ + '@type' => 'WebPage', + 'name' => 'Page with Breadcrumb', + 'breadcrumb' => [ + '@type' => 'BreadcrumbList', + 'itemListElement' => [], + ], + 'description' => 'Page description', + ], + [ + '@type' => 'WebPage', + 'name' => 'Page with Breadcrumb', + 'description' => 'Page description', + ], + ], + 'WebPage with only base properties to be removed' => [ + [ + '@type' => 'WebPage', + 'name' => 'Another Page', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/another' ], + 'datePublished' => '2023-01-01', + ], + [ + '@type' => 'WebPage', + 'name' => 'Another Page', + 'datePublished' => '2023-01-01', + ], + ], + 'WebPage without properties to be removed' => [ + [ + '@type' => 'WebPage', + 'name' => 'Clean Page', + 'description' => 'No properties to remove', + 'url' => 'https://example.com/clean', + 'datePublished' => '2023-01-01', + ], + [ + '@type' => 'WebPage', + 'name' => 'Clean Page', + 'description' => 'No properties to remove', + 'url' => 'https://example.com/clean', + 'datePublished' => '2023-01-01', + ], + ], + 'WebPage with null breadcrumb' => [ + [ + '@type' => 'WebPage', + 'name' => 'Page with Null Breadcrumb', + 'breadcrumb' => null, + 'url' => 'https://example.com/null-breadcrumb', + ], + [ + '@type' => 'WebPage', + 'name' => 'Page with Null Breadcrumb', + 'url' => 'https://example.com/null-breadcrumb', + ], + ], + 'WebPage with empty breadcrumb array' => [ + [ + '@type' => 'WebPage', + 'name' => 'Page with Empty Breadcrumb', + 'breadcrumb' => [], + 'description' => 'Page description', + ], + [ + '@type' => 'WebPage', + 'name' => 'Page with Empty Breadcrumb', + 'description' => 'Page description', + ], + ], + 'Empty WebPage except @type' => [ + [ + '@type' => 'WebPage', + ], + [ + '@type' => 'WebPage', + ], + ], + ]; + } +} From 38b15a935761a4bb59c4c13b5519b35fa7e95b1b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 16:58:42 +0100 Subject: [PATCH 244/319] Make the filters remove a property even if its value is null --- .../base-schema-node-property-filter.php | 4 +++- .../webpage-schema-node-property-filter.php | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php index 477fb8dbb6f..08f9367fe94 100644 --- a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php @@ -29,7 +29,7 @@ public function filter_properties( Schema_Piece $schema_piece ): Schema_Piece { $data = $schema_piece->get_data(); foreach ( $this->get_properties_avoid_list() as $property ) { - if ( isset( $data[ $property ] ) ) { + if ( \array_key_exists( $property, $data ) ) { unset( $data[ $property ] ); } } @@ -40,6 +40,8 @@ public function filter_properties( Schema_Piece $schema_piece ): Schema_Piece { /** * Gets the properties avoid list. * + * @codeCoverageIgnore + * * @return array The properties avoid list. */ private function get_properties_avoid_list(): array { diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php index 0a20cedb834..32725b2a6c3 100644 --- a/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/webpage-schema-node-property-filter.php @@ -26,8 +26,7 @@ public function filter_properties( Schema_Piece $schema_piece ): Schema_Piece { $filtered_piece = parent::filter_properties( $schema_piece ); $data = $filtered_piece->get_data(); - // Remove the article body to reduce schema size. - if ( isset( $data['breadcrumb'] ) ) { + if ( \array_key_exists( 'breadcrumb', $data ) ) { unset( $data['breadcrumb'] ); } From 1cd182b580df73ccf2881d625ae0598bfe24fce4 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:18:42 +0100 Subject: [PATCH 245/319] More tests --- .../Abstract_Default_Filter_Test.php | 40 +++++++++++++++++++ .../Default_Filter/Constructor_Test.php | 28 +++++++++++++ .../Filter_Test.php} | 33 +-------------- 3 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php rename tests/Unit/Schema_Aggregator/Application/Filtering/{Default_Filter_Test.php => Default_Filter/Filter_Test.php} (91%) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php new file mode 100644 index 00000000000..7b760b1391a --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php @@ -0,0 +1,40 @@ +elements_context_map_repository = Mockery::mock( Elements_Context_Map_Repository::class ); + $this->instance = new Default_Filter( $this->elements_context_map_repository ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php new file mode 100644 index 00000000000..387a56713b6 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php @@ -0,0 +1,28 @@ +assertInstanceOf( + Elements_Context_Map_Repository::class, + $this->getPropertyValue( $this->instance, 'elements_context_map_repository' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php similarity index 91% rename from tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter_Test.php rename to tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php index 8ee266c474b..63b4c50b2fa 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php @@ -1,15 +1,11 @@ elements_context_map_repository = Mockery::mock( Elements_Context_Map_Repository::class ); - $this->instance = new Default_Filter( $this->elements_context_map_repository ); - } +final class Filter_Test extends Abstract_Default_Filter_Test { /** * Tests the filter method of Default_Filter. From eeddfcae684a6bd597d7663ab437fb0a37618c3f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:19:10 +0100 Subject: [PATCH 246/319] Remove final --- .../Abstract_WebSite_Schema_Node_Filter_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php index fc3f12fa3d8..41a58220adb 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php @@ -11,7 +11,7 @@ /** * Base class for WebSite_Schema_Node_Filter tests. */ -class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { +final class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { /** * The WordPress_Current_Site_URL_Provider mock. From 174ea36514cb670c7d7fb88fdeee1a0e939ffb7e Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:19:20 +0100 Subject: [PATCH 247/319] Fix cs --- ...bPage_Schema_Node_Property_Filter_Test.php | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php index 12702d39e96..e88e15ac3eb 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php @@ -93,9 +93,9 @@ public function filter_properties_data(): array { ], 'WebPage with only breadcrumb to be removed' => [ [ - '@type' => 'WebPage', - 'name' => 'Page with Breadcrumb', - 'breadcrumb' => [ + '@type' => 'WebPage', + 'name' => 'Page with Breadcrumb', + 'breadcrumb' => [ '@type' => 'BreadcrumbList', 'itemListElement' => [], ], @@ -123,17 +123,17 @@ public function filter_properties_data(): array { ], 'WebPage without properties to be removed' => [ [ - '@type' => 'WebPage', - 'name' => 'Clean Page', - 'description' => 'No properties to remove', - 'url' => 'https://example.com/clean', + '@type' => 'WebPage', + 'name' => 'Clean Page', + 'description' => 'No properties to remove', + 'url' => 'https://example.com/clean', 'datePublished' => '2023-01-01', ], [ - '@type' => 'WebPage', - 'name' => 'Clean Page', - 'description' => 'No properties to remove', - 'url' => 'https://example.com/clean', + '@type' => 'WebPage', + 'name' => 'Clean Page', + 'description' => 'No properties to remove', + 'url' => 'https://example.com/clean', 'datePublished' => '2023-01-01', ], ], @@ -152,9 +152,9 @@ public function filter_properties_data(): array { ], 'WebPage with empty breadcrumb array' => [ [ - '@type' => 'WebPage', - 'name' => 'Page with Empty Breadcrumb', - 'breadcrumb' => [], + '@type' => 'WebPage', + 'name' => 'Page with Empty Breadcrumb', + 'breadcrumb' => [], 'description' => 'Page description', ], [ From 1a62f549238f56e2111961d2bd12f833ab3df7ee Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:19:39 +0100 Subject: [PATCH 248/319] Ignore unused code --- .../application/meta/response-meta-provider.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/schema-aggregator/application/meta/response-meta-provider.php b/src/schema-aggregator/application/meta/response-meta-provider.php index ffcdf4edf74..75ebbe6d37b 100644 --- a/src/schema-aggregator/application/meta/response-meta-provider.php +++ b/src/schema-aggregator/application/meta/response-meta-provider.php @@ -7,6 +7,8 @@ /** * Provides metadata for API responses. + * + * @codeCoverageIgnore -- Currently not used. */ class Response_Meta_Provider { From bb7a851fa1d22c71e32e23cae44e73574387f096 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:19:49 +0100 Subject: [PATCH 249/319] Ignore private method --- .../application/enhancement/person-schema-enhancer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php index 81b714ae10a..a7258ed7638 100644 --- a/src/schema-aggregator/application/enhancement/person-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/person-schema-enhancer.php @@ -77,6 +77,8 @@ protected function enhance_schema_piece( array $schema_data, Indexable $indexabl * * Retrieves job title from user meta. * + * @codeCoverageIgnore + * * @param int $user_id User ID. * * @return string|null Job title or null if unavailable. From 972d4c2d5d41fda3fb54952d580a5cbd4bc07c72 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:41:21 +0100 Subject: [PATCH 250/319] Remove final --- .../Filtering/Default_Filter/Abstract_Default_Filter_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php index 7b760b1391a..ad216171365 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php @@ -11,7 +11,7 @@ /** * Base class for Default_Filter tests. */ -final class Abstract_Default_Filter_Test extends TestCase { +class Abstract_Default_Filter_Test extends TestCase { /** * The instance of Default_Filter being tested. From 74441a6bf6725b83644213c8a151e0dfea6cc3ed Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:43:34 +0100 Subject: [PATCH 251/319] remove final --- .../Abstract_WebSite_Schema_Node_Filter_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php index 41a58220adb..fc3f12fa3d8 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php @@ -11,7 +11,7 @@ /** * Base class for WebSite_Schema_Node_Filter tests. */ -final class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { +class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { /** * The WordPress_Current_Site_URL_Provider mock. From 17e9016c5d84c68464f5b071fed4f08dbd8c2bfc Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 20 Jan 2026 23:47:47 +0100 Subject: [PATCH 252/319] Set abstract classes as abstract --- .../Filtering/Default_Filter/Abstract_Default_Filter_Test.php | 2 +- .../Abstract_WebSite_Schema_Node_Filter_Test.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php index ad216171365..3db29f0cbfd 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Abstract_Default_Filter_Test.php @@ -11,7 +11,7 @@ /** * Base class for Default_Filter tests. */ -class Abstract_Default_Filter_Test extends TestCase { +abstract class Abstract_Default_Filter_Test extends TestCase { /** * The instance of Default_Filter being tested. diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php index fc3f12fa3d8..91e44eb6081 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Abstract_WebSite_Schema_Node_Filter_Test.php @@ -11,7 +11,7 @@ /** * Base class for WebSite_Schema_Node_Filter tests. */ -class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { +abstract class Abstract_WebSite_Schema_Node_Filter_Test extends TestCase { /** * The WordPress_Current_Site_URL_Provider mock. From ebab39d48db6c9c35167570a1b61669f25531fe5 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 21 Jan 2026 14:43:34 +0100 Subject: [PATCH 253/319] Fixed some minor issues --- .../User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php index bea00a265ce..1710040bc9b 100644 --- a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php +++ b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php @@ -71,7 +71,7 @@ public function test_render_schema_xml_no_cache() { \YoastSEO()->helpers->options->set( 'enable_schema_aggregation_endpoint', true ); $this->xml_cache_manager->expects( 'get' ) ->once() - ->andReturn( false ); + ->andReturn( null ); $this->aggregator_config->expects( 'get_allowed_post_types' ) ->once() ->andReturn( [ 'page' ] ); @@ -102,8 +102,7 @@ public function test_render_schema_xml_with_cache() { ->once() ->andReturn( '' ); $this->aggregator_config->expects( 'get_allowed_post_types' ) - ->once() - ->andReturn( [ 'page' ] ); + ->never(); $this->xml_cache_manager->expects( 'set' ) ->never(); From 18501972ef089388b53962607fc1c9e1e2b74291 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 21 Jan 2026 16:02:40 +0100 Subject: [PATCH 254/319] Add action and set the option earlier. --- .../Site_Schema_Aggregator_Xml_Route_Test.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php index 1710040bc9b..3f430605f58 100644 --- a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php +++ b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php @@ -11,6 +11,7 @@ use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\User_Interface\Site_Schema_Aggregator_Xml_Route; use Yoast\WP\SEO\Tests\WP\TestCase; +use function var_dump; /** * Integration tests for Site_Schema_Aggregator_Xml_Route_Test. @@ -50,6 +51,7 @@ final class Site_Schema_Aggregator_Xml_Route_Test extends TestCase { */ private $aggregator_config; + /** * Set up the test. * @@ -60,6 +62,9 @@ public function set_up() { $this->xml_cache_manager = Mockery::mock( Xml_Manager::class ); $this->aggregator_config = Mockery::mock( Aggregator_Config::class ); $this->instance = new Site_Schema_Aggregator_Xml_Route( $this->aggregate_site_schema_map_command_handler, $this->xml_cache_manager, $this->aggregator_config ); + \YoastSEO()->helpers->options->set( 'enable_schema_aggregation_endpoint', true ); + + \do_action( 'rest_api_init' ); } /** @@ -68,7 +73,7 @@ public function set_up() { * @return void */ public function test_render_schema_xml_no_cache() { - \YoastSEO()->helpers->options->set( 'enable_schema_aggregation_endpoint', true ); + $this->xml_cache_manager->expects( 'get' ) ->once() ->andReturn( null ); @@ -82,7 +87,6 @@ public function test_render_schema_xml_no_cache() { $response = \rest_get_server()->dispatch( $request ); $this->assertInstanceOf( WP_REST_Response::class, $response ); - $response_data = $response->get_data(); $this->assertSame( 200, $response->status ); @@ -97,7 +101,6 @@ public function test_render_schema_xml_no_cache() { * @return void */ public function test_render_schema_xml_with_cache() { - \YoastSEO()->helpers->options->set( 'enable_schema_aggregation_endpoint', true ); $this->xml_cache_manager->expects( 'get' ) ->once() ->andReturn( '' ); From 8e5296c824e3bf604ce20633fd5346108ea3dc59 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 21 Jan 2026 16:07:00 +0100 Subject: [PATCH 255/319] CS --- .../User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php index 3f430605f58..ee0209ef479 100644 --- a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php +++ b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Xml_Route_Test.php @@ -11,7 +11,6 @@ use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; use Yoast\WP\SEO\Schema_Aggregator\User_Interface\Site_Schema_Aggregator_Xml_Route; use Yoast\WP\SEO\Tests\WP\TestCase; -use function var_dump; /** * Integration tests for Site_Schema_Aggregator_Xml_Route_Test. @@ -51,7 +50,6 @@ final class Site_Schema_Aggregator_Xml_Route_Test extends TestCase { */ private $aggregator_config; - /** * Set up the test. * From 91514046560c567a10eb7bc4ff9ac1f57788b517 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 22 Jan 2026 14:23:16 +0100 Subject: [PATCH 256/319] Rename method and update tests --- .../application/filtering/default-filter.php | 4 +- .../schema-node-filter-interface.php | 23 ---- .../webpage-schema-node-filter.php | 4 +- .../website-schema-node-filter.php | 4 +- .../WebPage_Schema_Node_Filter_Test.php | 12 +-- .../Filter_Test.php | 101 ------------------ 6 files changed, 12 insertions(+), 136 deletions(-) delete mode 100644 src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php delete mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index 44952661e8e..428d9329e5e 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -54,8 +54,8 @@ public function filter( Schema_Piece_Collection $schema ): Schema_Piece_Collecti foreach ( $this->filter_categories as $category ) { if ( \in_array( $schema_piece->get_type(), $elements_context_map[ $category ], true ) ) { $filter_class_name = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\\' . $schema_piece->get_type() . '_Schema_Node_Filter'; - if ( \class_exists( $filter_class_name ) && \is_a( $filter_class_name, 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\Schema_Node_Filter_Interface', true ) ) { - $should_keep = ( new $filter_class_name() )->filter( $schema, $schema_piece ); + if ( \class_exists( $filter_class_name ) && \is_a( $filter_class_name, 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\Schema_Node_Filter_Decider_Interface', true ) ) { + $should_keep = ( new $filter_class_name() )->should_filter( $schema, $schema_piece ); } else { $should_keep = false; diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php deleted file mode 100644 index 99db7419935..00000000000 --- a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-interface.php +++ /dev/null @@ -1,23 +0,0 @@ -get_data(); $articles_ids = $this->get_articles_ids( $schema ); foreach ( $articles_ids as $article_id ) { diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php index 4633bd66cc0..f4d4671f9ba 100644 --- a/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-filter/website-schema-node-filter.php @@ -14,7 +14,7 @@ * The class name uses WebSite instead of Website because we need it to reflect the schema piece name. * By doing so we can search for a piece-specific node filter in Default_Filter. */ -class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Interface { +class WebSite_Schema_Node_Filter implements Schema_Node_Filter_Decider_Interface { /** * The site info provider. @@ -38,7 +38,7 @@ public function __construct() { * * @return bool True if the schema piece should be kept, false otherwise. */ - public function filter( Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { + public function should_filter( Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { $blog_url = $this->current_site_url_provider->get_current_site_url(); $data = $schema_piece->get_data(); if ( $data['url'] === $blog_url ) { diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php index 6ea95926d80..ef6167043e4 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php @@ -36,9 +36,9 @@ public function setUp(): void { } /** - * Tests the filter method of WebPage_Schema_Node_Filter. + * Tests the should_filter method of WebPage_Schema_Node_Filter. * - * @dataProvider filter_data + * @dataProvider should_filter_data * * @param array> $schema_data The full schema data. * @param array $schema_piece_data The schema piece data to be filtered. @@ -46,23 +46,23 @@ public function setUp(): void { * * @return void */ - public function test_filter( array $schema_data, array $schema_piece_data, bool $expected ): void { + public function test_should_filter( array $schema_data, array $schema_piece_data, bool $expected ): void { $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); $schema = new Schema_Piece_Collection(); foreach ( $schema_data as $data ) { $schema->add( new Schema_Piece( $data, $data['@type'] ) ); } - $result = $this->instance->filter( $schema, $schema_piece ); + $result = $this->instance->should_filter( $schema, $schema_piece ); $this->assertSame( $expected, $result ); } /** - * Data provider for test_filter. + * Data provider for test_should_filter. * * @return array>, array, bool>> */ - public function filter_data(): array { + public function should_filter_data(): array { return [ 'WebPage without Article references' => [ [ diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php deleted file mode 100644 index 12c8fe4b575..00000000000 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Filter_Test.php +++ /dev/null @@ -1,101 +0,0 @@ -> $schema_data The full schema data. - * @param array $schema_piece_data The schema piece data to be filtered. - * @param bool $expected Expected result. - * - * @return void - */ - public function test_filter( array $schema_data, array $schema_piece_data, bool $expected ): void { - $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); - $schema = new Schema_Piece_Collection(); - foreach ( $schema_data as $data ) { - $schema->add( new Schema_Piece( $data, $data['@type'] ) ); - } - - Functions\expect( 'get_current_blog_id' ) - ->once() - ->andReturn( 1 ); - Functions\expect( 'get_home_url' ) - ->once() - ->with( 1 ) - ->andReturn( 'https://example.com' ); - Functions\expect( 'trailingslashit' ) - ->once() - ->andReturnFirstArg(); - - $result = $this->instance->filter( $schema, $schema_piece ); - - $this->assertSame( $expected, $result ); - } - - /** - * Data provider for test_filter. - * - * @return array>, array, bool>> - */ - public function filter_data(): array { - return [ - 'WebSite with matching current site URL' => [ - [ - [ - '@type' => 'WebSite', - '@id' => 'https://example.com/#website', - 'url' => 'https://example.com', - ], - ], - [ - '@type' => 'WebSite', - '@id' => 'https://example.com/#website', - 'url' => 'https://example.com', - ], - false, - ], - 'WebSite with different URL than current site' => [ - [ - [ - '@type' => 'WebSite', - '@id' => 'https://other.com/#website', - 'url' => 'https://other.com', - ], - ], - [ - '@type' => 'WebSite', - '@id' => 'https://other.com/#website', - 'url' => 'https://other.com', - ], - true, - ], - 'WebSite with current site URL as subdirectory' => [ - [], - [ - '@type' => 'WebSite', - '@id' => 'https://example.com/blog/#website', - 'url' => 'https://example.com/blog', - ], - true, - ], - ]; - } -} From bfa8c05c37065d2a7dfde9d8c15ffb182e36cdb0 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 22 Jan 2026 14:26:12 +0100 Subject: [PATCH 257/319] Rename method and update tests --- .../schema-node-filter-decider-interface.php | 23 ++++ .../Should_Filter_Test.php | 101 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-decider-interface.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Should_Filter_Test.php diff --git a/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-decider-interface.php b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-decider-interface.php new file mode 100644 index 00000000000..72fcf8f5605 --- /dev/null +++ b/src/schema-aggregator/application/filtering/schema-node-filter/schema-node-filter-decider-interface.php @@ -0,0 +1,23 @@ +> $schema_data The full schema data. + * @param array $schema_piece_data The schema piece data to be filtered. + * @param bool $expected Expected result. + * + * @return void + */ + public function test_should_filter( array $schema_data, array $schema_piece_data, bool $expected ): void { + $schema_piece = new Schema_Piece( $schema_piece_data, $schema_piece_data['@type'] ); + $schema = new Schema_Piece_Collection(); + foreach ( $schema_data as $data ) { + $schema->add( new Schema_Piece( $data, $data['@type'] ) ); + } + + Functions\expect( 'get_current_blog_id' ) + ->once() + ->andReturn( 1 ); + Functions\expect( 'get_home_url' ) + ->once() + ->with( 1 ) + ->andReturn( 'https://example.com' ); + Functions\expect( 'trailingslashit' ) + ->once() + ->andReturnFirstArg(); + + $result = $this->instance->should_filter( $schema, $schema_piece ); + + $this->assertSame( $expected, $result ); + } + + /** + * Data provider for test_should_filter. + * + * @return array>, array, bool>> + */ + public function should_filter_data(): array { + return [ + 'WebSite with matching current site URL' => [ + [ + [ + '@type' => 'WebSite', + '@id' => 'https://example.com/#website', + 'url' => 'https://example.com', + ], + ], + [ + '@type' => 'WebSite', + '@id' => 'https://example.com/#website', + 'url' => 'https://example.com', + ], + false, + ], + 'WebSite with different URL than current site' => [ + [ + [ + '@type' => 'WebSite', + '@id' => 'https://other.com/#website', + 'url' => 'https://other.com', + ], + ], + [ + '@type' => 'WebSite', + '@id' => 'https://other.com/#website', + 'url' => 'https://other.com', + ], + true, + ], + 'WebSite with current site URL as subdirectory' => [ + [], + [ + '@type' => 'WebSite', + '@id' => 'https://example.com/blog/#website', + 'url' => 'https://example.com/blog', + ], + true, + ], + ]; + } +} From 72878c4cfdaee269805b1cf9b08d975e3f2b84c1 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 22 Jan 2026 15:55:47 +0100 Subject: [PATCH 258/319] Add `Thing` schema piece. --- .../application/schema-aggregator-response-composer.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php index 5a40e2671f5..07a399eab38 100644 --- a/src/schema-aggregator/application/schema-aggregator-response-composer.php +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -28,6 +28,13 @@ public function compose( Schema_Piece_Collection $schema_pieces ): array { $piece->get_data() ); } + $composed_pieces[] = + [ + '@context' => 'https://schema.org', + '@type' => 'Thing', + 'name' => 'Yoast SEO schema aggregator version', + 'identifier' => '0.1', + ]; return $composed_pieces; } From 302c704de363aaaefae9c54b353a93b007c76630 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 27 Jan 2026 12:03:34 +0100 Subject: [PATCH 259/319] Add is debug flag for enabeling the version number --- .../aggregate-site-schema-command-handler.php | 2 +- .../aggregate-site-schema-command.php | 20 ++++++++++++++++++- .../schema-aggregator-response-composer.php | 19 ++++++++++-------- .../site-schema-aggregator-route.php | 6 +++++- .../Handle_Test.php | 2 +- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index 94385d69062..626456dbe46 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -64,6 +64,6 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { ); $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); - return $this->schema_response_composer->compose( $aggregated_schema_pieces ); + return $this->schema_response_composer->compose( $aggregated_schema_pieces, $command->is_debug() ); } } diff --git a/src/schema-aggregator/application/aggregate-site-schema-command.php b/src/schema-aggregator/application/aggregate-site-schema-command.php index 1e08d532ac9..51bf4e97388 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command.php @@ -17,15 +17,24 @@ class Aggregate_Site_Schema_Command { */ private $page_controls; + /** + * Whether debug mode is enabled. + * + * @var bool + */ + private $is_debug; + /** * The constructor. * * @param int $page The current page. * @param int $per_page The number of items per page. * @param string $post_type The post type to aggregate schema for. + * @param bool $is_debug Whether debug mode is enabled. */ - public function __construct( int $page, int $per_page, string $post_type ) { + public function __construct( int $page, int $per_page, string $post_type, bool $is_debug = false ) { $this->page_controls = new Page_Controls( $page, $per_page, $post_type ); + $this->is_debug = $is_debug; } /** @@ -36,4 +45,13 @@ public function __construct( int $page, int $per_page, string $post_type ) { public function get_page_controls(): Page_Controls { return $this->page_controls; } + + /** + * Checks if debug mode is enabled. + * + * @return bool + */ + public function is_debug(): bool { + return $this->is_debug; + } } diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php index 07a399eab38..73a62b5b132 100644 --- a/src/schema-aggregator/application/schema-aggregator-response-composer.php +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -15,10 +15,11 @@ class Schema_Aggregator_Response_Composer { * Composes the final schema response. * * @param Schema_Piece_Collection $schema_pieces The schema pieces to include in the response. + * @param bool $is_debug Whether debug mode is enabled. * * @return array The composed schema response. */ - public function compose( Schema_Piece_Collection $schema_pieces ): array { + public function compose( Schema_Piece_Collection $schema_pieces, bool $is_debug ): array { $composed_pieces = []; foreach ( $schema_pieces->to_array() as $piece ) { $composed_pieces[] = \array_merge( @@ -28,13 +29,15 @@ public function compose( Schema_Piece_Collection $schema_pieces ): array { $piece->get_data() ); } - $composed_pieces[] = - [ - '@context' => 'https://schema.org', - '@type' => 'Thing', - 'name' => 'Yoast SEO schema aggregator version', - 'identifier' => '0.1', - ]; + if ( $is_debug ) { + $composed_pieces[] = + [ + '@context' => 'https://schema.org', + '@type' => 'Thing', + 'name' => 'Yoast SEO schema aggregator version', + 'identifier' => '0.1', + ]; + } return $composed_pieces; } diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 9fe3c49bc83..0ebdda56bc2 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -144,13 +144,17 @@ public function get_permission_callback(): bool { */ public function aggregate_site_schema( WP_REST_Request $request ) { $post_type = $request->get_param( 'post_type' ); + $is_debug = (bool) $request->get_param( 'debug' ); $page = ( $request->get_param( 'page' ) ?? 1 ); $per_page = $this->config->get_per_page( $post_type ); $output = $this->cache_manager->get( $post_type, $page, $per_page ); + if ( $is_debug ) { + $output = null; + } if ( $output === null ) { try { - $output = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type ) ); + $output = $this->aggregate_site_schema_command_handler->handle( new Aggregate_Site_Schema_Command( $page, $per_page, $post_type, $is_debug ) ); $this->cache_manager->set( $post_type, $page, $per_page, $output ); } catch ( Exception $exception ) { diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php index a759b52ba8e..68a3b418cfc 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Handle_Test.php @@ -56,7 +56,7 @@ public function test_handle_orchestrates_aggregation_process( $this->schema_response_composer ->expects( 'compose' ) ->once() - ->with( $aggregated_pieces ) + ->with( $aggregated_pieces, false ) ->andReturn( $composed_response ); $result = $this->instance->handle( $command ); From d72f95feb2a1fa62ed8ac56fc2fbf2aaa5a69df5 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 27 Jan 2026 12:05:20 +0100 Subject: [PATCH 260/319] Add proper @codeCoverageIgnore annotation --- .../indexable-repository/indexable-repository.php | 1 + .../indexable-repository/wordpress-query-repository.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php index eda05e39b26..1bd3dd371f6 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php @@ -29,6 +29,7 @@ public function __construct( Base_Indexable_Repository $indexable_repository ) { /** * Retrieves existing public indexables in a paginated manner. * + * @codeCoverageIgnore -- This is a wrapper for indexable_Repository::find_all_public_paginated, which has dedicated integration tests. * @param int $page The page number. * @param int $page_size The number of items per page. * @param string $post_type The post type to filter by. diff --git a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php index 51449590c18..729bad15aa2 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php @@ -40,6 +40,8 @@ public function __construct( Indexable_Builder $indexable_builder, Pure_Indexabl /** * Builds on-the-fly public indexables in a paginated manner. * + * @codeCoverageIgnore -- This is covered by dedicated integration tests. + * * @param int $page The page number. * @param int $page_size The number of items per page. * @param string $post_type The post type to filter by. From 1af1935674912251f1c3bb43b6420495e5bb9f11 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 27 Jan 2026 12:05:35 +0100 Subject: [PATCH 261/319] Add unit tests --- ...ebPage_Schema_Node_Should_Filter_Test.php} | 4 +- .../Indexable_Repository/Constructor_Test.php | 56 +++++++++++++++ ...ract_Indexable_Repository_Factory_Test.php | 52 ++++++++++++++ .../Constructor_Test.php | 34 +++++++++ .../Get_Repository_Test.php | 27 +++++++ .../Constructor_Test.php | 70 +++++++++++++++++++ 6 files changed, 241 insertions(+), 2 deletions(-) rename tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/{WebPage_Schema_Node_Filter_Test.php => WebPage_Schema_Node_Should_Filter_Test.php} (95%) create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Get_Repository_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Should_Filter_Test.php similarity index 95% rename from tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php rename to tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Should_Filter_Test.php index ef6167043e4..655601e7054 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Should_Filter_Test.php @@ -11,11 +11,11 @@ /** * Tests the WebPage_Schema_Node_Filter class. * - * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\WebPage_Schema_Node_Filter::filter + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\WebPage_Schema_Node_Filter::should_filter * * @group schema-aggregator */ -final class WebPage_Schema_Node_Filter_Test extends TestCase { +final class WebPage_Schema_Node_Should_Filter_Test extends TestCase { /** * The instance of WebPage_Schema_Node_Filter being tested. diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php new file mode 100644 index 00000000000..e8f6d3e26c4 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php @@ -0,0 +1,56 @@ +indexable_repository = Mockery::mock( Base_Indexable_Repository::class ); + $this->instance = new Indexable_Repository( $this->indexable_repository ); + } + + /** + * Tests if the constructor sets properties correctly. + * + * @return void + */ + public function test_constructor(): void { + $this->assertInstanceOf( + Base_Indexable_Repository::class, + $this->getPropertyValue( $this->instance, 'indexable_repository' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php new file mode 100644 index 00000000000..87fe6f91354 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php @@ -0,0 +1,52 @@ +indexable_repository = Mockery::mock( Indexable_Repository::class ); + $this->wordpress_query_repository = Mockery::mock( WordPress_Query_Repository::class ); + $this->instance = new Indexable_Repository_Factory( + $this->indexable_repository, + $this->wordpress_query_repository + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php new file mode 100644 index 00000000000..480b29a90c9 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php @@ -0,0 +1,34 @@ +assertInstanceOf( + Indexable_Repository::class, + $this->getPropertyValue( $this->instance, 'native_repository' ) + ); + + $this->assertInstanceOf( + WordPress_Query_Repository::class, + $this->getPropertyValue( $this->instance, 'wordpress_repository' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Get_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Get_Repository_Test.php new file mode 100644 index 00000000000..ac024f6f9c7 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Get_Repository_Test.php @@ -0,0 +1,27 @@ +instance->get_repository( true ); + $this->assertSame( $this->indexable_repository, $repository ); + + $repository = $this->instance->get_repository( false ); + $this->assertSame( $this->wordpress_query_repository, $repository ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php new file mode 100644 index 00000000000..7393c2209e8 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php @@ -0,0 +1,70 @@ +indexable_builder = Mockery::mock( Indexable_Builder::class ); + $this->indexable_repository = Mockery::mock( Pure_Indexable_Repository::class ); + $this->instance = new WordPress_Query_Repository( $this->indexable_builder, $this->indexable_repository ); + } + + /** + * Tests if the constructor sets properties correctly. + * + * @return void + */ + public function test_constructor(): void { + $this->assertInstanceOf( + Indexable_Builder::class, + $this->getPropertyValue( $this->instance, 'indexable_builder' ) + ); + + $this->assertInstanceOf( + Pure_Indexable_Repository::class, + $this->getPropertyValue( $this->instance, 'indexable_repository' ) + ); + } +} From 7ae4fbd4e565e67aa707c3502e5d1c588904dc90 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 27 Jan 2026 12:05:49 +0100 Subject: [PATCH 262/319] Add integration tests --- .../Indexable_Repository_Test.php | 245 ++++++++++++++++++ .../WordPress_Query_Repository_Test.php | 200 ++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 tests/WP/Repositories/Indexable_Repository_Test.php create mode 100644 tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php diff --git a/tests/WP/Repositories/Indexable_Repository_Test.php b/tests/WP/Repositories/Indexable_Repository_Test.php new file mode 100644 index 00000000000..27f349646e1 --- /dev/null +++ b/tests/WP/Repositories/Indexable_Repository_Test.php @@ -0,0 +1,245 @@ + + */ + private $created_indexables = []; + + /** + * Sets up the test class. + * + * @return void + */ + public function set_up(): void { + parent::set_up(); + + global $wpdb; + + // Clean up any existing indexables. + $wpdb->query( "DELETE FROM {$wpdb->prefix}yoast_indexable" ); + + $this->instance = \YoastSEO()->classes->get( Indexable_Repository::class ); + $this->create_test_indexables(); + } + + /** + * Tears down the test class. + * + * @return void + */ + public function tear_down(): void { + global $wpdb; + + // Clean up all indexables to ensure clean state. + $wpdb->query( "DELETE FROM {$wpdb->prefix}yoast_indexable" ); + + parent::tear_down(); + } + + /** + * Tests the find_all_public_paginated method with real database data. + * + * @dataProvider find_all_public_paginated_data + * @covers ::find_all_public_paginated + * + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. + * @param int $expected_count The expected number of results. + * @param array $expected_properties Expected properties to check in results. + * + * @return void + */ + public function test_find_all_public_paginated( int $page, int $page_size, string $post_type, int $expected_count, array $expected_properties ): void { + $result = $this->instance->find_all_public_paginated( $page, $page_size, $post_type ); + + $this->assertIsArray( $result, 'Result should be an array' ); + $this->assertCount( $expected_count, $result, "Should return exactly {$expected_count} indexables. Got " . \count( $result ) . " results for post type {$post_type}" ); + + if ( $expected_count > 0 ) { + foreach ( $result as $index => $indexable ) { + $this->assertNotFalse( $indexable, "Result at index {$index} should not be false" ); + + if ( $indexable !== false ) { + $this->assertInstanceOf( Indexable::class, $indexable, 'Each result should be an Indexable instance' ); + $this->assertEquals( $post_type, $indexable->object_sub_type, "Post type should be {$post_type}" ); + $this->assertEquals( 'publish', $indexable->post_status, 'Post status should be publish' ); + + foreach ( $expected_properties as $property => $value ) { + $this->assertEquals( $value, $indexable->$property, "Property {$property} should match expected value" ); + } + } + } + } + } + + /** + * Data provider for the find_all_public_paginated test. + * + * @return Generator Test data to use. + */ + public static function find_all_public_paginated_data(): Generator { + yield 'First page posts - should return 3 posts' => [ + 'page' => 1, + 'page_size' => 5, + 'post_type' => 'post', + 'expected_count' => 3, + 'expected_properties' => [ 'object_type' => 'post' ], + ]; + + yield 'Second page posts - should return 0 (only 3 exist)' => [ + 'page' => 2, + 'page_size' => 5, + 'post_type' => 'post', + 'expected_count' => 0, + 'expected_properties' => [], + ]; + + yield 'First page pages - should return 2 pages' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'page', + 'expected_count' => 2, + 'expected_properties' => [ 'object_type' => 'post' ], + ]; + + yield 'Small page size - should return 1 post' => [ + 'page' => 1, + 'page_size' => 1, + 'post_type' => 'post', + 'expected_count' => 1, + 'expected_properties' => [ 'object_type' => 'post' ], + ]; + + yield 'Third post with page size 1 - should return 1 post' => [ + 'page' => 3, + 'page_size' => 1, + 'post_type' => 'post', + 'expected_count' => 1, + 'expected_properties' => [ 'object_type' => 'post' ], + ]; + + yield 'Non-existent post type - should return 0' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'non_existent_type', + 'expected_count' => 0, + 'expected_properties' => [], + ]; + } + + /** + * Creates test indexables in the database. + * + * @return void + */ + private function create_test_indexables(): void { + global $wpdb; + + $indexables_data = [ + [ + 'object_type' => 'post', + 'object_sub_type' => 'post', + 'post_status' => 'publish', + 'is_public' => 1, + 'permalink' => 'https://example.com/post-1', + 'permalink_hash' => \strlen( 'https://example.com/post-1' ) . ':' . \md5( 'https://example.com/post-1' ), + 'created_at' => '2024-01-01 10:00:00', + 'updated_at' => '2024-01-01 10:00:00', + 'blog_id' => \get_current_blog_id(), + 'version' => 2, + 'title' => 'Post 1', + 'description' => 'Description 1', + 'breadcrumb_title' => 'Post 1', + ], + [ + 'object_type' => 'post', + 'object_sub_type' => 'post', + 'post_status' => 'publish', + 'is_public' => null, // Null should be treated as public. + 'permalink' => 'https://example.com/post-2', + 'permalink_hash' => \strlen( 'https://example.com/post-2' ) . ':' . \md5( 'https://example.com/post-2' ), + 'created_at' => '2024-01-02 10:00:00', + 'updated_at' => '2024-01-02 10:00:00', + 'blog_id' => \get_current_blog_id(), + 'version' => 2, + 'title' => 'Post 2', + 'description' => 'Description 2', + 'breadcrumb_title' => 'Post 2', + ], + [ + 'object_type' => 'post', + 'object_sub_type' => 'post', + 'post_status' => 'publish', + 'is_public' => 1, + 'permalink' => 'https://example.com/post-3', + 'permalink_hash' => \strlen( 'https://example.com/post-3' ) . ':' . \md5( 'https://example.com/post-3' ), + 'created_at' => '2024-01-03 10:00:00', + 'updated_at' => '2024-01-03 10:00:00', + 'blog_id' => \get_current_blog_id(), + 'version' => 2, + 'title' => 'Post 3', + 'description' => 'Description 3', + 'breadcrumb_title' => 'Post 3', + ], + [ + 'object_type' => 'post', + 'object_sub_type' => 'page', + 'post_status' => 'publish', + 'is_public' => 1, + 'permalink' => 'https://example.com/page-1', + 'permalink_hash' => \strlen( 'https://example.com/page-1' ) . ':' . \md5( 'https://example.com/page-1' ), + 'created_at' => '2024-01-04 10:00:00', + 'updated_at' => '2024-01-04 10:00:00', + 'blog_id' => \get_current_blog_id(), + 'version' => 2, + 'title' => 'Page 1', + 'description' => 'Description 1', + 'breadcrumb_title' => 'Page 1', + ], + [ + 'object_type' => 'post', + 'object_sub_type' => 'page', + 'post_status' => 'publish', + 'is_public' => 1, + 'permalink' => 'https://example.com/page-2', + 'permalink_hash' => \strlen( 'https://example.com/page-2' ) . ':' . \md5( 'https://example.com/page-2' ), + 'created_at' => '2024-01-05 10:00:00', + 'updated_at' => '2024-01-05 10:00:00', + 'blog_id' => \get_current_blog_id(), + 'version' => 2, + 'title' => 'Page 2', + 'description' => 'Description 2', + 'breadcrumb_title' => 'Page 2', + ], + ]; + + foreach ( $indexables_data as $data ) { + $wpdb->insert( $wpdb->prefix . 'yoast_indexable', $data ); + $this->created_indexables[] = $wpdb->insert_id; + } + } +} diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php new file mode 100644 index 00000000000..3cdaf4543b0 --- /dev/null +++ b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php @@ -0,0 +1,200 @@ + + */ + private $created_posts = []; + + /** + * Sets up the test class. + * + * @return void + */ + public function set_up(): void { + parent::set_up(); + + $indexable_builder = \YoastSEO()->classes->get( Indexable_Builder::class ); + $pure_indexable_repository = \YoastSEO()->classes->get( Pure_Indexable_Repository::class ); + + $this->instance = new WordPress_Query_Repository( $indexable_builder, $pure_indexable_repository ); + $this->create_test_content(); + } + + /** + * Tears down the test class. + * + * @return void + */ + public function tear_down(): void { + foreach ( $this->created_posts as $post_id ) { + \wp_delete_post( $post_id, true ); + } + + parent::tear_down(); + } + + /** + * Tests the get method. + * + * @dataProvider get_data + * @covers ::get + * + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. + * @param int $min_expected The minimum expected number of results. + * @param array $expected_properties Expected properties to check in results. + * @param bool $should_have_results Whether results are expected. + * + * @return void + */ + public function test_get( int $page, int $page_size, string $post_type, int $min_expected, array $expected_properties, bool $should_have_results ): void { + $result = $this->instance->get( $page, $page_size, $post_type ); + + $this->assertIsArray( $result, 'Result should be an array' ); + $this->assertGreaterThanOrEqual( $min_expected, \count( $result ), "Should return at least {$min_expected} indexables for post type {$post_type}" ); + + if ( $should_have_results ) { + $this->assertNotEmpty( $result, 'Should have results when expected' ); + + foreach ( $result as $indexable ) { + $this->assertInstanceOf( Indexable::class, $indexable, 'Each result should be an Indexable instance' ); + $this->assertTrue( $indexable->is_public === true || $indexable->is_public === null, 'Should be public or null' ); + + foreach ( $expected_properties as $property => $value ) { + $this->assertEquals( $value, $indexable->$property, "Property {$property} should match expected value" ); + } + } + } else { + $this->assertEmpty( $result, 'Should have no results when not expected' ); + } + } + + /** + * Tests the get method with pagination. + * + * @covers ::get + * + * @return void + */ + public function test_get_pagination_returns_different_results(): void { + $page_1 = $this->instance->get( 1, 1, 'post' ); + $page_2 = $this->instance->get( 2, 1, 'post' ); + + $this->assertIsArray( $page_1 ); + $this->assertIsArray( $page_2 ); + $this->assertCount( 1, $page_1, 'First page should return exactly 1 result with page size 1' ); + $this->assertCount( 1, $page_2, 'Second page should return exactly 1 result with page size 1' ); + + $this->assertNotEquals( + $page_1[0]->object_id ?? null, + $page_2[0]->object_id ?? null, + 'Different pages should return different posts' + ); + } + + /** + * Data provider for the get test. + * + * @return Generator Test data to use. + */ + public static function get_data(): Generator { + yield 'First page posts' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'post', + 'min_expected' => 3, + 'expected_properties' => [ 'object_type' => 'post' ], + 'should_have_results' => true, + ]; + + yield 'First page pages' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'page', + 'min_expected' => 2, + 'expected_properties' => [], + 'should_have_results' => true, + ]; + + yield 'Small page size' => [ + 'page' => 1, + 'page_size' => 1, + 'post_type' => 'post', + 'min_expected' => 1, + 'expected_properties' => [ 'object_type' => 'post' ], + 'should_have_results' => true, + ]; + + yield 'High page number - should return 0' => [ + 'page' => 10, + 'page_size' => 5, + 'post_type' => 'post', + 'min_expected' => 0, + 'expected_properties' => [], + 'should_have_results' => false, + ]; + + yield 'Non-existent post type' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'non_existent_type', + 'min_expected' => 0, + 'expected_properties' => [], + 'should_have_results' => false, + ]; + } + + /** + * Creates test content using WordPress factories. + * + * @return void + */ + private function create_test_content(): void { + $post_ids = self::factory()->post->create_many( + 3, + [ + 'post_title' => 'Test Post', + 'post_status' => 'publish', + 'post_type' => 'post', + ] + ); + $this->created_posts = \array_merge( $this->created_posts, $post_ids ); + + $page_ids = self::factory()->post->create_many( + 2, + [ + 'post_title' => 'Test Page', + 'post_status' => 'publish', + 'post_type' => 'page', + ] + ); + $this->created_posts = \array_merge( $this->created_posts, $page_ids ); + } +} From 4e43d7db5a0d0488885af2b3e50d30d531f80ebb Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 27 Jan 2026 12:19:04 +0100 Subject: [PATCH 263/319] Fix cs --- .../WordPress_Query_Repository_Test.php | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php index 3cdaf4543b0..ab9a8a330ff 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php @@ -39,7 +39,7 @@ final class WordPress_Query_Repository_Test extends TestCase { public function set_up(): void { parent::set_up(); - $indexable_builder = \YoastSEO()->classes->get( Indexable_Builder::class ); + $indexable_builder = \YoastSEO()->classes->get( Indexable_Builder::class ); $pure_indexable_repository = \YoastSEO()->classes->get( Pure_Indexable_Repository::class ); $this->instance = new WordPress_Query_Repository( $indexable_builder, $pure_indexable_repository ); @@ -65,12 +65,12 @@ public function tear_down(): void { * @dataProvider get_data * @covers ::get * - * @param int $page The page number. - * @param int $page_size The number of items per page. - * @param string $post_type The post type to filter by. - * @param int $min_expected The minimum expected number of results. - * @param array $expected_properties Expected properties to check in results. - * @param bool $should_have_results Whether results are expected. + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. + * @param int $min_expected The minimum expected number of results. + * @param array $expected_properties Expected properties to check in results. + * @param bool $should_have_results Whether results are expected. * * @return void */ @@ -91,7 +91,8 @@ public function test_get( int $page, int $page_size, string $post_type, int $min $this->assertEquals( $value, $indexable->$property, "Property {$property} should match expected value" ); } } - } else { + } + else { $this->assertEmpty( $result, 'Should have no results when not expected' ); } } @@ -113,8 +114,8 @@ public function test_get_pagination_returns_different_results(): void { $this->assertCount( 1, $page_2, 'Second page should return exactly 1 result with page size 1' ); $this->assertNotEquals( - $page_1[0]->object_id ?? null, - $page_2[0]->object_id ?? null, + ( $page_1[0]->object_id ?? null ), + ( $page_2[0]->object_id ?? null ), 'Different pages should return different posts' ); } @@ -177,7 +178,7 @@ public static function get_data(): Generator { * @return void */ private function create_test_content(): void { - $post_ids = self::factory()->post->create_many( + $post_ids = self::factory()->post->create_many( 3, [ 'post_title' => 'Test Post', @@ -187,7 +188,7 @@ private function create_test_content(): void { ); $this->created_posts = \array_merge( $this->created_posts, $post_ids ); - $page_ids = self::factory()->post->create_many( + $page_ids = self::factory()->post->create_many( 2, [ 'post_title' => 'Test Page', From a535384f3da35f09a4b74bd238f07b5714420c48 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 27 Jan 2026 13:24:53 +0100 Subject: [PATCH 264/319] update @ covers tags --- tests/WP/Repositories/Indexable_Repository_Test.php | 3 +-- .../Indexable_Repository/WordPress_Query_Repository_Test.php | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/WP/Repositories/Indexable_Repository_Test.php b/tests/WP/Repositories/Indexable_Repository_Test.php index 27f349646e1..7ea9154ac70 100644 --- a/tests/WP/Repositories/Indexable_Repository_Test.php +++ b/tests/WP/Repositories/Indexable_Repository_Test.php @@ -10,7 +10,7 @@ /** * Integration Test Class for Indexable_Repository. * - * @coversDefaultClass \Yoast\WP\SEO\Repositories\Indexable_Repository + * @covers \Yoast\WP\SEO\Repositories\Indexable_Repository::find_all_public_paginated */ final class Indexable_Repository_Test extends TestCase { @@ -63,7 +63,6 @@ public function tear_down(): void { * Tests the find_all_public_paginated method with real database data. * * @dataProvider find_all_public_paginated_data - * @covers ::find_all_public_paginated * * @param int $page The page number. * @param int $page_size The number of items per page. diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php index ab9a8a330ff..8507371eaf0 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php @@ -13,7 +13,7 @@ /** * Integration Test Class for WordPress_Query_Repository. * - * @coversDefaultClass \Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\WordPress_Query_Repository + * @covers \Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\WordPress_Query_Repository::get */ final class WordPress_Query_Repository_Test extends TestCase { @@ -63,7 +63,6 @@ public function tear_down(): void { * Tests the get method. * * @dataProvider get_data - * @covers ::get * * @param int $page The page number. * @param int $page_size The number of items per page. @@ -100,8 +99,6 @@ public function test_get( int $page, int $page_size, string $post_type, int $min /** * Tests the get method with pagination. * - * @covers ::get - * * @return void */ public function test_get_pagination_returns_different_results(): void { From ae28988a431a7ffc36fa1d32bdacd9601f9fd7c4 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 27 Jan 2026 16:02:05 +0100 Subject: [PATCH 265/319] Refactor the elements-context map to be a class This allows us to exclude it from unit tests. --- .../elements-context-map/base-map-loader.php | 6 +- .../default-elements-context-map.php | 2731 +++++++++-------- 2 files changed, 1379 insertions(+), 1358 deletions(-) diff --git a/src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php index 6b15edddd88..151e10eec66 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/base-map-loader.php @@ -3,7 +3,9 @@ namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map; /** - * Map loader default implementation.. + * Map loader default implementation. + * + * @codeCoverageIgnore -- No logic to test. */ class Base_Map_Loader implements Map_Loader_Interface { @@ -13,6 +15,6 @@ class Base_Map_Loader implements Map_Loader_Interface { * @return array> The elements context map. */ public function load(): array { - return include __DIR__ . '/default-elements-context-map.php'; + return Default_Elements_Context_Map::get(); } } diff --git a/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php b/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php index 6e3e7cbee6e..bf6d03d4039 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php @@ -1,1362 +1,1381 @@ > + */ + private static $map = [ + 'action' => [ + 'Action', + 'AcceptAction', + 'AchieveAction', + 'ActivateAction', + 'AddAction', + 'AgreeAction', + 'AllocateAction', + 'AppendAction', + 'ApplyAction', + 'ArriveAction', + 'AskAction', + 'AssessAction', + 'AssignAction', + 'AuthorizeAction', + 'BefriendAction', + 'BookmarkAction', + 'BorrowAction', + 'BuyAction', + 'CancelAction', + 'CheckAction', + 'CheckInAction', + 'CheckOutAction', + 'ChooseAction', + 'ClaimAction', + 'CommentAction', + 'CommunicateAction', + 'ConfirmAction', + 'ConsumeAction', + 'ControlAction', + 'CookAction', + 'CreateAction', + 'DeactivateAction', + 'DeleteAction', + 'DepartAction', + 'DisagreeAction', + 'DiscoverAction', + 'DislikeAction', + 'DonateAction', + 'DownloadAction', + 'DrawAction', + 'DrinkAction', + 'EatAction', + 'EditAction', + 'EndorseAction', + 'ExerciseAction', + 'FilmAction', + 'FindAction', + 'FollowAction', + 'GiveAction', + 'IgnoreAction', + 'InformAction', + 'InsertAction', + 'InstallAction', + 'InteractAction', + 'InviteAction', + 'JoinAction', + 'LeaveAction', + 'LendAction', + 'LikeAction', + 'ListenAction', + 'LoseAction', + 'MarryAction', + 'MoneyTransfer', + 'MoveAction', + 'OrderAction', + 'OrganizeAction', + 'PaintAction', + 'PayAction', + 'PerformAction', + 'PhotographAction', + 'PlanAction', + 'PlayAction', + 'PreOrderAction', + 'PrependAction', + 'QuoteAction', + 'ReactAction', + 'ReadAction', + 'ReceiveAction', + 'RegisterAction', + 'RejectAction', + 'RentAction', + 'ReplaceAction', + 'ReplyAction', + 'ReportAction', + 'ReserveAction', + 'ResumeAction', + 'ReturnAction', + 'ReviewAction', + 'RsvpAction', + 'ScheduleAction', + 'SearchAction', + 'SeekToAction', + 'SellAction', + 'SendAction', + 'ShareAction', + 'SubscribeAction', + 'SuspendAction', + 'TakeAction', + 'TieAction', + 'TipAction', + 'TrackAction', + 'TradeAction', + 'TransferAction', + 'TravelAction', + 'UnRegisterAction', + 'UpdateAction', + 'UseAction', + 'ViewAction', + 'VoteAction', + 'WantAction', + 'WatchAction', + 'WearAction', + 'WinAction', + 'WriteAction', + ], + 'commerce' => [ + 'Product', + 'Car', + 'Drug', + 'DietarySupplement', + 'IndividualProduct', + 'Motorcycle', + 'ProductGroup', + 'ProductModel', + 'SomeProducts', + 'Vehicle', + 'BusOrCoach', + 'MotorizedBicycle', + 'Offer', + 'AggregateOffer', + 'Demand', + 'Order', + 'OrderItem', + 'Invoice', + 'PriceSpecification', + 'CompoundPriceSpecification', + 'DeliveryChargeSpecification', + 'PaymentChargeSpecification', + 'UnitPriceSpecification', + 'ShippingConditions', + 'ShippingDeliveryTime', + 'ShippingRateSettings', + 'ShippingService', + 'MerchantReturnPolicy', + 'MerchantReturnPolicySeasonalOverride', + 'OfferShippingDetails', + 'OfferCatalog', + 'ParcelDelivery', + 'FinancialProduct', + 'BankAccount', + 'CurrencyConversionService', + 'DepositAccount', + 'InvestmentFund', + 'InvestmentOrDeposit', + 'LoanOrCredit', + 'MortgageLoan', + 'PaymentCard', + 'CreditCard', + 'PaymentService', + ], + 'content' => [ + 'CreativeWork', + 'AmpStory', + 'AnalysisNewsArticle', + 'Answer', + 'ArchiveComponent', + 'Article', + 'AskPublicNewsArticle', + 'Atlas', + 'Audiobook', + 'BackgroundNewsArticle', + 'Blog', + 'BlogPosting', + 'Book', + 'BookSeries', + 'Certification', + 'Chapter', + 'Claim', + 'Clip', + 'Code', + 'Collection', + 'ComicCoverArt', + 'ComicIssue', + 'ComicSeries', + 'ComicStory', + 'Comment', + 'Conversation', + 'CorrectionComment', + 'Course', + 'CoverArt', + 'CreativeWorkSeason', + 'CreativeWorkSeries', + 'CriticReview', + 'DataCatalog', + 'DataDownload', + 'Dataset', + 'DefinedTermSet', + 'Diet', + 'DigitalDocument', + 'DiscussionForumPosting', + 'Drawing', + 'EducationalOccupationalCredential', + 'EmailMessage', + 'Episode', + 'ExercisePlan', + 'FAQPage', + 'Game', + 'Guide', + 'HowTo', + 'HowToDirection', + 'HowToSection', + 'HowToStep', + 'HowToTip', + 'HyperToc', + 'HyperTocEntry', + 'ImageGallery', + 'Legislation', + 'LegislationObject', + 'LiveBlogPosting', + 'Manuscript', + 'Map', + 'MathSolver', + 'MediaGallery', + 'MediaObject', + 'MediaReview', + 'MediaReviewItem', + 'Menu', + 'MenuSection', + 'Message', + 'Movie', + 'MovieClip', + 'MovieSeries', + 'MusicAlbum', + 'MusicComposition', + 'MusicPlaylist', + 'MusicRecording', + 'MusicRelease', + 'MusicVideoObject', + 'NewsArticle', + 'Newspaper', + 'NoteDigitalDocument', + 'OpinionNewsArticle', + 'Painting', + 'Periodical', + 'Photograph', + 'Play', + 'Poster', + 'PresentationDigitalDocument', + 'ProductCollection', + 'PublicationIssue', + 'PublicationVolume', + 'Question', + 'Quiz', + 'Quotation', + 'RadioClip', + 'RadioEpisode', + 'RadioSeason', + 'RadioSeries', + 'Recipe', + 'Recommendation', + 'Report', + 'ReportageNewsArticle', + 'Review', + 'ReviewNewsArticle', + 'SatiricalArticle', + 'ScholarlyArticle', + 'Sculpture', + 'Season', + 'SheetMusic', + 'ShortStory', + 'SocialMediaPosting', + 'SoftwareApplication', + 'SoftwareSourceCode', + 'SpecialAnnouncement', + 'SpreadsheetDigitalDocument', + 'Statement', + 'TechArticle', + 'TextDigitalDocument', + 'Thesis', + 'TVClip', + 'TVEpisode', + 'TVSeason', + 'TVSeries', + 'UserBlocks', + 'UserCheckins', + 'UserComments', + 'UserDownloads', + 'UserInteraction', + 'UserLikes', + 'UserPageVisits', + 'UserPlays', + 'UserPlusOnes', + 'UserTweets', + 'VideoClip', + 'VideoGallery', + 'VideoGame', + 'VideoGameClip', + 'VideoGameSeries', + 'VideoObject', + 'VideoObjectSnapshot', + 'VisualArtwork', + 'WebContent', + '3DModel', + 'AudioObject', + 'AudioObjectSnapshot', + 'ImageObject', + 'ImageObjectSnapshot', + 'JobPosting', + 'HowToItem', + 'HowToSupply', + 'HowToTool', + 'MenuItem', + 'Trip', + 'BoatTrip', + 'BusTrip', + 'Flight', + 'TouristTrip', + 'TrainTrip', + ], + 'data' => [ + 'Intangible', + 'ActionAccessSpecification', + 'AlignmentObject', + 'Audience', + 'BedDetails', + 'Brand', + 'BroadcastChannel', + 'BroadcastFrequencySpecification', + 'ComputerLanguage', + 'DataFeedItem', + 'DefinedTerm', + 'CategoryCode', + 'DefinedRegion', + 'DigitalDocumentPermission', + 'EnergyConsumptionDetails', + 'EntryPoint', + 'FinancialIncentive', + 'FloorPlan', + 'GameServer', + 'GeospatialGeometry', + 'Grant', + 'MonetaryGrant', + 'HealthInsurancePlan', + 'HealthPlanCostSharingSpecification', + 'HealthPlanFormulary', + 'HealthPlanNetwork', + 'Language', + 'MediaSubscription', + 'MemberProgram', + 'Observation', + 'Occupation', + 'OccupationalExperienceRequirements', + 'Permit', + 'GovernmentPermit', + 'ProgramMembership', + 'PropertyValueSpecification', + 'Quantity', + 'Distance', + 'Duration', + 'Energy', + 'Mass', + 'Rating', + 'AggregateRating', + 'EndorsementRating', + 'EmployerAggregateRating', + 'Reservation', + 'BoatReservation', + 'BusReservation', + 'EventReservation', + 'FlightReservation', + 'FoodEstablishmentReservation', + 'LodgingReservation', + 'RentalCarReservation', + 'ReservationPackage', + 'TaxiReservation', + 'TrainReservation', + 'Role', + 'LinkRole', + 'OrganizationRole', + 'EmployeeRole', + 'PerformanceRole', + 'Schedule', + 'Seat', + 'Service', + 'BroadcastService', + 'CableOrSatelliteService', + 'FoodService', + 'GovernmentService', + 'TaxiService', + 'WebAPI', + 'ServiceChannel', + 'SpeakableSpecification', + 'StatisticalPopulation', + 'StructuredValue', + 'CDCPMDRecord', + 'ContactPoint', + 'PostalAddress', + 'DatedMoneySpecification', + 'DeliveryTimeSettings', + 'EngineSpecification', + 'ExchangeRateSpecification', + 'GeoCircle', + 'GeoCoordinates', + 'GeoShape', + 'InteractionCounter', + 'MonetaryAmount', + 'MonetaryAmountDistribution', + 'NutritionInformation', + 'OpeningHoursSpecification', + 'OwnershipInfo', + 'PostalCodeRangeSpecification', + 'PropertyValue', + 'LocationFeatureSpecification', + 'QuantitativeValue', + 'QuantitativeValueDistribution', + 'RepaymentSpecification', + 'ServicePeriod', + 'TypeAndQuantityNode', + 'WarrantyPromise', + 'Ticket', + 'VirtualLocation', + 'DataType', + 'Boolean', + 'False', + 'True', + 'Date', + 'DateTime', + 'Number', + 'Float', + 'Integer', + 'Text', + 'CssSelectorType', + 'PronounceableText', + 'URL', + 'XPathType', + 'Time', + ], + 'entity' => [ + 'Thing', + 'Person', + 'Patient', + 'Organization', + 'Airline', + 'Consortium', + 'Cooperative', + 'Corporation', + 'EducationalOrganization', + 'CollegeOrUniversity', + 'ElementarySchool', + 'HighSchool', + 'MiddleSchool', + 'Preschool', + 'School', + 'FundingScheme', + 'GovernmentOrganization', + 'LibrarySystem', + 'LocalBusiness', + 'MedicalOrganization', + 'DiagnosticLab', + 'Hospital', + 'MedicalClinic', + 'Pharmacy', + 'Physician', + 'VeterinaryCare', + 'MemberProgramTier', + 'NGO', + 'NewsMediaOrganization', + 'OnlineBusiness', + 'OnlineStore', + 'PerformingGroup', + 'DanceGroup', + 'MusicGroup', + 'TheaterGroup', + 'PoliticalParty', + 'Project', + 'FundingAgency', + 'ResearchProject', + 'ResearchOrganization', + 'SearchRescueOrganization', + 'SportsOrganization', + 'SportsTeam', + 'WorkersUnion', + 'AccountingService', + 'AnimalShelter', + 'ArchiveOrganization', + 'AutoBodyShop', + 'AutoDealer', + 'AutoPartsStore', + 'AutoRental', + 'AutoRepair', + 'AutoWash', + 'AutomatedTeller', + 'AutomotiveBusiness', + 'Bakery', + 'BankOrCreditUnion', + 'BarOrPub', + 'BeautySalon', + 'BedAndBreakfast', + 'BikeStore', + 'BookStore', + 'BowlingAlley', + 'Brewery', + 'CafeOrCoffeeShop', + 'Campground', + 'Casino', + 'ChildCare', + 'ClothingStore', + 'ComputerStore', + 'ConvenienceStore', + 'DaySpa', + 'Dentist', + 'DepartmentStore', + 'DistilleryOrganization', + 'Distillery', + 'DryCleaningOrLaundry', + 'ElectronicsStore', + 'EmploymentAgency', + 'EntertainmentBusiness', + 'AdultEntertainment', + 'AmusementPark', + 'ArtGallery', + 'ComedyClub', + 'MovieTheater', + 'NightClub', + 'ExerciseGym', + 'FinancialService', + 'Florist', + 'FoodEstablishment', + 'FurnitureStore', + 'GardenStore', + 'GasStation', + 'GeneralContractor', + 'GolfCourse', + 'GovernmentOffice', + 'PostOffice', + 'GroceryStore', + 'HairSalon', + 'HardwareStore', + 'HealthAndBeautyBusiness', + 'HealthClub', + 'HobbyShop', + 'HomeAndConstructionBusiness', + 'Electrician', + 'HVACBusiness', + 'HousePainter', + 'Locksmith', + 'MovingCompany', + 'Plumber', + 'RoofingContractor', + 'HomeGoodsStore', + 'Hostel', + 'Hotel', + 'IceCreamShop', + 'InsuranceAgency', + 'InternetCafe', + 'JewelryStore', + 'LegalService', + 'Attorney', + 'Notary', + 'Library', + 'LiquorStore', + 'LodgingBusiness', + 'MedicalBusiness', + 'MensClothingStore', + 'MobilePhoneStore', + 'Motel', + 'MotorcycleDealer', + 'MotorcycleRepair', + 'MovieRentalStore', + 'MusicStore', + 'NailSalon', + 'OfficeEquipmentStore', + 'Optician', + 'OutletStore', + 'PawnShop', + 'PetStore', + 'ProfessionalService', + 'RadioStation', + 'RealEstateAgent', + 'RecyclingCenter', + 'Resort', + 'Restaurant', + 'FastFoodRestaurant', + 'SelfStorage', + 'ShoeStore', + 'ShoppingCenter', + 'SkiResort', + 'SportingGoodsStore', + 'SportsActivityLocation', + 'StadiumOrArena', + 'Store', + 'TattooParlor', + 'TelevisionStation', + 'TennisComplex', + 'TireShop', + 'TouristInformationCenter', + 'ToyStore', + 'TravelAgency', + 'WholesaleStore', + 'Winery', + 'Place', + 'Accommodation', + 'Apartment', + 'CampingPitch', + 'House', + 'SingleFamilyResidence', + 'Room', + 'HotelRoom', + 'MeetingRoom', + 'Suite', + 'AdministrativeArea', + 'City', + 'Country', + 'SchoolDistrict', + 'State', + 'CivicStructure', + 'Airport', + 'Aquarium', + 'Beach', + 'BoatTerminal', + 'Bridge', + 'BusStation', + 'BusStop', + 'Cemetery', + 'Crematorium', + 'EventVenue', + 'FireStation', + 'GovernmentBuilding', + 'CityHall', + 'Courthouse', + 'DefenceEstablishment', + 'Embassy', + 'LegislativeBuilding', + 'Museum', + 'MusicVenue', + 'Park', + 'ParkingFacility', + 'PerformingArtsTheater', + 'PlaceOfWorship', + 'BuddhistTemple', + 'Church', + 'CatholicChurch', + 'HinduTemple', + 'Mosque', + 'Synagogue', + 'Playground', + 'PoliceStation', + 'PublicToilet', + 'RVPark', + 'SubwayStation', + 'TaxiStand', + 'TrainStation', + 'Zoo', + 'Landform', + 'BodyOfWater', + 'Canal', + 'LakeBodyOfWater', + 'OceanBodyOfWater', + 'Pond', + 'Reservoir', + 'RiverBodyOfWater', + 'SeaBodyOfWater', + 'Waterfall', + 'Continent', + 'Mountain', + 'Volcano', + 'LandmarksOrHistoricalBuildings', + 'Residence', + 'ApartmentComplex', + 'GatedResidenceCommunity', + 'TouristAttraction', + 'TouristDestination', + 'Taxon', + ], + 'enumeration' => [ + 'RespiratoryTherapy', + 'Enumeration', + 'ActionStatusType', + 'ActiveActionStatus', + 'CompletedActionStatus', + 'FailedActionStatus', + 'PotentialActionStatus', + 'AdultOrientedEnumeration', + 'AlcoholConsideration', + 'DangerousGoodConsideration', + 'HealthcareConsideration', + 'NarcoticConsideration', + 'ReducedRelevanceForChildrenConsideration', + 'SexualContentConsideration', + 'TobaccoNicotineConsideration', + 'UnclassifiedAdultConsideration', + 'ViolenceConsideration', + 'WeaponConsideration', + 'BoardingPolicyType', + 'GroupBoardingPolicy', + 'ZoneBoardingPolicy', + 'BodyMeasurementTypeEnumeration', + 'BodyMeasurementArm', + 'BodyMeasurementBust', + 'BodyMeasurementChest', + 'BodyMeasurementFoot', + 'BodyMeasurementHand', + 'BodyMeasurementHead', + 'BodyMeasurementHeight', + 'BodyMeasurementHips', + 'BodyMeasurementInsideLeg', + 'BodyMeasurementNeck', + 'BodyMeasurementUnderbust', + 'BodyMeasurementWaist', + 'BodyMeasurementWeight', + 'BookFormatType', + 'AudiobookFormat', + 'EBook', + 'GraphicNovel', + 'Hardcover', + 'Paperback', + 'BusinessEntityType', + 'BusinessFunction', + 'CarUsageType', + 'ContactPointOption', + 'HearingImpairedSupported', + 'TollFree', + 'DayOfWeek', + 'Friday', + 'Monday', + 'PublicHolidays', + 'Saturday', + 'Sunday', + 'Thursday', + 'Tuesday', + 'Wednesday', + 'DeliveryMethod', + 'LockerDelivery', + 'OnSitePickup', + 'ParcelService', + 'DigitalDocumentPermissionType', + 'CommentPermission', + 'ReadPermission', + 'WritePermission', + 'DigitalPlatformEnumeration', + 'AndroidPlatform', + 'DesktopWebPlatform', + 'GenericWebPlatform', + 'IOSPlatform', + 'MobileWebPlatform', + 'DigitalSourceType', + 'AlgorithmicMediaDigitalSource', + 'AlgorithmicallyEnhancedDigitalSource', + 'CompositeCaptureDigitalSource', + 'CompositeDigitalSource', + 'CompositeSyntheticDigitalSource', + 'CompositeWithTrainedAlgorithmicMediaDigitalSource', + 'DataDrivenMediaDigitalSource', + 'DigitalArtDigitalSource', + 'DigitalCaptureDigitalSource', + 'MinorHumanEditsDigitalSource', + 'MultiFrameComputationalCaptureDigitalSource', + 'NegativeFilmDigitalSource', + 'PositiveFilmDigitalSource', + 'PrintDigitalSource', + 'ScreenCaptureDigitalSource', + 'TrainedAlgorithmicMediaDigitalSource', + 'VirtualRecordingDigitalSource', + 'DriveWheelConfigurationValue', + 'AllWheelDriveConfiguration', + 'FourWheelDriveConfiguration', + 'FrontWheelDriveConfiguration', + 'RearWheelDriveConfiguration', + 'DrugCostCategory', + 'ReimbursementCap', + 'Retail', + 'Wholesale', + 'DrugPregnancyCategory', + 'FDAcategoryA', + 'FDAcategoryB', + 'FDAcategoryC', + 'FDAcategoryD', + 'FDAcategoryX', + 'FDAnotEvaluated', + 'DrugPrescriptionStatus', + 'OTC', + 'PrescriptionOnly', + 'EUEnergyEfficiencyEnumeration', + 'EUEnergyEfficiencyCategoryA', + 'EUEnergyEfficiencyCategoryA1Plus', + 'EUEnergyEfficiencyCategoryA2Plus', + 'EUEnergyEfficiencyCategoryA3Plus', + 'EUEnergyEfficiencyCategoryB', + 'EUEnergyEfficiencyCategoryC', + 'EUEnergyEfficiencyCategoryD', + 'EUEnergyEfficiencyCategoryE', + 'EUEnergyEfficiencyCategoryF', + 'EUEnergyEfficiencyCategoryG', + 'EnergyStarEnergyEfficiencyEnumeration', + 'EventAttendanceModeEnumeration', + 'MixedEventAttendanceMode', + 'OfflineEventAttendanceMode', + 'OnlineEventAttendanceMode', + 'EventStatusType', + 'EventCancelled', + 'EventMovedOnline', + 'EventPostponed', + 'EventRescheduled', + 'EventScheduled', + 'FulfillmentTypeEnumeration', + 'FulfillmentTypeDelivery', + 'FulfillmentTypePickup', + 'GameAvailabilityEnumeration', + 'DemoGameAvailability', + 'FullGameAvailability', + 'GamePlayMode', + 'CoOp', + 'MultiPlayer', + 'SinglePlayer', + 'GameServerStatus', + 'OfflinePermanently', + 'OfflineTemporarily', + 'Online', + 'OnlineFull', + 'GenderType', + 'Female', + 'Male', + 'GovernmentBenefitsType', + 'BasicIncome', + 'BusinessSupport', + 'DisabilitySupport', + 'HealthCare', + 'OneTimePayments', + 'PaidLeave', + 'ParentalSupport', + 'UnemploymentSupport', + 'HealthAspectEnumeration', + 'AllergiesHealthAspect', + 'BenefitsHealthAspect', + 'CausesHealthAspect', + 'ContagiousnessHealthAspect', + 'EffectivenessHealthAspect', + 'GettingAccessHealthAspect', + 'HowItWorksHealthAspect', + 'HowOrWhereHealthAspect', + 'IngredientsHealthAspect', + 'LivingWithHealthAspect', + 'MayTreatHealthAspect', + 'MisconceptionsHealthAspect', + 'OverviewHealthAspect', + 'PatientExperienceHealthAspect', + 'PregnancyHealthAspect', + 'PreventionHealthAspect', + 'PrognosisHealthAspect', + 'RelatedTopicsHealthAspect', + 'RisksOrComplicationsHealthAspect', + 'SafetyHealthAspect', + 'ScreeningHealthAspect', + 'SeeDoctorHealthAspect', + 'SelfCareHealthAspect', + 'SideEffectsHealthAspect', + 'StagesHealthAspect', + 'SymptomsHealthAspect', + 'TreatmentsHealthAspect', + 'TypesHealthAspect', + 'UsageOrScheduleHealthAspect', + 'IncentiveEligibility', + 'IncentiveStatus', + 'IncentiveType', + 'ItemAvailability', + 'BackOrder', + 'Discontinued', + 'InStock', + 'InStoreOnly', + 'LimitedAvailability', + 'MadeToOrder', + 'OnlineOnly', + 'OutOfStock', + 'PreOrder', + 'PreSale', + 'Reserved', + 'SoldOut', + 'ItemListOrderType', + 'ItemListOrderAscending', + 'ItemListOrderDescending', + 'ItemListUnordered', + 'LegalForceStatus', + 'InForce', + 'NotInForce', + 'PartiallyInForce', + 'LegalValueLevel', + 'AuthoritativeLegalValue', + 'DefinitiveLegalValue', + 'OfficialLegalValue', + 'UnofficialLegalValue', + 'MapCategoryType', + 'ParkingMap', + 'SeatingMap', + 'TransitMap', + 'VenueMap', + 'MeasurementMethodEnum', + 'ExhaustEmissionsMeasurementMethod', + 'MeasurementTypeEnumeration', + 'WearableMeasurementBack', + 'WearableMeasurementChestOrBust', + 'WearableMeasurementCollar', + 'WearableMeasurementCup', + 'WearableMeasurementHeight', + 'WearableMeasurementHips', + 'WearableMeasurementInseam', + 'WearableMeasurementLength', + 'WearableMeasurementOutsideLeg', + 'WearableMeasurementSleeve', + 'WearableMeasurementWaist', + 'WearableMeasurementWidth', + 'MediaManipulationRatingEnumeration', + 'DecontextualizedContent', + 'EditedOrCroppedContent', + 'OriginalMediaContent', + 'SatireOrParodyContent', + 'StagedContent', + 'TransformedContent', + 'MedicalAudienceType', + 'Clinician', + 'MedicalResearcher', + 'MedicalDevicePurpose', + 'Diagnostic', + 'Therapeutic', + 'MedicalEnumeration', + 'MedicalEvidenceLevel', + 'EvidenceLevelA', + 'EvidenceLevelB', + 'EvidenceLevelC', + 'MedicalImagingTechnique', + 'CT', + 'MRI', + 'PET', + 'Radiography', + 'Ultrasound', + 'XRay', + 'MedicalObservationalStudyDesign', + 'CaseSeries', + 'CohortStudy', + 'CrossSectional', + 'Longitudinal', + 'Observational', + 'Registry', + 'MedicalProcedureType', + 'NoninvasiveProcedure', + 'PercutaneousProcedure', + 'MedicalSpecialty', + 'Anesthesia', + 'Cardiovascular', + 'CommunityHealth', + 'Dentistry', + 'Dermatologic', + 'Dermatology', + 'DietNutrition', + 'Emergency', + 'Endocrine', + 'Gastroenterologic', + 'Genetic', + 'Geriatric', + 'Gynecologic', + 'Hematologic', + 'Infectious', + 'LaboratoryScience', + 'Midwifery', + 'Musculoskeletal', + 'Neurologic', + 'Nursing', + 'Obstetric', + 'Oncologic', + 'Optometric', + 'Otolaryngologic', + 'Pathology', + 'Pediatric', + 'PharmacySpecialty', + 'Physiotherapy', + 'PlasticSurgery', + 'Podiatric', + 'PrimaryCare', + 'Psychiatric', + 'PublicHealth', + 'Pulmonary', + 'Renal', + 'Rheumatologic', + 'SpeechPathology', + 'Surgical', + 'Toxicologic', + 'Urologic', + 'MedicalStudyStatus', + 'ActiveNotRecruiting', + 'Completed', + 'EnrollingByInvitation', + 'NotYetRecruiting', + 'Recruiting', + 'ResultsAvailable', + 'ResultsNotAvailable', + 'Suspended', + 'Terminated', + 'Withdrawn', + 'MedicalTrialDesign', + 'DoubleBlindedTrial', + 'InternationalTrial', + 'MultiCenterTrial', + 'OpenTrial', + 'PlaceboControlledTrial', + 'RandomizedTrial', + 'SingleBlindedTrial', + 'SingleCenterTrial', + 'TripleBlindedTrial', + 'MedicineSystem', + 'Ayurvedic', + 'Chiropractic', + 'Homeopathic', + 'Osteopathic', + 'TraditionalChinese', + 'WesternConventional', + 'MerchantReturnEnumeration', + 'MerchantReturnFiniteReturnWindow', + 'MerchantReturnNotPermitted', + 'MerchantReturnUnlimitedWindow', + 'MerchantReturnUnspecified', + 'MusicAlbumProductionType', + 'CompilationAlbum', + 'DJMixAlbum', + 'DemoAlbum', + 'LiveAlbum', + 'MixtapeAlbum', + 'RemixAlbum', + 'SoundtrackAlbum', + 'SpokenWordAlbum', + 'StudioAlbum', + 'MusicAlbumReleaseType', + 'AlbumRelease', + 'BroadcastRelease', + 'EPRelease', + 'SingleRelease', + 'MusicReleaseFormatType', + 'CDFormat', + 'CassetteFormat', + 'DVDFormat', + 'DigitalAudioTapeFormat', + 'DigitalFormat', + 'LaserDiscFormat', + 'VinylFormat', + 'NLNonprofitType', + 'NonprofitANBI', + 'NonprofitSBBI', + 'NonprofitType', + 'OfferItemCondition', + 'DamagedCondition', + 'NewCondition', + 'RefurbishedCondition', + 'UsedCondition', + 'OrderStatus', + 'OrderCancelled', + 'OrderDelivered', + 'OrderInTransit', + 'OrderPaymentDue', + 'OrderPickupAvailable', + 'OrderProblem', + 'OrderProcessing', + 'OrderReturned', + 'PaymentMethod', + 'ByBankTransferInAdvance', + 'ByInvoice', + 'COD', + 'Cash', + 'CheckInAdvance', + 'DirectDebit', + 'InStorePrepay', + 'PhoneCarrierPayment', + 'PaymentStatusType', + 'PaymentAutomaticallyApplied', + 'PaymentComplete', + 'PaymentDeclined', + 'PaymentDue', + 'PaymentPastDue', + 'PhysicalActivityCategory', + 'AerobicActivity', + 'AnaerobicActivity', + 'Balance', + 'Flexibility', + 'LeisureTimeActivity', + 'OccupationalActivity', + 'StrengthTraining', + 'PhysicalExamEnumeration', + 'Abdomen', + 'Appearance', + 'CardiovascularExam', + 'Ear', + 'Eye', + 'Genitourinary', + 'Head', + 'Lung', + 'MusculoskeletalExam', + 'Neck', + 'Neuro', + 'Nose', + 'Skin', + 'Throat', + 'PriceComponentTypeEnumeration', + 'ActivationFee', + 'CleaningFee', + 'DistanceFee', + 'Downpayment', + 'Installment', + 'Subscription', + 'PriceTypeEnumeration', + 'InvoicePrice', + 'ListPrice', + 'MSRP', + 'MinimumAdvertisedPrice', + 'RegularPrice', + 'SRP', + 'SalePrice', + 'StrikethroughPrice', + 'QualitativeValue', + 'RefundTypeEnumeration', + 'ExchangeRefund', + 'FullRefund', + 'StoreCreditRefund', + 'ReservationStatusType', + 'ReservationCancelled', + 'ReservationConfirmed', + 'ReservationHold', + 'ReservationPending', + 'RestrictedDiet', + 'DiabeticDiet', + 'GlutenFreeDiet', + 'HalalDiet', + 'HinduDiet', + 'KosherDiet', + 'LowCalorieDiet', + 'LowFatDiet', + 'LowLactoseDiet', + 'LowSaltDiet', + 'VeganDiet', + 'VegetarianDiet', + 'ReturnFeesEnumeration', + 'FreeReturn', + 'OriginalShippingFees', + 'RestockingFees', + 'ReturnFeesCustomerResponsibility', + 'ReturnShippingFees', + 'ReturnLabelSourceEnumeration', + 'ReturnLabelCustomerResponsibility', + 'ReturnLabelDownloadAndPrint', + 'ReturnLabelInBox', + 'ReturnMethodEnumeration', + 'KeepProduct', + 'ReturnAtKiosk', + 'ReturnByMail', + 'ReturnInStore', + 'RsvpResponseType', + 'RsvpResponseMaybe', + 'RsvpResponseNo', + 'RsvpResponseYes', + 'SizeGroupEnumeration', + 'WearableSizeGroupBig', + 'WearableSizeGroupBoys', + 'WearableSizeGroupExtraShort', + 'WearableSizeGroupExtraTall', + 'WearableSizeGroupGirls', + 'WearableSizeGroupHusky', + 'WearableSizeGroupInfants', + 'WearableSizeGroupJuniors', + 'WearableSizeGroupMaternity', + 'WearableSizeGroupMens', + 'WearableSizeGroupMisses', + 'WearableSizeGroupPetite', + 'WearableSizeGroupPlus', + 'WearableSizeGroupRegular', + 'WearableSizeGroupShort', + 'WearableSizeGroupTall', + 'WearableSizeGroupWomens', + 'SizeSpecification', + 'SizeSystemEnumeration', + 'SizeSystemImperial', + 'SizeSystemMetric', + 'WearableSizeSystemAU', + 'WearableSizeSystemBR', + 'WearableSizeSystemCN', + 'WearableSizeSystemContinental', + 'WearableSizeSystemDE', + 'WearableSizeSystemEN13402', + 'WearableSizeSystemEurope', + 'WearableSizeSystemFR', + 'WearableSizeSystemGS1', + 'WearableSizeSystemIT', + 'WearableSizeSystemJP', + 'WearableSizeSystemMX', + 'WearableSizeSystemUK', + 'WearableSizeSystemUS', + 'Specialty', + 'StatusEnumeration', + 'SteeringPositionValue', + 'LeftHandDriving', + 'RightHandDriving', + 'USNonprofitType', + 'Nonprofit501a', + 'Nonprofit501c1', + 'Nonprofit501c10', + 'Nonprofit501c11', + 'Nonprofit501c12', + 'Nonprofit501c13', + 'Nonprofit501c14', + 'Nonprofit501c15', + 'Nonprofit501c16', + 'Nonprofit501c17', + 'Nonprofit501c18', + 'Nonprofit501c19', + 'Nonprofit501c2', + 'Nonprofit501c20', + 'Nonprofit501c21', + 'Nonprofit501c22', + 'Nonprofit501c23', + 'Nonprofit501c24', + 'Nonprofit501c25', + 'Nonprofit501c26', + 'Nonprofit501c27', + 'Nonprofit501c28', + 'Nonprofit501c3', + 'Nonprofit501c4', + 'Nonprofit501c5', + 'Nonprofit501c6', + 'Nonprofit501c7', + 'Nonprofit501c8', + 'Nonprofit501c9', + 'Nonprofit501d', + 'Nonprofit501e', + 'Nonprofit501f', + 'Nonprofit501k', + 'Nonprofit501n', + 'Nonprofit501q', + 'Nonprofit527', + 'WarrantyScope', + ], + 'event' => [ + 'Event', + 'BusinessEvent', + 'ChildrensEvent', + 'ComedyEvent', + 'CourseInstance', + 'DanceEvent', + 'DeliveryEvent', + 'EducationEvent', + 'EventSeries', + 'ExhibitionEvent', + 'Festival', + 'FoodEvent', + 'Hackathon', + 'LiteraryEvent', + 'MusicEvent', + 'OnDemandEvent', + 'PublicationEvent', + 'BroadcastEvent', + 'SaleEvent', + 'ScreeningEvent', + 'SocialEvent', + 'SportsEvent', + 'TheaterEvent', + 'VisualArtsEvent', + ], + 'medical' => [ + 'MedicalEntity', + 'AnatomicalStructure', + 'Artery', + 'Bone', + 'BrainStructure', + 'Joint', + 'Ligament', + 'Muscle', + 'Nerve', + 'Vein', + 'AnatomicalSystem', + 'DrugClass', + 'DrugCost', + 'DrugStrength', + 'DoseSchedule', + 'MaximumDoseSchedule', + 'RecommendedDoseSchedule', + 'ReportedDoseSchedule', + 'LifestyleModification', + 'PhysicalActivity', + 'MedicalCause', + 'MedicalCondition', + 'InfectiousDisease', + 'MedicalSignOrSymptom', + 'MedicalSign', + 'VitalSign', + 'MedicalSymptom', + 'MedicalContraindication', + 'MedicalDevice', + 'MedicalGuideline', + 'MedicalGuidelineContraindication', + 'MedicalGuidelineRecommendation', + 'MedicalIndication', + 'ApprovedIndication', + 'PreventionIndication', + 'TreatmentIndication', + 'MedicalIntangible', + 'DDxElement', + 'MedicalCode', + 'MedicalConditionStage', + 'MedicalProcedure', + 'DiagnosticProcedure', + 'PalliativeProcedure', + 'PhysicalExam', + 'SurgicalProcedure', + 'TherapeuticProcedure', + 'MedicalRiskCalculator', + 'MedicalRiskEstimator', + 'MedicalRiskFactor', + 'MedicalRiskScore', + 'MedicalStudy', + 'MedicalObservationalStudy', + 'MedicalTrial', + 'MedicalTest', + 'BloodTest', + 'ImagingTest', + 'MedicalTestPanel', + 'PathologyTest', + 'MedicalTherapy', + 'OccupationalTherapy', + 'PhysicalTherapy', + 'RadiationTherapy', + 'Substance', + 'SuperficialAnatomy', + ], + 'meta' => [ 'Class', 'Property' ], + 'website' => [ + 'WebSite', + 'WebPage', + 'WebPageElement', + 'SiteNavigationElement', + 'BreadcrumbList', + 'ItemList', + 'ListItem', + 'AboutPage', + 'CheckoutPage', + 'CollectionPage', + 'ContactPage', + 'ItemPage', + 'MedicalWebPage', + 'ProfilePage', + 'QAPage', + 'RealEstateListing', + 'SearchResultsPage', + 'WPAdBlock', + 'WPFooter', + 'WPHeader', + 'WPSideBar', + 'Table', + ], + ]; -return [ - 'action' => [ - 'Action', - 'AcceptAction', - 'AchieveAction', - 'ActivateAction', - 'AddAction', - 'AgreeAction', - 'AllocateAction', - 'AppendAction', - 'ApplyAction', - 'ArriveAction', - 'AskAction', - 'AssessAction', - 'AssignAction', - 'AuthorizeAction', - 'BefriendAction', - 'BookmarkAction', - 'BorrowAction', - 'BuyAction', - 'CancelAction', - 'CheckAction', - 'CheckInAction', - 'CheckOutAction', - 'ChooseAction', - 'ClaimAction', - 'CommentAction', - 'CommunicateAction', - 'ConfirmAction', - 'ConsumeAction', - 'ControlAction', - 'CookAction', - 'CreateAction', - 'DeactivateAction', - 'DeleteAction', - 'DepartAction', - 'DisagreeAction', - 'DiscoverAction', - 'DislikeAction', - 'DonateAction', - 'DownloadAction', - 'DrawAction', - 'DrinkAction', - 'EatAction', - 'EditAction', - 'EndorseAction', - 'ExerciseAction', - 'FilmAction', - 'FindAction', - 'FollowAction', - 'GiveAction', - 'IgnoreAction', - 'InformAction', - 'InsertAction', - 'InstallAction', - 'InteractAction', - 'InviteAction', - 'JoinAction', - 'LeaveAction', - 'LendAction', - 'LikeAction', - 'ListenAction', - 'LoseAction', - 'MarryAction', - 'MoneyTransfer', - 'MoveAction', - 'OrderAction', - 'OrganizeAction', - 'PaintAction', - 'PayAction', - 'PerformAction', - 'PhotographAction', - 'PlanAction', - 'PlayAction', - 'PreOrderAction', - 'PrependAction', - 'QuoteAction', - 'ReactAction', - 'ReadAction', - 'ReceiveAction', - 'RegisterAction', - 'RejectAction', - 'RentAction', - 'ReplaceAction', - 'ReplyAction', - 'ReportAction', - 'ReserveAction', - 'ResumeAction', - 'ReturnAction', - 'ReviewAction', - 'RsvpAction', - 'ScheduleAction', - 'SearchAction', - 'SeekToAction', - 'SellAction', - 'SendAction', - 'ShareAction', - 'SubscribeAction', - 'SuspendAction', - 'TakeAction', - 'TieAction', - 'TipAction', - 'TrackAction', - 'TradeAction', - 'TransferAction', - 'TravelAction', - 'UnRegisterAction', - 'UpdateAction', - 'UseAction', - 'ViewAction', - 'VoteAction', - 'WantAction', - 'WatchAction', - 'WearAction', - 'WinAction', - 'WriteAction', - ], - 'commerce' => [ - 'Product', - 'Car', - 'Drug', - 'DietarySupplement', - 'IndividualProduct', - 'Motorcycle', - 'ProductGroup', - 'ProductModel', - 'SomeProducts', - 'Vehicle', - 'BusOrCoach', - 'MotorizedBicycle', - 'Offer', - 'AggregateOffer', - 'Demand', - 'Order', - 'OrderItem', - 'Invoice', - 'PriceSpecification', - 'CompoundPriceSpecification', - 'DeliveryChargeSpecification', - 'PaymentChargeSpecification', - 'UnitPriceSpecification', - 'ShippingConditions', - 'ShippingDeliveryTime', - 'ShippingRateSettings', - 'ShippingService', - 'MerchantReturnPolicy', - 'MerchantReturnPolicySeasonalOverride', - 'OfferShippingDetails', - 'OfferCatalog', - 'ParcelDelivery', - 'FinancialProduct', - 'BankAccount', - 'CurrencyConversionService', - 'DepositAccount', - 'InvestmentFund', - 'InvestmentOrDeposit', - 'LoanOrCredit', - 'MortgageLoan', - 'PaymentCard', - 'CreditCard', - 'PaymentService', - ], - 'content' => [ - 'CreativeWork', - 'AmpStory', - 'AnalysisNewsArticle', - 'Answer', - 'ArchiveComponent', - 'Article', - 'AskPublicNewsArticle', - 'Atlas', - 'Audiobook', - 'BackgroundNewsArticle', - 'Blog', - 'BlogPosting', - 'Book', - 'BookSeries', - 'Certification', - 'Chapter', - 'Claim', - 'Clip', - 'Code', - 'Collection', - 'ComicCoverArt', - 'ComicIssue', - 'ComicSeries', - 'ComicStory', - 'Comment', - 'Conversation', - 'CorrectionComment', - 'Course', - 'CoverArt', - 'CreativeWorkSeason', - 'CreativeWorkSeries', - 'CriticReview', - 'DataCatalog', - 'DataDownload', - 'Dataset', - 'DefinedTermSet', - 'Diet', - 'DigitalDocument', - 'DiscussionForumPosting', - 'Drawing', - 'EducationalOccupationalCredential', - 'EmailMessage', - 'Episode', - 'ExercisePlan', - 'FAQPage', - 'Game', - 'Guide', - 'HowTo', - 'HowToDirection', - 'HowToSection', - 'HowToStep', - 'HowToTip', - 'HyperToc', - 'HyperTocEntry', - 'ImageGallery', - 'Legislation', - 'LegislationObject', - 'LiveBlogPosting', - 'Manuscript', - 'Map', - 'MathSolver', - 'MediaGallery', - 'MediaObject', - 'MediaReview', - 'MediaReviewItem', - 'Menu', - 'MenuSection', - 'Message', - 'Movie', - 'MovieClip', - 'MovieSeries', - 'MusicAlbum', - 'MusicComposition', - 'MusicPlaylist', - 'MusicRecording', - 'MusicRelease', - 'MusicVideoObject', - 'NewsArticle', - 'Newspaper', - 'NoteDigitalDocument', - 'OpinionNewsArticle', - 'Painting', - 'Periodical', - 'Photograph', - 'Play', - 'Poster', - 'PresentationDigitalDocument', - 'ProductCollection', - 'PublicationIssue', - 'PublicationVolume', - 'Question', - 'Quiz', - 'Quotation', - 'RadioClip', - 'RadioEpisode', - 'RadioSeason', - 'RadioSeries', - 'Recipe', - 'Recommendation', - 'Report', - 'ReportageNewsArticle', - 'Review', - 'ReviewNewsArticle', - 'SatiricalArticle', - 'ScholarlyArticle', - 'Sculpture', - 'Season', - 'SheetMusic', - 'ShortStory', - 'SocialMediaPosting', - 'SoftwareApplication', - 'SoftwareSourceCode', - 'SpecialAnnouncement', - 'SpreadsheetDigitalDocument', - 'Statement', - 'TechArticle', - 'TextDigitalDocument', - 'Thesis', - 'TVClip', - 'TVEpisode', - 'TVSeason', - 'TVSeries', - 'UserBlocks', - 'UserCheckins', - 'UserComments', - 'UserDownloads', - 'UserInteraction', - 'UserLikes', - 'UserPageVisits', - 'UserPlays', - 'UserPlusOnes', - 'UserTweets', - 'VideoClip', - 'VideoGallery', - 'VideoGame', - 'VideoGameClip', - 'VideoGameSeries', - 'VideoObject', - 'VideoObjectSnapshot', - 'VisualArtwork', - 'WebContent', - '3DModel', - 'AudioObject', - 'AudioObjectSnapshot', - 'ImageObject', - 'ImageObjectSnapshot', - 'JobPosting', - 'HowToItem', - 'HowToSupply', - 'HowToTool', - 'MenuItem', - 'Trip', - 'BoatTrip', - 'BusTrip', - 'Flight', - 'TouristTrip', - 'TrainTrip', - ], - 'data' => [ - 'Intangible', - 'ActionAccessSpecification', - 'AlignmentObject', - 'Audience', - 'BedDetails', - 'Brand', - 'BroadcastChannel', - 'BroadcastFrequencySpecification', - 'ComputerLanguage', - 'DataFeedItem', - 'DefinedTerm', - 'CategoryCode', - 'DefinedRegion', - 'DigitalDocumentPermission', - 'EnergyConsumptionDetails', - 'EntryPoint', - 'FinancialIncentive', - 'FloorPlan', - 'GameServer', - 'GeospatialGeometry', - 'Grant', - 'MonetaryGrant', - 'HealthInsurancePlan', - 'HealthPlanCostSharingSpecification', - 'HealthPlanFormulary', - 'HealthPlanNetwork', - 'Language', - 'MediaSubscription', - 'MemberProgram', - 'Observation', - 'Occupation', - 'OccupationalExperienceRequirements', - 'Permit', - 'GovernmentPermit', - 'ProgramMembership', - 'PropertyValueSpecification', - 'Quantity', - 'Distance', - 'Duration', - 'Energy', - 'Mass', - 'Rating', - 'AggregateRating', - 'EndorsementRating', - 'EmployerAggregateRating', - 'Reservation', - 'BoatReservation', - 'BusReservation', - 'EventReservation', - 'FlightReservation', - 'FoodEstablishmentReservation', - 'LodgingReservation', - 'RentalCarReservation', - 'ReservationPackage', - 'TaxiReservation', - 'TrainReservation', - 'Role', - 'LinkRole', - 'OrganizationRole', - 'EmployeeRole', - 'PerformanceRole', - 'Schedule', - 'Seat', - 'Service', - 'BroadcastService', - 'CableOrSatelliteService', - 'FoodService', - 'GovernmentService', - 'TaxiService', - 'WebAPI', - 'ServiceChannel', - 'SpeakableSpecification', - 'StatisticalPopulation', - 'StructuredValue', - 'CDCPMDRecord', - 'ContactPoint', - 'PostalAddress', - 'DatedMoneySpecification', - 'DeliveryTimeSettings', - 'EngineSpecification', - 'ExchangeRateSpecification', - 'GeoCircle', - 'GeoCoordinates', - 'GeoShape', - 'InteractionCounter', - 'MonetaryAmount', - 'MonetaryAmountDistribution', - 'NutritionInformation', - 'OpeningHoursSpecification', - 'OwnershipInfo', - 'PostalCodeRangeSpecification', - 'PropertyValue', - 'LocationFeatureSpecification', - 'QuantitativeValue', - 'QuantitativeValueDistribution', - 'RepaymentSpecification', - 'ServicePeriod', - 'TypeAndQuantityNode', - 'WarrantyPromise', - 'Ticket', - 'VirtualLocation', - 'DataType', - 'Boolean', - 'False', - 'True', - 'Date', - 'DateTime', - 'Number', - 'Float', - 'Integer', - 'Text', - 'CssSelectorType', - 'PronounceableText', - 'URL', - 'XPathType', - 'Time', - ], - 'entity' => [ - 'Thing', - 'Person', - 'Patient', - 'Organization', - 'Airline', - 'Consortium', - 'Cooperative', - 'Corporation', - 'EducationalOrganization', - 'CollegeOrUniversity', - 'ElementarySchool', - 'HighSchool', - 'MiddleSchool', - 'Preschool', - 'School', - 'FundingScheme', - 'GovernmentOrganization', - 'LibrarySystem', - 'LocalBusiness', - 'MedicalOrganization', - 'DiagnosticLab', - 'Hospital', - 'MedicalClinic', - 'Pharmacy', - 'Physician', - 'VeterinaryCare', - 'MemberProgramTier', - 'NGO', - 'NewsMediaOrganization', - 'OnlineBusiness', - 'OnlineStore', - 'PerformingGroup', - 'DanceGroup', - 'MusicGroup', - 'TheaterGroup', - 'PoliticalParty', - 'Project', - 'FundingAgency', - 'ResearchProject', - 'ResearchOrganization', - 'SearchRescueOrganization', - 'SportsOrganization', - 'SportsTeam', - 'WorkersUnion', - 'AccountingService', - 'AnimalShelter', - 'ArchiveOrganization', - 'AutoBodyShop', - 'AutoDealer', - 'AutoPartsStore', - 'AutoRental', - 'AutoRepair', - 'AutoWash', - 'AutomatedTeller', - 'AutomotiveBusiness', - 'Bakery', - 'BankOrCreditUnion', - 'BarOrPub', - 'BeautySalon', - 'BedAndBreakfast', - 'BikeStore', - 'BookStore', - 'BowlingAlley', - 'Brewery', - 'CafeOrCoffeeShop', - 'Campground', - 'Casino', - 'ChildCare', - 'ClothingStore', - 'ComputerStore', - 'ConvenienceStore', - 'DaySpa', - 'Dentist', - 'DepartmentStore', - 'DistilleryOrganization', - 'Distillery', - 'DryCleaningOrLaundry', - 'ElectronicsStore', - 'EmploymentAgency', - 'EntertainmentBusiness', - 'AdultEntertainment', - 'AmusementPark', - 'ArtGallery', - 'ComedyClub', - 'MovieTheater', - 'NightClub', - 'ExerciseGym', - 'FinancialService', - 'Florist', - 'FoodEstablishment', - 'FurnitureStore', - 'GardenStore', - 'GasStation', - 'GeneralContractor', - 'GolfCourse', - 'GovernmentOffice', - 'PostOffice', - 'GroceryStore', - 'HairSalon', - 'HardwareStore', - 'HealthAndBeautyBusiness', - 'HealthClub', - 'HobbyShop', - 'HomeAndConstructionBusiness', - 'Electrician', - 'HVACBusiness', - 'HousePainter', - 'Locksmith', - 'MovingCompany', - 'Plumber', - 'RoofingContractor', - 'HomeGoodsStore', - 'Hostel', - 'Hotel', - 'IceCreamShop', - 'InsuranceAgency', - 'InternetCafe', - 'JewelryStore', - 'LegalService', - 'Attorney', - 'Notary', - 'Library', - 'LiquorStore', - 'LodgingBusiness', - 'MedicalBusiness', - 'MensClothingStore', - 'MobilePhoneStore', - 'Motel', - 'MotorcycleDealer', - 'MotorcycleRepair', - 'MovieRentalStore', - 'MusicStore', - 'NailSalon', - 'OfficeEquipmentStore', - 'Optician', - 'OutletStore', - 'PawnShop', - 'PetStore', - 'ProfessionalService', - 'RadioStation', - 'RealEstateAgent', - 'RecyclingCenter', - 'Resort', - 'Restaurant', - 'FastFoodRestaurant', - 'SelfStorage', - 'ShoeStore', - 'ShoppingCenter', - 'SkiResort', - 'SportingGoodsStore', - 'SportsActivityLocation', - 'StadiumOrArena', - 'Store', - 'TattooParlor', - 'TelevisionStation', - 'TennisComplex', - 'TireShop', - 'TouristInformationCenter', - 'ToyStore', - 'TravelAgency', - 'WholesaleStore', - 'Winery', - 'Place', - 'Accommodation', - 'Apartment', - 'CampingPitch', - 'House', - 'SingleFamilyResidence', - 'Room', - 'HotelRoom', - 'MeetingRoom', - 'Suite', - 'AdministrativeArea', - 'City', - 'Country', - 'SchoolDistrict', - 'State', - 'CivicStructure', - 'Airport', - 'Aquarium', - 'Beach', - 'BoatTerminal', - 'Bridge', - 'BusStation', - 'BusStop', - 'Cemetery', - 'Crematorium', - 'EventVenue', - 'FireStation', - 'GovernmentBuilding', - 'CityHall', - 'Courthouse', - 'DefenceEstablishment', - 'Embassy', - 'LegislativeBuilding', - 'Museum', - 'MusicVenue', - 'Park', - 'ParkingFacility', - 'PerformingArtsTheater', - 'PlaceOfWorship', - 'BuddhistTemple', - 'Church', - 'CatholicChurch', - 'HinduTemple', - 'Mosque', - 'Synagogue', - 'Playground', - 'PoliceStation', - 'PublicToilet', - 'RVPark', - 'SubwayStation', - 'TaxiStand', - 'TrainStation', - 'Zoo', - 'Landform', - 'BodyOfWater', - 'Canal', - 'LakeBodyOfWater', - 'OceanBodyOfWater', - 'Pond', - 'Reservoir', - 'RiverBodyOfWater', - 'SeaBodyOfWater', - 'Waterfall', - 'Continent', - 'Mountain', - 'Volcano', - 'LandmarksOrHistoricalBuildings', - 'Residence', - 'ApartmentComplex', - 'GatedResidenceCommunity', - 'TouristAttraction', - 'TouristDestination', - 'Taxon', - ], - 'enumeration' => [ - 'RespiratoryTherapy', - 'Enumeration', - 'ActionStatusType', - 'ActiveActionStatus', - 'CompletedActionStatus', - 'FailedActionStatus', - 'PotentialActionStatus', - 'AdultOrientedEnumeration', - 'AlcoholConsideration', - 'DangerousGoodConsideration', - 'HealthcareConsideration', - 'NarcoticConsideration', - 'ReducedRelevanceForChildrenConsideration', - 'SexualContentConsideration', - 'TobaccoNicotineConsideration', - 'UnclassifiedAdultConsideration', - 'ViolenceConsideration', - 'WeaponConsideration', - 'BoardingPolicyType', - 'GroupBoardingPolicy', - 'ZoneBoardingPolicy', - 'BodyMeasurementTypeEnumeration', - 'BodyMeasurementArm', - 'BodyMeasurementBust', - 'BodyMeasurementChest', - 'BodyMeasurementFoot', - 'BodyMeasurementHand', - 'BodyMeasurementHead', - 'BodyMeasurementHeight', - 'BodyMeasurementHips', - 'BodyMeasurementInsideLeg', - 'BodyMeasurementNeck', - 'BodyMeasurementUnderbust', - 'BodyMeasurementWaist', - 'BodyMeasurementWeight', - 'BookFormatType', - 'AudiobookFormat', - 'EBook', - 'GraphicNovel', - 'Hardcover', - 'Paperback', - 'BusinessEntityType', - 'BusinessFunction', - 'CarUsageType', - 'ContactPointOption', - 'HearingImpairedSupported', - 'TollFree', - 'DayOfWeek', - 'Friday', - 'Monday', - 'PublicHolidays', - 'Saturday', - 'Sunday', - 'Thursday', - 'Tuesday', - 'Wednesday', - 'DeliveryMethod', - 'LockerDelivery', - 'OnSitePickup', - 'ParcelService', - 'DigitalDocumentPermissionType', - 'CommentPermission', - 'ReadPermission', - 'WritePermission', - 'DigitalPlatformEnumeration', - 'AndroidPlatform', - 'DesktopWebPlatform', - 'GenericWebPlatform', - 'IOSPlatform', - 'MobileWebPlatform', - 'DigitalSourceType', - 'AlgorithmicMediaDigitalSource', - 'AlgorithmicallyEnhancedDigitalSource', - 'CompositeCaptureDigitalSource', - 'CompositeDigitalSource', - 'CompositeSyntheticDigitalSource', - 'CompositeWithTrainedAlgorithmicMediaDigitalSource', - 'DataDrivenMediaDigitalSource', - 'DigitalArtDigitalSource', - 'DigitalCaptureDigitalSource', - 'MinorHumanEditsDigitalSource', - 'MultiFrameComputationalCaptureDigitalSource', - 'NegativeFilmDigitalSource', - 'PositiveFilmDigitalSource', - 'PrintDigitalSource', - 'ScreenCaptureDigitalSource', - 'TrainedAlgorithmicMediaDigitalSource', - 'VirtualRecordingDigitalSource', - 'DriveWheelConfigurationValue', - 'AllWheelDriveConfiguration', - 'FourWheelDriveConfiguration', - 'FrontWheelDriveConfiguration', - 'RearWheelDriveConfiguration', - 'DrugCostCategory', - 'ReimbursementCap', - 'Retail', - 'Wholesale', - 'DrugPregnancyCategory', - 'FDAcategoryA', - 'FDAcategoryB', - 'FDAcategoryC', - 'FDAcategoryD', - 'FDAcategoryX', - 'FDAnotEvaluated', - 'DrugPrescriptionStatus', - 'OTC', - 'PrescriptionOnly', - 'EUEnergyEfficiencyEnumeration', - 'EUEnergyEfficiencyCategoryA', - 'EUEnergyEfficiencyCategoryA1Plus', - 'EUEnergyEfficiencyCategoryA2Plus', - 'EUEnergyEfficiencyCategoryA3Plus', - 'EUEnergyEfficiencyCategoryB', - 'EUEnergyEfficiencyCategoryC', - 'EUEnergyEfficiencyCategoryD', - 'EUEnergyEfficiencyCategoryE', - 'EUEnergyEfficiencyCategoryF', - 'EUEnergyEfficiencyCategoryG', - 'EnergyStarEnergyEfficiencyEnumeration', - 'EventAttendanceModeEnumeration', - 'MixedEventAttendanceMode', - 'OfflineEventAttendanceMode', - 'OnlineEventAttendanceMode', - 'EventStatusType', - 'EventCancelled', - 'EventMovedOnline', - 'EventPostponed', - 'EventRescheduled', - 'EventScheduled', - 'FulfillmentTypeEnumeration', - 'FulfillmentTypeDelivery', - 'FulfillmentTypePickup', - 'GameAvailabilityEnumeration', - 'DemoGameAvailability', - 'FullGameAvailability', - 'GamePlayMode', - 'CoOp', - 'MultiPlayer', - 'SinglePlayer', - 'GameServerStatus', - 'OfflinePermanently', - 'OfflineTemporarily', - 'Online', - 'OnlineFull', - 'GenderType', - 'Female', - 'Male', - 'GovernmentBenefitsType', - 'BasicIncome', - 'BusinessSupport', - 'DisabilitySupport', - 'HealthCare', - 'OneTimePayments', - 'PaidLeave', - 'ParentalSupport', - 'UnemploymentSupport', - 'HealthAspectEnumeration', - 'AllergiesHealthAspect', - 'BenefitsHealthAspect', - 'CausesHealthAspect', - 'ContagiousnessHealthAspect', - 'EffectivenessHealthAspect', - 'GettingAccessHealthAspect', - 'HowItWorksHealthAspect', - 'HowOrWhereHealthAspect', - 'IngredientsHealthAspect', - 'LivingWithHealthAspect', - 'MayTreatHealthAspect', - 'MisconceptionsHealthAspect', - 'OverviewHealthAspect', - 'PatientExperienceHealthAspect', - 'PregnancyHealthAspect', - 'PreventionHealthAspect', - 'PrognosisHealthAspect', - 'RelatedTopicsHealthAspect', - 'RisksOrComplicationsHealthAspect', - 'SafetyHealthAspect', - 'ScreeningHealthAspect', - 'SeeDoctorHealthAspect', - 'SelfCareHealthAspect', - 'SideEffectsHealthAspect', - 'StagesHealthAspect', - 'SymptomsHealthAspect', - 'TreatmentsHealthAspect', - 'TypesHealthAspect', - 'UsageOrScheduleHealthAspect', - 'IncentiveEligibility', - 'IncentiveStatus', - 'IncentiveType', - 'ItemAvailability', - 'BackOrder', - 'Discontinued', - 'InStock', - 'InStoreOnly', - 'LimitedAvailability', - 'MadeToOrder', - 'OnlineOnly', - 'OutOfStock', - 'PreOrder', - 'PreSale', - 'Reserved', - 'SoldOut', - 'ItemListOrderType', - 'ItemListOrderAscending', - 'ItemListOrderDescending', - 'ItemListUnordered', - 'LegalForceStatus', - 'InForce', - 'NotInForce', - 'PartiallyInForce', - 'LegalValueLevel', - 'AuthoritativeLegalValue', - 'DefinitiveLegalValue', - 'OfficialLegalValue', - 'UnofficialLegalValue', - 'MapCategoryType', - 'ParkingMap', - 'SeatingMap', - 'TransitMap', - 'VenueMap', - 'MeasurementMethodEnum', - 'ExhaustEmissionsMeasurementMethod', - 'MeasurementTypeEnumeration', - 'WearableMeasurementBack', - 'WearableMeasurementChestOrBust', - 'WearableMeasurementCollar', - 'WearableMeasurementCup', - 'WearableMeasurementHeight', - 'WearableMeasurementHips', - 'WearableMeasurementInseam', - 'WearableMeasurementLength', - 'WearableMeasurementOutsideLeg', - 'WearableMeasurementSleeve', - 'WearableMeasurementWaist', - 'WearableMeasurementWidth', - 'MediaManipulationRatingEnumeration', - 'DecontextualizedContent', - 'EditedOrCroppedContent', - 'OriginalMediaContent', - 'SatireOrParodyContent', - 'StagedContent', - 'TransformedContent', - 'MedicalAudienceType', - 'Clinician', - 'MedicalResearcher', - 'MedicalDevicePurpose', - 'Diagnostic', - 'Therapeutic', - 'MedicalEnumeration', - 'MedicalEvidenceLevel', - 'EvidenceLevelA', - 'EvidenceLevelB', - 'EvidenceLevelC', - 'MedicalImagingTechnique', - 'CT', - 'MRI', - 'PET', - 'Radiography', - 'Ultrasound', - 'XRay', - 'MedicalObservationalStudyDesign', - 'CaseSeries', - 'CohortStudy', - 'CrossSectional', - 'Longitudinal', - 'Observational', - 'Registry', - 'MedicalProcedureType', - 'NoninvasiveProcedure', - 'PercutaneousProcedure', - 'MedicalSpecialty', - 'Anesthesia', - 'Cardiovascular', - 'CommunityHealth', - 'Dentistry', - 'Dermatologic', - 'Dermatology', - 'DietNutrition', - 'Emergency', - 'Endocrine', - 'Gastroenterologic', - 'Genetic', - 'Geriatric', - 'Gynecologic', - 'Hematologic', - 'Infectious', - 'LaboratoryScience', - 'Midwifery', - 'Musculoskeletal', - 'Neurologic', - 'Nursing', - 'Obstetric', - 'Oncologic', - 'Optometric', - 'Otolaryngologic', - 'Pathology', - 'Pediatric', - 'PharmacySpecialty', - 'Physiotherapy', - 'PlasticSurgery', - 'Podiatric', - 'PrimaryCare', - 'Psychiatric', - 'PublicHealth', - 'Pulmonary', - 'Renal', - 'Rheumatologic', - 'SpeechPathology', - 'Surgical', - 'Toxicologic', - 'Urologic', - 'MedicalStudyStatus', - 'ActiveNotRecruiting', - 'Completed', - 'EnrollingByInvitation', - 'NotYetRecruiting', - 'Recruiting', - 'ResultsAvailable', - 'ResultsNotAvailable', - 'Suspended', - 'Terminated', - 'Withdrawn', - 'MedicalTrialDesign', - 'DoubleBlindedTrial', - 'InternationalTrial', - 'MultiCenterTrial', - 'OpenTrial', - 'PlaceboControlledTrial', - 'RandomizedTrial', - 'SingleBlindedTrial', - 'SingleCenterTrial', - 'TripleBlindedTrial', - 'MedicineSystem', - 'Ayurvedic', - 'Chiropractic', - 'Homeopathic', - 'Osteopathic', - 'TraditionalChinese', - 'WesternConventional', - 'MerchantReturnEnumeration', - 'MerchantReturnFiniteReturnWindow', - 'MerchantReturnNotPermitted', - 'MerchantReturnUnlimitedWindow', - 'MerchantReturnUnspecified', - 'MusicAlbumProductionType', - 'CompilationAlbum', - 'DJMixAlbum', - 'DemoAlbum', - 'LiveAlbum', - 'MixtapeAlbum', - 'RemixAlbum', - 'SoundtrackAlbum', - 'SpokenWordAlbum', - 'StudioAlbum', - 'MusicAlbumReleaseType', - 'AlbumRelease', - 'BroadcastRelease', - 'EPRelease', - 'SingleRelease', - 'MusicReleaseFormatType', - 'CDFormat', - 'CassetteFormat', - 'DVDFormat', - 'DigitalAudioTapeFormat', - 'DigitalFormat', - 'LaserDiscFormat', - 'VinylFormat', - 'NLNonprofitType', - 'NonprofitANBI', - 'NonprofitSBBI', - 'NonprofitType', - 'OfferItemCondition', - 'DamagedCondition', - 'NewCondition', - 'RefurbishedCondition', - 'UsedCondition', - 'OrderStatus', - 'OrderCancelled', - 'OrderDelivered', - 'OrderInTransit', - 'OrderPaymentDue', - 'OrderPickupAvailable', - 'OrderProblem', - 'OrderProcessing', - 'OrderReturned', - 'PaymentMethod', - 'ByBankTransferInAdvance', - 'ByInvoice', - 'COD', - 'Cash', - 'CheckInAdvance', - 'DirectDebit', - 'InStorePrepay', - 'PhoneCarrierPayment', - 'PaymentStatusType', - 'PaymentAutomaticallyApplied', - 'PaymentComplete', - 'PaymentDeclined', - 'PaymentDue', - 'PaymentPastDue', - 'PhysicalActivityCategory', - 'AerobicActivity', - 'AnaerobicActivity', - 'Balance', - 'Flexibility', - 'LeisureTimeActivity', - 'OccupationalActivity', - 'StrengthTraining', - 'PhysicalExamEnumeration', - 'Abdomen', - 'Appearance', - 'CardiovascularExam', - 'Ear', - 'Eye', - 'Genitourinary', - 'Head', - 'Lung', - 'MusculoskeletalExam', - 'Neck', - 'Neuro', - 'Nose', - 'Skin', - 'Throat', - 'PriceComponentTypeEnumeration', - 'ActivationFee', - 'CleaningFee', - 'DistanceFee', - 'Downpayment', - 'Installment', - 'Subscription', - 'PriceTypeEnumeration', - 'InvoicePrice', - 'ListPrice', - 'MSRP', - 'MinimumAdvertisedPrice', - 'RegularPrice', - 'SRP', - 'SalePrice', - 'StrikethroughPrice', - 'QualitativeValue', - 'RefundTypeEnumeration', - 'ExchangeRefund', - 'FullRefund', - 'StoreCreditRefund', - 'ReservationStatusType', - 'ReservationCancelled', - 'ReservationConfirmed', - 'ReservationHold', - 'ReservationPending', - 'RestrictedDiet', - 'DiabeticDiet', - 'GlutenFreeDiet', - 'HalalDiet', - 'HinduDiet', - 'KosherDiet', - 'LowCalorieDiet', - 'LowFatDiet', - 'LowLactoseDiet', - 'LowSaltDiet', - 'VeganDiet', - 'VegetarianDiet', - 'ReturnFeesEnumeration', - 'FreeReturn', - 'OriginalShippingFees', - 'RestockingFees', - 'ReturnFeesCustomerResponsibility', - 'ReturnShippingFees', - 'ReturnLabelSourceEnumeration', - 'ReturnLabelCustomerResponsibility', - 'ReturnLabelDownloadAndPrint', - 'ReturnLabelInBox', - 'ReturnMethodEnumeration', - 'KeepProduct', - 'ReturnAtKiosk', - 'ReturnByMail', - 'ReturnInStore', - 'RsvpResponseType', - 'RsvpResponseMaybe', - 'RsvpResponseNo', - 'RsvpResponseYes', - 'SizeGroupEnumeration', - 'WearableSizeGroupBig', - 'WearableSizeGroupBoys', - 'WearableSizeGroupExtraShort', - 'WearableSizeGroupExtraTall', - 'WearableSizeGroupGirls', - 'WearableSizeGroupHusky', - 'WearableSizeGroupInfants', - 'WearableSizeGroupJuniors', - 'WearableSizeGroupMaternity', - 'WearableSizeGroupMens', - 'WearableSizeGroupMisses', - 'WearableSizeGroupPetite', - 'WearableSizeGroupPlus', - 'WearableSizeGroupRegular', - 'WearableSizeGroupShort', - 'WearableSizeGroupTall', - 'WearableSizeGroupWomens', - 'SizeSpecification', - 'SizeSystemEnumeration', - 'SizeSystemImperial', - 'SizeSystemMetric', - 'WearableSizeSystemAU', - 'WearableSizeSystemBR', - 'WearableSizeSystemCN', - 'WearableSizeSystemContinental', - 'WearableSizeSystemDE', - 'WearableSizeSystemEN13402', - 'WearableSizeSystemEurope', - 'WearableSizeSystemFR', - 'WearableSizeSystemGS1', - 'WearableSizeSystemIT', - 'WearableSizeSystemJP', - 'WearableSizeSystemMX', - 'WearableSizeSystemUK', - 'WearableSizeSystemUS', - 'Specialty', - 'StatusEnumeration', - 'SteeringPositionValue', - 'LeftHandDriving', - 'RightHandDriving', - 'USNonprofitType', - 'Nonprofit501a', - 'Nonprofit501c1', - 'Nonprofit501c10', - 'Nonprofit501c11', - 'Nonprofit501c12', - 'Nonprofit501c13', - 'Nonprofit501c14', - 'Nonprofit501c15', - 'Nonprofit501c16', - 'Nonprofit501c17', - 'Nonprofit501c18', - 'Nonprofit501c19', - 'Nonprofit501c2', - 'Nonprofit501c20', - 'Nonprofit501c21', - 'Nonprofit501c22', - 'Nonprofit501c23', - 'Nonprofit501c24', - 'Nonprofit501c25', - 'Nonprofit501c26', - 'Nonprofit501c27', - 'Nonprofit501c28', - 'Nonprofit501c3', - 'Nonprofit501c4', - 'Nonprofit501c5', - 'Nonprofit501c6', - 'Nonprofit501c7', - 'Nonprofit501c8', - 'Nonprofit501c9', - 'Nonprofit501d', - 'Nonprofit501e', - 'Nonprofit501f', - 'Nonprofit501k', - 'Nonprofit501n', - 'Nonprofit501q', - 'Nonprofit527', - 'WarrantyScope', - ], - 'event' => [ - 'Event', - 'BusinessEvent', - 'ChildrensEvent', - 'ComedyEvent', - 'CourseInstance', - 'DanceEvent', - 'DeliveryEvent', - 'EducationEvent', - 'EventSeries', - 'ExhibitionEvent', - 'Festival', - 'FoodEvent', - 'Hackathon', - 'LiteraryEvent', - 'MusicEvent', - 'OnDemandEvent', - 'PublicationEvent', - 'BroadcastEvent', - 'SaleEvent', - 'ScreeningEvent', - 'SocialEvent', - 'SportsEvent', - 'TheaterEvent', - 'VisualArtsEvent', - ], - 'medical' => [ - 'MedicalEntity', - 'AnatomicalStructure', - 'Artery', - 'Bone', - 'BrainStructure', - 'Joint', - 'Ligament', - 'Muscle', - 'Nerve', - 'Vein', - 'AnatomicalSystem', - 'DrugClass', - 'DrugCost', - 'DrugStrength', - 'DoseSchedule', - 'MaximumDoseSchedule', - 'RecommendedDoseSchedule', - 'ReportedDoseSchedule', - 'LifestyleModification', - 'PhysicalActivity', - 'MedicalCause', - 'MedicalCondition', - 'InfectiousDisease', - 'MedicalSignOrSymptom', - 'MedicalSign', - 'VitalSign', - 'MedicalSymptom', - 'MedicalContraindication', - 'MedicalDevice', - 'MedicalGuideline', - 'MedicalGuidelineContraindication', - 'MedicalGuidelineRecommendation', - 'MedicalIndication', - 'ApprovedIndication', - 'PreventionIndication', - 'TreatmentIndication', - 'MedicalIntangible', - 'DDxElement', - 'MedicalCode', - 'MedicalConditionStage', - 'MedicalProcedure', - 'DiagnosticProcedure', - 'PalliativeProcedure', - 'PhysicalExam', - 'SurgicalProcedure', - 'TherapeuticProcedure', - 'MedicalRiskCalculator', - 'MedicalRiskEstimator', - 'MedicalRiskFactor', - 'MedicalRiskScore', - 'MedicalStudy', - 'MedicalObservationalStudy', - 'MedicalTrial', - 'MedicalTest', - 'BloodTest', - 'ImagingTest', - 'MedicalTestPanel', - 'PathologyTest', - 'MedicalTherapy', - 'OccupationalTherapy', - 'PhysicalTherapy', - 'RadiationTherapy', - 'Substance', - 'SuperficialAnatomy', - ], - 'meta' => [ 'Class', 'Property' ], - 'website' => [ - 'WebSite', - 'WebPage', - 'WebPageElement', - 'SiteNavigationElement', - 'BreadcrumbList', - 'ItemList', - 'ListItem', - 'AboutPage', - 'CheckoutPage', - 'CollectionPage', - 'ContactPage', - 'ItemPage', - 'MedicalWebPage', - 'ProfilePage', - 'QAPage', - 'RealEstateListing', - 'SearchResultsPage', - 'WPAdBlock', - 'WPFooter', - 'WPHeader', - 'WPSideBar', - 'Table', - ], -]; + /** + * Get the full map of schema.org types. + * + * @return array> The map; + */ + public static function get(): array { + return self::$map; + } +} From 9fdc039c7eb4965d9145525dd2df6635461584ca Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 27 Jan 2026 16:02:16 +0100 Subject: [PATCH 266/319] Fix annotation and test name --- ...er_Test.php => WebPage_Schema_Node_Should_Filter_Test.php} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/{WebPage_Schema_Node_Filter_Test.php => WebPage_Schema_Node_Should_Filter_Test.php} (95%) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Should_Filter_Test.php similarity index 95% rename from tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php rename to tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Should_Filter_Test.php index ef6167043e4..655601e7054 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebPage_Schema_Node_Should_Filter_Test.php @@ -11,11 +11,11 @@ /** * Tests the WebPage_Schema_Node_Filter class. * - * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\WebPage_Schema_Node_Filter::filter + * @covers \Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\WebPage_Schema_Node_Filter::should_filter * * @group schema-aggregator */ -final class WebPage_Schema_Node_Filter_Test extends TestCase { +final class WebPage_Schema_Node_Should_Filter_Test extends TestCase { /** * The instance of WebPage_Schema_Node_Filter being tested. From 871fdc10021b00d88f8208bda6eae75b15423acc Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 30 Jan 2026 10:29:22 +0100 Subject: [PATCH 267/319] The feature thumbnail --- images/schema-aggregator-thumbnail.png | Bin 0 -> 38737 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/schema-aggregator-thumbnail.png diff --git a/images/schema-aggregator-thumbnail.png b/images/schema-aggregator-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..4faeb14c72818abd1b70926c603d02f0a6848245 GIT binary patch literal 38737 zcmXV0Wk6g_uU=>=6n7}a-6`(w4!bNag(Ah>9g4eC++}fhDDLj=6nEFl+wcC{lRU{z zW|A{`=1ho^f+P|=9y|a5K$4ac0|Edaz5@VI`*6_jlC1Er)&M{fuC$o2ip$b*o6ZQq z?C-Ot`6J7(&d?mvh12r5h*Q_UKc;`22od5w1PH_lh>(%~*dvwVs`g}+k|tZ`B>zC> z%M{++RHZC3CT4GJK{rP2=^x=YGvdIu_k#`2fen|Gojd)svjA!JAdQXVmk+bk=+$Ze z+4fC2xXx_$u}HIS{Vj^2W_<~Kw5_4{rkQE>_VzqS&OS>n2zf(Q)lE_<%B3wNPziM> zwN}zcQDyI-wU)$Vgv>3+I}`Kj+_f%vX<_X-CM?B5O%{`5($eyRSGz%VAFIviS7|HH zRUwCXokJCswGthdjGnW3q1R(WYG8ADtq0tC_76`Kl199x&nX|qmk(=e&KK!>Q z(LmR}2q;=4GinRJTarr$v!oiqRkDX5HWjR5uWqI4fq+91q#|srvdLNepr96?b@91J zdyl%}x7b5yoigpLYMr*q03DedzgiQ0G3CqM62uTC55Fspx1`Esj}*EBz2@>{_*I3Vy_{oo*vifY$!w_&2Ph6P`HN)2tJlo6_2cS44Gp^7T&*p>MYvyM;4 z0xA^0wMW5(BK1UdLipk|pbJh~%-XeBu>4TwOn#psunwA4SuF`et{0^9p-dtH7Ti8R z|M8-@T8nDEr_jPao0d)UL;h7TV#hb+R0vw0Th=_JWk;E=LQ0$qav2~wD($4QJvBkw zIcnB32==N|!on->4A)rds$>r5qRN!d-sAL+&?HunNq$Wj$H3b3V+pgErutDDnywyW zaBW4X7h8gkU~1BVu9!B?IZ^r;Vt3KhaLDd{O>q9qfcbc|NB*G%o%LY=#-NdVXpNoB zOd{ye>8v+OhKdMQ(Qg6ElMuZ+jl`FE29_3L?KD!M7X%w<6!&SuJ;5PhS{J+K zB*$w|Hv|`LAyggm&*V=0J7 zlqV4ngn$AjME+b5Usl7wV^yz~COdM6rDo*>x8qF_+eM*KX$f#|Kci$r&Ka!**f{6r zr~^+JdwhxcYbEc7lAB0EbOxR2e%YINgwo#CbF+{Bk?rRm=`si0-btR$Rpb0f8Q9=n zCz6FXhf0CvbA44OHJAjy3)MQadoEgVsB+29ZyE3bYvLhcSq_2(&0n74DeSxmNV#$^ zFPD|?PdxDm5{x3|9!3#b29P^M83CCL3f9(4+)|dX$w~|fvrdLu&jAp7mZov~xDW2%>Z?X@?d&P|hgk&l0+y9b@m?UoNAaOXr1lgzD zK(fieH~KMNf&MCJu0jz-wIXB%Siwnt3DPvQ6`~?DK4F$ug&GyGgGGdAG~`hw4*Jxb zbF&*zAdM9j0zE(=J*R1U>hveug~j>F60W``9LAp6=U{HIlG$9T0d|Bs*xyKQ_KLSy zk~n8B14gi1X7v6CUtnX==U~V^pAwD_y4o_$JQLWg0)lxLZ!wl}9B;V@n)R2CYm-Qf zhT3Dt@Z*D?R1J;ulF>=JR7X-?(pYq66_?xA+?o97KU+5R)_j>xQvn}o{gw@Ej~df* z&vB#AenCj_x|31J6(ptdn{5 zkWvf5dtdhqhE|`8GxZO}c6G9!8RKGkLa+H)+ZDUX&7v~PSAWO}E!mpMS~QGSOCgOy zKT>H1@3jesvWrr3s*F&wbXz!c`z5J?AxB`STd*rWEr}Mr!}{BpVkQyWm>Ke{R<_c_JHGaWCR z1_D*~Iq{=`n|p}>#g7`!CQr4hmcChWgN2n+3Gl+ufdKuSHkpR(&Jveq1Pj5GHEFyh zxILwXlC2U$*>#{)y9FPyX}V~rdQ|vJfc*mpjksE%cw(37Pn8@>d$pG(S_RzQ~B14eP6{GVmDP^)7EYX~OIw(Iqmn;y8-~)dq%c%Jc^3p~2Dw?_nmtLCt zG*dX8VI+a}dZ&;;16|CnI|ngGN#JxYuc=Uo zP)Wq2O5hn;Y@&Yha!w~&J6pb3!8<*MX^{7i}-9X`6v2#qL828m{k_ zqKPU@5Q8;`f{vx}y1fJvYKJRUuX8noh9$ltmZ(5{oq62`ZU@G1aa{UKYZ0OmOGhWZ<>Cs zN87ukF;^4>ChHw1g^LE6-?j2pt|UOCCu%XnswzQ+B^&t6$G@rl)kqhcQ9MVny_IBw zTpo<1XRV=52?M{M<>162)ufe&BK+7PT>X645>oH9?V5a}NMrp0OG&c0HlQs^i9)vr zc=I#O*ZD^>sNj_bcw?oHRgnlB?rGHFQ)w9GY3^x|0oPpH7uXk^cF&|iD z>Sf+B72SZIPe|GZ_YWMFJllQi{YoSku z;Cg(w(nIel!Kj**WcOjOcAB}VU_HdhsTB{>z!1m6Nr#&KTT8?`_(wTm{SvIHC3){tCI>JjHM@N6k#oRp4OKtnmgr1Rg4$g&A1QZ@ zgqT6rNm;@#)!x3~)eG>V>3Bu_+?96@D1_Gw%(O95kD@{rE5Bya>$}NCD||_8lQr+M zqwA&Ji$N^BQ~7LfXy;gj-iX?|q2|~iWW>d{!t(bR()NQs(XP7xaUgi%VN_5-HAUs; zXCQ46H!QLiRd(~uSEoeE->Lqk1_S0#gx~<9`&Z*9tb7ucNt(5&U%=0j z@O=enIDrGTX0dN0Z9YgYOzEw$419YenzYWPZi98)P7aRnxf3IC1}!_x4#xE9!uf8) zi2TQ2GA=!aHgpQKB5!4wm1~A6|M27E7P;}Oa&|F+g$}~;*MANaLpIzf8xYz~5BUQ- zcQaCR4{S6_j3bp2##7-sl_(S^Cwi&DZ@Wz9p9wFEn%iZ}E;k;C?xt!_Vup+jv6O@P z9HI{~lPZ7j(bg71Ota;>N{don#%uMp<{%xN&){doG~#vGW4Pmv)KT-6FXXkiFe?#2vpK+^XbO)_XmS#mE?aV4Lt zd!+FIx3a5@m8RB-UxRWk=oi!}9-DG?X1~p};Sp&h0G=7ddCJ@7 zk$w4;gmE-HQ7h$moMCb<66!zQ%FbQba4S9A<^V&Go92WhGdv2pnTM!m$^$LWDu8PA z1S9B;#3T+nHpiiR*-s9@qovov&SF3MIQ~(IlC@@Vh%o)fpn~Pn+zE1cXT8~xr(tIA z@nJYx2W`cGj|GJcXW)80R(RoAufod_CFz@z!X9O)_7VkUP+RfI&wl7cPMY0P^Gieh z-G{u;v!*dey-NbkWs4F651^|EI5_8!Mj{}l#9MV2#Ro4U!J?o^bj}vH&eMk2t}Sn< z!)K}G2jzUhVx*)eXV6y}0^?XR=`ndmW9ygOYSf0yKHP2Ob&CpqT=343^@4h(%*!WIhj*{@he;LU<- zHfFZM6s2<(lye#Dk`Uz&4&BPE+vc&!;@h33nmUwP1m{JtPlJ zIhv=Pd=L`VP)FKu6zM2vI+<#cF7c#L6@H;ct21BvQamawUuAkr-l@$w>mfR?$>ky{ zMzpKEOCvxVv?R-z=cfmuBv9P6$K*-)Mk2Dkr7#JYt~;6j(p1FF;aAQfkxz@En+o@d zfEBmZX2Ci2^cOF8Qe&}xb{u68ya7u@QQ(yu-*4j-7O~Yc%X0PZNEP`+fUgxKI9L&$ zA1I!0L#{;7Y#$Va0KQ7kw}?sj>6~h~-37(XU5AOR?uc7&(L3EzU!F^A*lAZil6&|e z>+(LCM?wb6DN?HXhqcHWg`L!im0&T%LpV;TsJPvL-7bPlURzTHNu46}M`Rrz16>lC z%6z{6q@6RqLZEIv-$bbKEX{g?hntLCW4z->z2%l#9FXfO z(ahqqWDADJ<(krmQBP`!h!Q`TzEfY8*Rpoy7d6e!g_nHL2&Zlrqm3NpnGEJ^DGpg0 zB>%9i$Ryn@xn&7H%`@33RCrvoGLAIEVTRe4$vp)7D@>`dbag;>l2zC#Azbq6S&0tM z%`jyOB~~`HyMPi`deDWAm=P1}ZIr^8m<9dx55DeZ?+D!K42Jt~iW_bOJ$6+q+CRng zzMzOCQU4;oHgKooP-7y4^Q?z7q1vdb8f4urdI@umE<|(bT-*rGzY*VYFXNDKI9QSg z2O9jwm#JF_f9{wEksurdD)kuzd|#+297YlRfNWQ z5cHveA6c|0Y&)hWHq~eJV^6#9%PfJdZdxqWGQg1ihPur2BRyp{qe2Dq1+bJvnMX4n zw8Uu&p)!dP?ellWjssNzg#hz@1*^x@r8E4l_z$Bmbd_S$-ky3S5>p=%&+)7Ag9^f( zo7^7oY?rjqWUIf(W07EdO_%S8k@4>vZ8dcocraB8($7u%Ezt)S(%3)!J`WbC8_p3` z`}^@sVYepaJLGY`Z9&|={*qxFO5~duuUp7+bUT=xSy$05!%BVqeUPsW!M$V3sw@~~ zGG@Q>??Qp9o`x%9#jW$HLb*2*;KZq)A@T!nbLR(H38=k>t-oZTB3dMc76Sc{?xO7?acmg`vR7 zGvh%b6~b4{vNAl#+u)xd*jTeyRSw*4~H zMx)rC?&dfAbH!=B+Ek$^ErRP+)2PJ6;xECIb#b1CR=^%tLNj^szFC&L&gAVcyetJN z9m#@_z(d|!Gk~nKyA+aXm-=6L?V8#N4VmI_c={o5VhC$~5f6ttO*c_)Ecj$m& zi-4(Y2;RND!&z?jToqksAJ!vC{`s=x6P)W`cgV35o$nO1;En4+=_eKt)=@AdOg4en zlD9(A)~To#ma7bv#$?g%;;^zfD(}5tQ-;ZtQ5yNWN8`k+D(0x`hw2)BmN)&$8qx&3 zUR#oYu{J)~{(h%XCQwuCk!TUr%gOZ+OWz|6TvywDS~K$CzBm?QM<%2CI;?sXT|w`Q z8#B>nnUp?JK@VYGrwp)aOKug^5f@{1&Gb2>No`V5NVbv7MlRX;QhkzRh9o38s!7(x zhumA#Og{@0ri(uk#ch+DGFg;aksu$$x9I3^36k99My@p~B$-`z=)QJ;{6%n{ex+lJ z>d10P<4@PaGClC~ni3zZpw|Wdu|NvK!cj?(ns*8bJ8UwUbhlvKFc{7F%pXnk%gAL_zU z(!X_HT2@l?dlj$;=+*U8k`6PeF0<%@wrEGMYBhD`25aNj4GDP<);qRW% z*kd!*OOn=)VyjywSpv6}71y}oef|tcFp2f97Zc>5MQ18lNB56`LgBf}Z-U1im0x9X zLqpNsAHYR8(#yj_wi+%}2Iv&oIU))4ad#B{jBBdJaxJb&i%A+HMFsqljrGyBS|kpB zX3ZLSbtxn6-DiojmZns}(d6 zGyu&@g@S*9Q`xLf+8rG;cThQpME^XXWR;w|LyH0b>QNb~;CY7lh@}s;^+WC~Z39)* z%qov#bco#~7|aPR&k$5-Fv^G0_;W-E1)ELS_93JBrH9{+y5a|IT1XyoPF&Ddm`~f! zq->2KDIcvp_B}u8{Hac;ymyN80hdPNot&($l1BCTA<(g;=9hSd}=qMjxKCp>4Ya#*<^uNk3i|(Zqw=GsBIx5emJUJm9_h zjPBy@{?guxdcfe~UI172(X}UMsTIHPe7+tTkah47YPOh_MZNRB%q3X&T2p>WV%)!f zPK!dtEn>FChp{P%I+J(gYBHwMG7zjq z|Fq7ib)yCCKa&ky3rXJIY2)g(7`X_}B*+)3$&q27I}SIsNK#)m4t==&Xe*U7mM-yX zZVc{Q;st6mqIh6gMFeLCnstB|kVUU(v|6x=o0Qk2IbMf}QNz$|(x1!RBEp&-s2%PU z(xU+-9FvO-s=|!Lj0%0!d4WgZ3?!I@2Ak`3gO81kTchU z=O4{V>WeDHUHZq>MCV@_vS0H*JcEX;*VNBXSxr-}giRPq&KEb)juM|))zt{_+cwC& zTtNlP668GyYA4eI+k2u3OBM7O-{oBkNjcrDCx6l^$Md7m0WG1vI4xf0=?6RzQx!XC z+OAN11Ggg&^pR|zzXW}7>N~yGTv>}M0(Q8%cTkDll5q@1ekAzrDly)jbPY+w38_@R z_FSLNSeEP<>Curchd@vUjH>LJJEMDtU#Ib+Kq%Dl%TsARre`TFeR`$t;^Pe@v#XuIE{AURJ`>hmA|#In`1}c{xho6ZgXOIdFnr!vs|*F zpy~ZlxSoyTc_2^bq@9Oe)pS}nuU&tjI46qt--ltqeT|j=X2;V^p)}3wzSyjrw3lF zzrC6Ww7EH|Ml@#OKQe0aT0O=gNs0e6uC;ja7o2&MD@Vhj6sWE&u}OPzd)O^`-A9=x z{`}8=>he9(gY@7*_8fC$gFKt(dA<9OQz-vg6T>!CtbeC#P?7tPalz-lOY1=NFXo-i zsQDM&GAY^Wa@Q2v_vxyjl%Ii`~!&lQZHS_e$rvYBKe;$)nuVsWh8H5u75)* zRq|cxlmpeuza z=$2yy*R`{oi}ruFV>fO3H&_69Qb^nk3$sT|s21-QG1fnDhLHhnJ{Oo>hKW?^pSvtT z{=%=Qg;Y15(BhzflB+V}5=!5NS%&}j&pjQ9fP?er{{3}%*^VQZk#75Ze*x8P^LT9v z|KY{lgD7;HHJVdqqbCF-o+uQFu=@Ry!nH(FMD>e1T9|V1%mx9ELvY90N|SweAkyV@ zr$4M>249oycHhZz!!pZh)8CBkGZew+%Gc@Fm#6VGZc#lmA`7GG0{QE+lZJJ#AsWgF?y^xSL6M>X>jP`vzLK2KxDx$1x+D~iq* z@ARzW9VV53TSWan2^F9Pi4?Gz9^N4I^R%`xIpB{+%>?8{g5OULtJcH&u(%LfJGxw~ zyG~iiQV^EcIZPJs@&00a28h=lx0mH)J72B?22;!v5hJ>>=RDi&44|Q3_eT=A|4nz^ zU&k*Nr6@lNJ};_)cgDt33m15=ykrdD1uz#j1*v%TxjFv0=VdY_UZ>;6%OSdlPmdW&gSO)nz8_%s*H@;Tmg_AgJ`6(QD?m~% z7CIKyM#G8nta;vQ-Zs&q*OuN-XL-QfF2XBkXADhajx>Jgm^YuR4PD9aa)AB~V)7Z83Z-3^i@Rjv zCY{&W&MD_BSL%i0b)g*Mu7&7r%u!%~zea~w+sA6`P=wzxKV*F8DN6H@VFIBktM>M# zhOAZ^ZM)GM#wYY577Uv6;vNXoz>Q+jb&J9rEE-zlwDe#Kaq2YEj|X9fSjdH#bdiyU zSa#pQDC>KpsobP)c>}gyl2ev+pNG7Mo)Gi7BxQ&$3Iz|mkiWeQ*?*X@f&x5lY(%|H z-sA5-a<@LSw%n_EzoeS|Y&@h2Aoo|ju6Q28VtX+c9GDJN@03dnY;(aQnxDDccrQ>A z%Qd=+R=f8Uyp6{Lxc+jSs`}Ay$bv0M*D>YzqG(4haEkv;*XGYF@cf=CV_WeJZ=Gz? z)Ac=52aqw%S2Lc|-R&d(NYPeipmJ(B%Q*B1+s3WNu*n4Le~|_S>Y3w8*-=qIY3_{hMq<>@9ThbPphry791(9 z?gJItR0A)^@vmF}0N?AJ;Pc}8%U}G=0EO;;-R)63TP4G-Rm+A|${$&`eB7Bapwos8 zM&?{WA?@WRd#XB{8Iek2F6Ql>!8lT=;@iScif5i4H?wLF!@pTgZjTqqIEQcU*FeY& zur$t8q|VsYOcoxepsJQFF;{z0Mjfsd$DUPLL{Ae0d-Uj-h`dcP63N@M^$z#D)6x$% zkB=Wzsn8K3i`VM9!x-?j`fN&F#rf_K-t$A*Ntm?12{wioGeY>U)POm<7P-Jaf^z^~ zZUZ`~S$IpTGYjre`cK2b;>~6d(d}_`u1Ws4%N3MWqYLG=esxco?~NXlim~7U15Caz zJF`05XZQ+3`8zrVRhmO_Eb0D|pTebVaj(OBJO>~D)V{(g`Xr)f-;I6%{6Q5R8Lc(z zxBHZnkC)%)^Y;xVoTX-eQ#FW)%@}hK9b4IJO6X8)Xt1JLC|-3lh63n>INo>WV!V@} zrprCp(G>`T@g&msSK!+dM~gm(D*5?G_8$hni%eE|AH3f4%FN+FIJAO!mBHM@yyB`9 zgd9S0EH!b?#+xxlJrrw{BfzQ9gCWg0gv;k9Yegw1R*lO9BzcO%dGx6e-8m4vaOU@W z?XG*w1AB7#b@S%h$R{eY#eZ>^-`vp_u1+RZ;QTv4TMeEt2GLNw7@)He@hkpyK{ zg<>NBluAYeae~X1Y=M38;{Da(3IwJr%00C9)ojxW9lkA8j;pzx%2N*{IF7F53Itk_ zlhR)R&Kt_2)KhWoS98u9qhqTit-DB^iDmNblNWvRjg#I28Yvv}*O*Pxifvb8yqF*j z24DE%lU*#`Wk?(u>XnY5o;c1!3hag|v8e4nEb zXkKJh;gb=HqWTW6B=9%mORKHd1;%JiThM7pTZ=LDadyh<4N_+!e|`Y?lq1{kmj^V} zCWSMdE!D~X!f{p}$iaBig*x!6H1|Mr&Ep-Ev`Z7mjT#Lp-F%h(@ue`tt#2Z_dJRzaAgUH*KK7M#_a%lFAd zP+tDNu$wj!aoCD?Djr`brQ$g!<|pfv^zmc9Qn_}{2qybbi^b{yO{EO;{EGZt<5XyA z&hrYxv^Xlo)8&S!zd3^$-K{^k6(7?^9%rSZ>_lq#2y8$GYi=odfQmwnJX-6IWQ$QK z3meWKLI_O0+xfF%W>J!?$p9jat_heMe08Len|%tn56twBS7sGgucI-cjlz3Z=2|pDMF}P@Mq>W z1c>Vrz%Ks2b$^!G%nOrWOrS%BXYCKm$dRNT|1PTx5TcshFW!*z-KRN-?_TY4`h!OD zGaT+Ji|XyryZHmBMXO6rJt0-${-?#Rz^5wpOk2*3<6r$ysQFUsQ3SjaWl8PR@*^?M zZr&mMyP4%m#Kj4ghs(0F{#|5&@|@9VMLLDiHe59A4&piE2VMR%IUnwaW5^`c6@#-4 zS2;rfi!y@5P@zVW$wipiEC5c8Hf!istQw zVxs1HLb5(sFYqNw&;6QwW8|z+j{{I0Wxvw^Cv#MQYm0t0BljAY!{nFxf$WR)I4wS8 z$);LpzDCBbN*pGl_2(hRt_8h*RwM5rX))=JmrUtB4K)C;K}Iy2{q{m+@A44jUAedZ z){v>GthzVWq-ol91SF8BSrzIiFY0bw;jqPxn-_+~bzN9c{;CMvi{MBgfp zpJytfzdTHO0Cs*n-JW<%L|V9cZ2W<06GeMRQ3oB!4b9#V@?d3LwqpSPtgwG@dKZ8D z*A zhVt*qs3GrO0Dx`d6fu9=Cs*qKCpqw92Up$InE$DKY_snMC}!-YHBrob{r(YJ_0I;j zczfncssH0jlvTLIUkV3XVg7>y$YR2++Wrf-vhUab;J9_VY&+|0WzF4u|6_wyvVEqM zg_FMj<2*p@@Bao1$YN!0c}#qZAo=m1A0I3#RH`9%X*9Cl{~iH!io|oMO^(R_9&l@f zRCJ-0glYa+mSXz;g!{wsd`;e0@NY;G^r)hF+U`MHEoU#cZ>|UA$N$JybcpkOMS7`j zf+VrTWD#aX<5t|;ZQ>g|4eWnTqeI^APC#$ZooCf>Vo%@O3mAJLIy44>r2i>}ybU!e zSu8L6(4aGg43PgPdy`=fQBQN4^%*Y0_x&aIZ*Fka=>rdXP2;1(j;#L)0G@~9id9?z z(f^}|>e`g3?&pO6`2>VZ(JSZ^{QDW)YXq%acXOkEg!kXG4_0rjBSQC|PJ?jfe|F)} zB^@?qpLwov{}(YF$wJQ-?cQ!Is?2}s0r;N(v(wF&%M>3el7}CKY~()~AONA$*tdu; zfshCD-?W4RgPQPll?eQNK3x9;>}8rd-!!?n2O$4%VYsn_p^ECWO|IGeT(`8rp4tq? zHz;G7LF@p)pE$=7Rrv(XGGchUY`-y$TZ~}+V%0?;s%PkTuSO+sM~jW`&c-6dkNP9P zXJY=yKCXAs;xMj6RfjpfTua?Y+U}@VFoIP09?}fSA=!Hs`yzmEqD;oSkYTp!P;x|m!0+YYJA$@%J2m{8n8621 zGHfbT&;7NqU@u9f6dpduTY9kQxA)qL@3S6DZ!wsqweSF8A~f|S#SCTT%};X*Jfj|> z0sx_&L4pyMKV>n31!R~uKD=N5Kc88w!TEOZu7m&d7c-s~6@T>}%o_ z^n>hvE>gGnO?=1=!08u$KP&k|eZTSipjfU6!|Na(KvcMe8C=%x1XIRLEk(p{wn|<)vATO^8$j|G(XCZ6#k&p|722C z?*}WhQwfmGQ(6@!=n26NZf9f!&_7kdji%zPr=^us2_EM}Cfwtm|Dtb3<$tAu%7E%0 zl$74FAtXK_nC$l7JBC~ziV|?u*+S$U&Vc@(IUBTcKt_FdnT-&)b`eA`lNXkEzxBBb z;q4G3Gi&^g&=YemS+L!;pCGN>bgg16?cvn(&hse4UDx}hu8EUiIRY_QoBa8>P>{ku zs~j-=aVx(fy9>1o4RP!sN>ITiPuG09#o#NhnIP9`o1;A*?UAI8(He0IYp+>Gvn<;6gVEO64`aSmL^QvRni(c@ExpO{4-A(`w0p_7sLb zbaNGND}51_pS~Bwh#-Fr_33owG`%CCj%!fJ7$E@x?61^1+>WhZ_f}a=5PhXMybl6! ztlDo>^Y%Qha!oR_lYGa$4`lPu^pR|oi6sQ0B1OJ&z43D;{sgjlcIM+xYhmBmpV zsJXLnq3lcsoz7QuxbMlGyl^NI3ba1Z>FIkPgth2+ztqjQyRUnumUrl$Qr!(!{Bk0m zzZE$5aS_(zB7J6di`rLQ{fWupNs7rW-ubk)*7jV;C34D3I&fEMIS4^Vv`hOTb2s65 zsQ{GW!>ai@m`%m(X+~u*MHcChhq4RxLPcoGe(Ldi>92IVZ+ABluW66DT_$>OdJG?kl`9NS*uXz}J8=B!3Cpg^snz+YYfJ> zBw>KuhdfnZ0cY#g$G?KlB+gSdNM47doM+zW!fnhhrqY&5{v^{r`x@=-Mn|ea^D~6| zWpML*%k3{G1%W}QoOnMT@gHCByst-C``~`yV#1hZH*vppSxkf)WOM$~dwQHtg;rGL z=hpfrjNRgnZEhwbu87LyS{mhgHu9xiex4M+l1ecnZymcQQnOegQpf!j;JvE`?4J5u8%OZm6xxjF9r!@ zw(Q|4AXFuXQ(Di~LI;3i&-h1wN(2_VQ&&ae3mgwf2^4=x6F(si5#Apbjp8rR>+tCQ zv~Ape^%_JtHC&KRYDd)@(AC`(!0HNmv|F67;s2Y{tGgV??QPxmP!L1f#iZ*#TK`p# zfVXaVDTz9#SU2zA_?uNzc?*-LSFrsXfia|JT0^Ac`h=4^3~&Ih^8`Aww8H-F?Y>nwMe9u)4v zq9oKPINR)4J=LX^+7zoK~j7LqwUr7Y9#CYX188AAfb$Qqf{>&LbG7=is zMVy^0tE;JNclw(i>A==L%s(~ph}#n_<{-E_!hzNeq#YiO#gE-0PoO4295ndTaN%s5 zDUhir12=f?u5JmF!-bl4dDCnoKXV6z?x~u?4F^9S2%2yQ7HZa$wbvyE9Nm z@qBw~#)&13jcN3d<}8dkW#WwAO-hU+w>eyi)%;G7a-cA{kk)R|@SRhdAQp-y;il1k zQ{*e#RHTGrI>$+tNEIRgv(I`wbNsOVjnbZp=?18DBJC!n=?TetTg7Rw%P8B~|#);l=n-AsL<5=f{8!WVhft)iTnW2-cM6$%dig)Xt<2?(R>us5x{qTwrNe?jn6V9O9&rsa z*+1tX<8w3NgE^$fQplGz*JlQ_^o#vI$7BkV={sEFq4?Prf1+eVm3$5;B>fn6!@!hD zN{^KYN$_135Q@Slt(tOkMl?G`5M!t>i@&;VmvlR4elUs~?9OPz+K}Ut?81>*d-GSz zkcO<8ygkq|le#lieG}A&OD|*J{c$}e`EM*KjAqL9^p0MYGSNJmJ)Og{L$P%MQq%{= zHd3T^i7j$Pj~rGtlKJ@x4c3X@sWh}Sm;1ZPj2;y+L9f$48^|p>f;0a1yck{R@E%Z6h>YfW7 zJ}<_VJgw7B!F&1#(~jbZSlaxnxCx3u5wv9+vXF>Z(t`!R)uiQd6_#n!Nr*ra?R4f_ z+M!jsuHL-ybEVBQUtO>)dgxMAs>zF`M6UVv`JI{UHJ8=i%Qzx4CL*uVPc$p~8&y@d zkJghGzo!CdEwDQ!vXF!X4h$B=CJ|cd(qe8~sAE%nku-{9I=?Jsy)>B2F#60QFwDN)OH3lLc^oR*+n(fL^ffrv0BmrF4krc( z-10}jv9tF6IRbWu6O+`7XP9w-vV90dV&Nz=mu&9G^|qKb>`NHur1M!qW}T7~NM{sS z;WsbDQN!Z9_~_g=ffH$LsXcTYw9)>)Vy@x9$IyD-eiNkZKU;DVe1o0hWzQS_m(b^h ziSndK2ILg3Zuh@U+F4T*sAYAjqfrEI)t^)HB9)ouq{<`UY`2K1k^&^#wpnM;h`%=5eEdcLdss*l{;sY#&* z`%IXyhxlZvp1e{(p{;}tjMThl|FNh4Z(nYIjS&y=d=o{I*}crZJ6^p#vA(LLcW#x| z%W9dNH9?zjR&_6h7N@omWH!fhhZnZU9*z<9Br zJDL~dGH#;LDsFbHb+qj*X=3umS`z+G}KX<4ved$*UReZhg7Z4F%!u>68 zjR4Z=^|CTut>qT39JXH`h- z$7c8)1xf{iCm7-pVhNGq8hKEEW0ZW4QL+*Fg6X)JbgKB^Qv5|@_^;mUsT2pxn>PJh zqg}TH-XuL87`w{B^e_y?<;22Z4o~L?C7&wM#FzT-&$PoK=!Y)fpd*U52s5it-BjQK zqITt#UyxfL4Ovn%imZQ8VnkW}KAF~M<6~m5G%YC+dJW;6kEWilfh z(3_B92u1w(o}Ne#<}Dkozig9)+P zGGc9zd>+Yla*!B0zonhI8oxRBY{Vp(;kVbuDLD4k)bqQFO0}WOkA8WX-8p}6{NgWh z;zn38$h_!t-V%z^q5Cnhmqw*{iH=myCFRgYM?GO6$)&!e{0$;*4|USrn%wMm@Xm0} zYU@ebCt?h(*-b+`+u)`nknDGCQrzGgiU=lIJ(&4bt+Ph|Fm zY*i#=X05AfHtBgg+4j~6+w`)>4%xx1*wTJBIQZQDn+oo=e@hv8yzq-=uV3L5jxi^%uYC(C-H=lEY65#;wW1Y}av{Tn$ah20J|8URG#ig||9|7weX< zXgp~eCI@@yEN_rmJJ*S0FZPYy#1u+n0Kw6uXZt+6`C-F5ikSk{hI%vwuwmX$I-A){Zvwbe1AxamfZJku;j!Z|&Tl zhhMPaOceX#wg{Uj>r=;Hoc`^`UL69bEhoqYr)r3u-o(ACWg1uwl79{k@tRCktGW zx!|zdaW5+ziAo$>j=q|slr2={+p*;cLAiBFTWiZBdXgaVIPAr-)>w*9?(TNV&Aev+ z!si{?AzS%$ES5H7$?{hyc2>#vagWmJ@$sve+ohCE4gJKO_+tzuMN^Aa6^g}~?&&#M zlE!9TJ4)qtn$4|iNbKf=nrqd?!L3uCu?==YoZY>U;F@|WXo5j~bypVnD|ZkQrss%{ zL1h+t3k)(i;-ON`v|E;48rz9%jK*o@o|j$nb!VQ0rOT(QI{kFx{YvzfKYQU5*`?@d zc9YcM0W$?-xHV7Y>AWIrhrs>954Q#+ z6u+zJ9M978Ew@Mt*UieW)}$`VC9AF`AiCioeJ%_0!gMnE11f>!WIRo8B!>FxRR{96 z4&enf1vp)k(X|+jW9oB_zG^FJyWpr^hklxph1h)~`OV4gJ_~qfVf%mcQk*G|!jWG` zu3_1{Ph;?PqCQW@m#g}hfA8yzhC@&NR=}wM(NoXar?9^Td@pPrpSVIpTBhs`KQ}#G zeW|x=eXJgyW1yGw;S{{@2YJ73!s<4t63poP3&~XhA7$XgqT@g&|6Cfml zFH3Lad%_@YWj2jT@buI4{n!M1H!6oc#c^4o)a$>FZyY}kQ=?9WVD&RA0b-fWr_O3&;yDaef&LScE`Q%MRfzK8-Fco z_R1Z8voP7qaJ}}0z5YL%t}>virduD7?(S{`rMtU31!<55=`QJR0cntKknZm8lJ4$? zyYc<*{5of5PwuJpthJt_78iFJg9E1Z}N0jOSWULF1X#OF1@_RDd zovT`&Gui5KL*xN*FO1_SV$aGG(mq?U{*F71 z-YH1GUiywAl4J^|(Gw$`&K(wKWxnSE33hJd75MW*e0ktQcn1$fVF!}1hRz5~L2$zj z12r!f75o>lkDdIgltrEmLg{`I5Zpje*^%_y9kRaC|4?8=I>GW)WWKOL2TZBg> zAg(k+&j-7%cTUT+Q=MHiQdJa%C;$on`CTGFhr}Ji0j?)FQ3oGD5%A54h$qUbbI`t? z;8jUPJ@a}Va`IU0T3(F(1n!%mwtww{k1tPPO%l)kx@4v+=(=w}+K<|avVnZR)LURi zpis3{!}NU9fzF18^R7{{aPp44-`?nsU!*0uK5I4|6C^K3LE^uFC~CUnjzUu5Z}d2t z({6j56?oe~ew$vleLHzNn{M~~!D5ne#`j2r0PmYRo6LhjjXv!>Eyuu3uUeN|ws$id zjOn{__G^#-m9qp};v0DEujl#sig%PEARWy|O>RvWX-Oq`%D{ zRfN;LLk_n&?4T&$NlaKw2jCLimrn5dMC`u*3Qg?T^8(z-wizp>Yn%$a(#vD`J?yb8 zL*ZYf$fiP=y(E7t<6T(G5jq(Lr`opG(xy?oI^J1pKR|Ru;XQc_9}|86F|Jz*>{D#z zzalwZf_sIKaFm!%ql~M4(N#6>BaNnwXC{x7R9+uc^pk9ggoNg5@Y?Mvil>%}jbT`3 zgKmF`v^}?`7^|~dmHy@L>FGF^A~CgHgsqprLyO}`{US5u-zCn$%dMgsp6=;!hqn~9 z@SIqocz-ZfvFf&miO)XK9u$osVSjQMiO;3ad!-zVD17&PFhaGBO*bR5_QtPcbwcf7 zK6fYHNgh1_bC$tB`chr0c%Wy$0c;-Ky_sWaq74sY2IIw8!SSBTCV(8q^m42Lim--!!E#mzj_+Z7Ein7 zlMW3O!O+Ipc@Vq$QWq|64ocXC@z6)?uQk`(q?^^u>FORTw!CEriz-a;0pJQ%3FT?g z<`IRoW9vY1VB#pl;m~O^mf_Ke43_L<@G5%A~Qbf41hZrDf`l)L& z&#F;Gkj?k!&PwJQ1#UJkx?e6i2*!Og?0_|Xm^W)=YdA=mSCfNdOv3XV+hZ#G zeE#Q06Jy6q;F7#@5-1WFQ&@Xvhe6EuR3EWy+%V@LfitC6cWwM>Y_oLEZnBv<#FK^w zHjYMe9MsY>qa*$8ZIWeN-x?jn&+yDBOzIvhFzri?z5*@?H}{!-8^?qSjJmtCse|mH zb|LcadioY*L#JJ5^8$d1zi|cv<>vJiKCc0CV2}+8WsgV-|HkhQU~LP$wS2V;VR_2A z-)9jSvy0waN?&3OX<$|VxnN`SR3ku+Up+vT(niB^*2>cL*WT9sjm75{6X31``F~Flc^+4Jizb_b?ll^T z12KHnC%iOs1Q8a0Ru{j(b%4HR2$8%V9~5ZY!r-uOPxdA0xe7T_4~78X>^QRbC3<&l zH=@L?*Xb|I`|v^$-7ms#m+Q>Lj~wDO&vGx-ne%<4wAH}y@Y&xphPq-ID2%DU?N2k+ zY@++h7;WOSX9a+-cL&Xu7zAuW7!HUO-&$_*0qV(GWewSavwZDhVelyYS6~BH^N_(% z{;=YIZ(~+5JGy;*{9RYqQC8#Ddyj`6g+Xr$J&DH@eF)A{J&nmrb(6gJao6wGAp6`Q zDb*C@D#qxAwfEq)h0klD@Y705vpY@NWlF~qL__BD^!h}T3UaNsnf;iStxN)ser%5@ zF29ubkvV^4`3aX;mmkgNIHRpvjS6XqLcj$(-%(Kqzzv$X5jfvOJPFRzkkvQBS!j8J zHg*@Yow2uGcT=Cm`i3HDBN$9W^sRxzGW|#-f+2|(#d0U>@E%Nmpng0sP!-?oAl;#s zP-{xYvB%9dNbUs8hTc$g`n)grddCCUGmeb0O~Oj%JZ`B?Xl zXL$djfVVB{SDAMGqlKNmQZ^vbdcnO|Vp{F*h!z}HzmmIblVUwD5$$so#RDh;=3Epq zsqPNOwf|T@duo2Ayjn2wg!wzibGnY0={BO;GK`38yj(>}&Z7>WW{&gBx$QDJffYGW`^V#s3$*xvFkrI)qw7n#f2f$fz?#FF;=yx~~oERHd?*-&Ku z5J%Ag?9H!T*zK-YW%cZzm||JvscJT4_!Y(zY5*ll zGnKsE!gY+K*&u50?$#&U%EM1D0nMtO>q7H8a zXJtB;4vVD9(eQlte^Xf86$!znb?%qaUBVbL!1Mz@IzWLywVuwScrZPZ-uKbAFE7D0 zbrp3+V-*5b7FZ#jkJYGXA#Zr#sMo_40*^G)gC4*PpQ?5?*!VU4*`IIde?{v;+)%-)PekXYYQwI7oKWd-@jiJ z5AT$=fF~}jlI7<&tXhpXD{_^uRm|au{uZxfLy}--eyxRL(E>=yjMeFG%;|NBL<#Yj zCyOv@)kbcn@gvuYP2N6a@$%QW-z>so?|%UFc!GYBp9Z&IYx$!O_NMPjmmN--o0ho5Kp1_}?*v}Yk{ z{L+k24bv4FkyHjnzH1i`zeh;hp;6!#v_isz0R1Y+mm6Y7QanlUTA_AGC4>y$myB(* zDKPL|(<}?L_T_u8<73KfNj8#%bTEz^*`}@-gc7u+1;k0xH*gK>3|b z2Q+o6+JO6oH7IdUge2(ZhIFTMp`=owRO_ZBn*VYA*-aA=4L09z-BR67oZ`0L5M&@a zv{UKl^{zlYpX*8B9q9v_W0-Pzfm-()OimHoF^J76QX2EVB}PMN@!KJu)WrMct33rD zK!Jx22s!A0(w<$mASUQT4l`kG!3|0NqMP;?JrGSMpiUOctik>qBTG>g(g+xwtm_NW z7PCm^p-@YeZowU-6hF9?=U z%ukx$iX&PkFkoE~)+P}90nIN21##G(g@4;hY1N~4|)0WWV?nEsKj(LCmf9~=ekpCv^WZyu-i z!X{SuGy!2B<~1qs5Fk=1E2;f-orW}|@`Cevf9W8_YVn!CY&i6gKBMHqe{Kql$jnvp zvvS>3=sEtt$N_rqgs=$_a(M@HK1s><|Gub2ebU$=Lg2_E|Ji3;QK2Vc{8bHXLUDW7 zTmz!43b}mt@xPzqANQEK@Y;~c#8ZGd1E}yPL(BsgS@{KDq<}RBgbDgq<-s2FthXYY z|1!S}h}ybgIn5CLFUL?qD3h}FubwBEz;`x55QzC>FDRt}wEVBUk$TzVC5QPsP*u%nlW)AvYUJ7&3$J6Ul5s_0`t*<#aytok=zj0)gY%O^t`u);+D%H9^=;aaqT zWBX@%!>H_(EJZHARX}2h`(NSf(o7q$RPa(=s!w2a!GK{omN;mje5b~Inkr8f8Eb!( zoU#9Su_o9a^#xwVG0|8`^Ze%1x{4s*0vxjn@6+8GwdL7D6?y#AHgg`v!&I_JY(iG@ zF)$8Sr04}wcyr(qDYh*a;xFUqEamBbr7UFfnfzYo>q3wA`xDtZ&CZ=9B+#l{iclW+ z8^H!}+W~0yT^W2Hb=J#4b8tPwJvf2vayTJ53-z{{N`HymwqpV7{#-;!qyzT2Ex?t* z1F8QDVcb){DNYlyFU8``ML+RcyN|#}XhmUpPWNk?TJ`!>XM6}U9CfPCJ?`PSA^OaN zzmXc-@_hjJ29h-}$qXGPHKc@i^bC(vE(!=qT4Yn=Jnmsu%iLo{YYj?!Q$hJOPN51L z1-=`Mw?@Ea0;t}0p|W#tak@ZZx<<8fFm|xCKb(kTDcc_!IfK_N?ysENLIPioi>SK_ zMKl8R9WZuwTjEXfNO6qZ-p{V_HBC=wAc=LZv}66UGgYxEMBWaeHDp3=QJc7V@q$u2 zfktw$Ed#tZ;dW(NuP$2=g;*7rRVQpdNx$qE6&zlbp4c7?EopEpxLeLB8@Dh>4jj3` z9w}NRWlr0M4JbH9$hgripQT+xhKPZ*geElC7w2dUhEZuP^-x8KHRew>q5To@PMNnNUKMYBogKIO*iqoKn7L1bR#ri`wt>O98WE3fb3*qke_G`?TlgHFe61 z0rF@?vyfo9hK#OT{6d*6=OK+7V7Zz^7 z{dPX1Zia!gd~cBQo3^ocXGzrtPEAwEgkf98@@6xth=;o2%0LCPXR)J@gCO5h`Mj(w z+4@9%E5PKK0JDhv&4J`4H6n5F?NXuOwI98GQ5bZ)`hKokXqS>IHru-a!gRP1n{Bp1%^%H%gfogJRP$W1z}y_-yX4=bvyots z`Npt&G28?5*9g+2C>kj#tSlrxUeTdL%7!7l3~}{HB8}$^>3+}5d(D|refBb3N6Yu^&Im2!>(6Vl z;v_POy)TyY;W~yzvP%pK&Z!&T^>c(9+#%&SY`Gy&E}SPCtmcwdz=c1g_Vf2b&#&Li zb2QfETEAp~SE>8YeMHlqmUO*7sx2~?P_KYnL{)MUm+WD~>UTDNu;UZqMho}3JU}~- zJrFTFNFb``*_}%w?)6W?>Q} zN)+s0yDU)je7Fb9iRjewyidn9s`|&DU7EV$2VMD9s3THLA6>&%W5+m%`P^sj%>mD& zTA`ft^B&ZU;;wkrh$?*VIp=BptKHGs`J#qCTRNlW4r}15Y^s&HvuMlXa+*N*oW7L` zQLQSvKp|Fi=f@#!|z=FJ53Y|+^ z#cs1Qz>mk_!iH)hpJ7;{x2K9iH<&3-^;;nR_pkKURA%cgf+;r4AK{>Jt{REc1@aWk z6Jnw<`P&4}=1bUN3c0~mtb2Dp5dyJUcF9jtVg9E4vX)Ia7LoB3M%1N} zjX{5`yIyLObva2?N;!X;P}Tw-Ggu*IH7>OMS2z{Jgjx{PV&c_QvW#-fNxZ~U3+(zeY!rBzp zi)ypZt(N|Tf{XteufyRXJLqB#Cl?b?65Utu4iod;MjR8aZIpC=o)pnc)pU#%Wp@+e zP?;reDZ^7+!BDkW5Y?>&8)TzpixQ@w0~ub%ncDo$y2K*AX7JjZ74FP%mJ3`b>*(7^ zE7H>gJeYI?Ub?3f2wLbxD$u)_Lz~AOdArV*Ys37C$;lJ>!Y!uhY@#+%^yr|HKL=@T z^_U+2!7S>gx^}fjhjK>?F~8Zs88_LT#|DTiuyG!p?oL;kp2%0ecO!oN>UF!eNupHA zCHd8x22_R|Cz!q5(A>3`_q{`O<5VQr7B+IcN77S6$>kwD$&iXSFY9GB;Dau(&V-5 zrKP)yv+XCSgvQ39t$Jl|iM_+Wdd&7NS#LkN(X9M}GgcLJfFt&rK`n&du;JVGr=Ddy=Po}+B7v14 zyquEelQC`>Vec>I!A{D3>GPks7e(tS%5p5+u2wSwylLUj60jebVX0jNw?0jqTm63G zRZ)`DBp~ZX`PQ`kemoR)vxnk7LdWlms60b#4)IL?gqKn|O?Ww3@zR<3?mo6qV$IMv z-d<-{J6t?TI^N1t_5`oYB4xKRYZ_P(A{$#&)*!X(4p@kuD~&Zd%A^L;6ed77_&X2( z{KR{ck;-@Z2>6rc?w=FT!-Dc4S4Tc@2mRfog}%0pLnkbJUFG)&7c?MONUbBY{9%({ zc)_1g&6Q{4W3(hvfM&dsB2C55>mQ*&O6??*ms^q{lL}XMqfo+-v2jr}LB;|*-gc6p zOYrfh*$1pyir(z$W}B9SF5aPpDu>_lmM36AaiQ=-B#tRVuF;Ac5xS{DCWe{0jI65@ z2{o23gL|D4xh49_91@~GD9Q*uR+}EYrzPF}C?|+IS#>?B2^G{xSUf7$ZK zQapJpMY&T6G7k<}1F5!F;s~Wcfy$1e{t1;fv>R*oesewa#NPM7bH<<`_GmpKoz{u7 zc`hG3iZd)W6c)nJxBsTg?!oRe`42rBYNzS@`>-b~kcS+W%RF16W(KA8+Q_h2WU3St z?q`RX>r)ggt zmo|Ex{FqBJcfPh20f~7d<$h{cj7mNhEuHw@0p3U3>xT0R=ei_>{9&)#RWoE7eg00# zII^e~)0VKFf*;6M1VfRhL30AU_V>X$nG{txrbZH<=2b^8S@&PVE#{M*)3G~0<5=X^ zIp1)k6GCOE8(Zd=_rZ=Wq$mel3(F;M(2u_cFTu}+e0*Fq-`lf?wuZSqS(X?jO2qmY z-_j%}54~xvvl*f6dTJ7^l)_A(Sqc%6_s`8@{(PF}h-|*X#!lxs{)4 zv-#zAo0(%geuu|!LVVE7?H9$+Xmios$_jn0WLz}Q(f!KUWM7vIF zr=j74xpv&^?{I>QN{yAv$!`8NTI=wd(Y0pd`O>!0;-lnr+(4vGK)}_Rj%=wgzEzyXj^7|> znu$}?-}Twhx%v@@n%-!yP?Bq?4rNcJh-!gm*(moITH%?wUm~`6I9q$(%kZ)B$h)G@ zPeylcJ)>}J%gb~u4R8(S+tGh>YiKzeF=mgB>GyHd4QXRdoM*f8OT9){5Q%+~yWrRU z)YBWGTjo061-QL;?x!;c$qab4#q*RO2UY>nR4+Ojl!7*w)v#TKPSCOQ%0-s-`QT+F zly-f|#0mM&?eqO{_C|Gl_9|**5ZexJN}&Zsuq;uvPjw9z^zs6J^=yXw&&n(0)@l`y z71LzG#Jr9Rp&NzFcizaAZM@aN;hKGU8zR@Zcm;b-aN03@TE-0PYMhGnJ!lTwzg9Rs z>2T@x)#QWM9V*T_rm1A7xJ0eGn}JuiaSwB{n^E~VqlH79w3aM&x)%Gi9{i!EN=~jD zDkAK?f7q$-w?+7LAN}R+`5eJ|id zDQI$Ld>mBU$cO+81FIL&1)N8{*F5oGh4rZav_T*KgoIB=BFdSp@I-GI3qhC z?4uHQ_J=DRtj)bF0651;xM0Aq5Bg$V{T&Tw8!A7H`BmmVGWvb01NFufG5Z(b7(9}TBA3VDU6bH=QJCgr!7pUnFDaf4D z@?z|;Q4d2AjQ_A4{2K=pwQy1E`9Q^}e>sgXL&{8dg)aXUT*~NIcnKr4FZG_}JIS;> zyyO%oy$v0a1Z<16dG|1gisI%v5Y8Yvh+PrGM-v9m@BOxA|+NlL<8m|GI8P_M1kK^=f?Mhc=j?n*jFscLXIFyi``lRf(WH&?E{*Ova>YR%w&p|Vr^mYvzYmwKo)h>GG1?%}jo(`% znFj>zkVI)rDUpFv+V|(($PSo-8UPUF46sm4xioD6Y#1Cs#cf_sR5ko@!1evIBB+K} zu{R3FQJ}GpkLh{r$pV0w@ zNpcKOlV96;1%P@9IPA)nWz+mHp1nDm2i$&#)0LZUXt0d=$PozSm>AqlaU_n#54ymp zpbx?c^o<>{t6|3Uw-_=eO5HCHwib7NLAfpNCji8$IM2M!t8xXsB|E}&(yta zBQ^HbSKa3>TZz~~6h(ditz=CbMT+dEe^cdq2LE!+skWTmOhiD&1%U1YG_?)rG z;HM~j2nqGcbc-7$jy7w}L4h)7vmbOXm0-r*wX+wk zrL7r6tVe5@AEMu`=R~Nz-3}Zs&y>BWY=LpS&V1u-5p6FFMw+ z9fiU8@#oXG26zMx`yiBU@mTmuT|-)ZcWq&xOTHP;OKV55C9YhvDu#%^g$?-jMTGmb z=Dai`U+blpMcR(!YDFgJ>O9fl8zY4au|1H2i0t7Inyne;CG=&*%p!adNS!_ z8A@YK(4pi|mK?Z5Ba(;DJz&XUweV!CYoLA5SUT@b<6Hj3WLIE25UpoZ~qIR@ArUpp6q%sO{uX=ZTp+QCJSEEMi|m`yU=dAe=(~LQcdMg%uo>K zBwH>rrmXjU3t#aSy2K9gEbvH>dPI%r_^yMYpVo*Sq9b7Amu#DwihBG*e6iIj=xYgl z{KN}?L(d_LP81Q}kV@7*&v>eVYuLg&uZD_H(@*ekfBOGGeEWFA*rI|H4D8YHUTz>-uz?TgZma zAD!x+NI=Oj*#mayC`hoh+6Xxx8e0`(lfH#Mz_!O6+-j_CIT55osvYa^ybzIXoI-2z zJDhJ9UtNh6(@&k<_V0@7-ol5{6y`Do17rBB1a{bpQYPa zIJPkaWz=qa3zB}rJdn#U2uY&u?0P26%K5b10xHCW8l&N4e@uCLITl(pU|wX_+`L=& zYAEhqu^9K9Xkq8a)&&;X%AbCZ47(#O%QZ=IWb(Q(OUa7GHKqCi_Z9qbOwJA)1;VQH z(EODNwvI9(ZYGiTHt(0mK`SruvYxYed479Qng!sxSj475?W%&Wo0_v%LdfH+$X=cf zvlFyr>+TG2EN#QoUO3y3M(>mDP+CAyY|>AQfhG|tv=4~j@J+-rZ?MGeRq|^CNq8>b z&!B93oc7w8U^R>~6VYIN8MqqqvZs+M{=itv;w6}=tv-1`z}MQ))#kN4%1p*qg`q7tKrF++BCpYs0=cX$0gdhIf`Q-0(gEo9sUY z4p*%+;0~3mGQ2k}ZMXIDAw!%0bH_D$qDXOJ<i5E;xmZGp_ zEvQXNrjJ&;n<2D%vd!cX4eZd+Qc7Bi>axv~NQKl+TKTuzm`wxBKm{b~)EG;X z)9$k`eU11HwL^xMipEC8cgc7>5`%}vepL{InePHyeE*=(`K56y)rM%&Cv3qpa8znT zv34k>&jlZYepUI)OeD_T#_hphwUMrv(0JX?d{*|Ch>IoI*!+k{ggu#ms2}sGvq)0K ztSEMu=IUH-nk0z`-o;6zU3sg2v!UKBu0XB^$-;63JbUS2&u{9Qt+OAi z7$)BeAkS7ML;tFg*q2l7+nqxG2C0b0^%6hl_bgX`fBSP?jV~ph7wr+WK)_ z7nEOqI)HR=ANC{MH#d2r;{7WBLWh6!U98hhpT1&0T^zQ^ReUI6{k@xTm4X{WaQk{B z_k1z0l(X`A3!2u}(Jn_tu&8k=BtJfn{?46pbA_t?e$6k@m}YS}*D_p2E+shh;y&E} z5=f8e2A;G3=`*z)>Ba@*I8#x;Ct_sCL+N>)g8Qp?y4h$YAE9ztR&%$D#V|e6v zMDb|H9;?T@HuaRwS>+^{vdu0dWWRh?Q7zk#zfP$BYFW!Yj0rv)AQgo1!Qz;JvLqf- z9QAi)sr@{{(21&Rk=$>LjpCpWB5zTxT12$)UK!?-ib9kjL9wW>f-DgEf6)s@2?IvYtuA*t1ld+{|lM2CZ?&>TqRA$^#^w31hd% ztaBL^i{j&PR>Wc%@U}>54YK+o_6BO;W}GmQZ7*QS`tVumr!jE4?*KiZa$@I;+m{m+ zI@AHZIMgWq3@thH{;m)ziJ?L)H~z3_hIGSGq^V)csN31K0j9z1%)}f$mys2Vn<$N^ z%X0gu1bZ{Dw^NAbuaJMnrn13EU=GiNRSv*&7OLSL+8!U&%}(G1_8;tVe zDwH8fDumaSzy=g7=>9lS*Z=LTHa)AVOKn0>Y4crXx!Q z9(LajCUz&%C2z*|dygf)9TL7jqM?s3*9r+oT^*^k(;0k_ zdeWyHFH<~8giF|yZ1_%Tcs!})QP5gako83O$jXD(9*<9;IBF_+hFhaqeo?Z0xojn9ayV&H z%Y0pF5*B4_)w{gaw};~#cZg%ti;89Y8!Sb%o#C)mYS$R)@no@#&#&+@lEQK{Uol?~ zFh}y>j(S4Z^)2?oZz#jqH4RM@#!Z> z6n`INl_%Or={uau3)$%Nu-nm}8U~BZD{jl!>`R2MOQ#0=wZiS34~?NEB38J{*yg2* zC)3leF&3As({TSO*^ao2BE~6?<7`$RR z<_?s!Ou&|rd(0^-*SW5Qv=}TygiI6BWJlrD;8E=yl$Wu&0$cX9Gv=KED^#@(%Yvo? zjN3AJ+3Z%O5Sppmub(qUU!x*qY3gTpPqd)9^7}GMx9_*21^yOkjv~G-3$%M}b|V)f ze6E1;gLzci;MHYZ{~^toq&WM|qIkLJQVH0$?GxPZ)vw*3`-k&&O6kbgk4Da{j(H-%Ytzr?DNWdp$;1N&+TWfbRwNBU$1f zS%3K(8{&aJeb)E54oO&iLv=;p_un9tkeL7Yb?AQFd!c+GS5IpD2gdj+!S~Q86&xCG zLTLRnI@14BILKO*z+yu7FW*4XjWkjLOj!ach3J(&wfzJ=Lq$s25dUzUK62a=b+H4sp3)!Q|EdO29*ND8;5v*7 z{l`wTH4&QB7N(q5{QSSBf#(@aGfaCw|7TQ0St3H%9$8JdFYsQ6FJ?9pbsJyESowg~ z4Ga_PdmJOTxvLUMahunF<(aEy!Y%DqCPLz1zo+USGc#p#r_rbSYf{1)iJHB~fdnfd zN^2{>705%0|Q+s$|CBX8p&1E1rdzcI&4mKr** z&`F4x-GG++E1<^f>um-&HvxkY`))aoRZ-!XHwsM2OQqA5Kjzal9Gtl^lGB@Fx`sg;5&*Y8wyx>M{^+zvb15nY&HL15y?ri}lyP~%T zV4;z}y*ET(%m9&zZtJbjcGfkw7@6#8?H#5fOL{L?U#x24!kaBDkPfg=YW@U$6KnWb zJ}$9RYnk*JWk=z$&0$Y|`<)&IR7x|`{@nc}gsg6p&Z*OU7@yf_)e%C->-rrSyi4lA zPGAsm>6BdWUAOuo0m~x}A_4Db&Q(DLw_BcnlkB?88Tc-r>X|0E60w-g(WlZd%#ip+ zt1gjXBsM9*_bNazJy3qGhc8kA!d6ou;oui{3?f7SW^9B!$=r!Qj=i&VpygjMzASq5&Acz zpkX${C8iZ~W3$JkKmV%FQg_db3!SFgD4GgD{}*#jjUI2-LksaA9}}x#tDr0v&A$}J zZ;?2)l8_evjQX-|NB!} z%}NHK*Y9CJAC(m4Uk&Ox;*JA72b82m2tr?Q-~P1$YGv6ooFy z=U+bk2t2#P>>bryiU5TF8o?9Ed2%Z3uj#n*uMSWj@RcSz`G-)kf6vE=%;hGS@}k%f@5UoyPJjaLBM#cb#CuXNDV)kfe|Z4

zpm{OVypjhtf7|(6y$j{A^ENxX!lAl^$Hv=Rl-4b^>*Da=#b!93mAc&GvN%-*t0LAG z4;C){?HKG3?Cd+`6av8*P6$|%pieaag@I`A$8-MZ>lw;5+0XF#Ux)b(dS0*^GyH%2 z7ap^_JtAoMCu+gIbG~@yM4xqs;9&e0wuOD%?tcE55C`v}f4RM_$7#v>FOVQVPBXma zv_PTCIzogTP>&?sfnGwwYS7~+7@AI7a z1Pf1oiZG%9^&?MsO6Ku=I2fn*|I46ztnhhFH{s{aVuxF8QORg&d9iLkv3%**V+$;&3~cUdOcpjl6!l; z?FI|H#weVi{jZA{s`+}r!o48&dCIJRGu8aoo8WphSC!<#KrG!N(I!|gDoLyi`j z5;)E=wMV(D=(c<+U)=unnZ+dNM|VI^!XVjENZNCHin-BE?A5jx;T23_2 zAR=8prn2>PW#=&1X8*=yP5dqHQn*@PL+(Y`SaGCwFlv=DJJ0`?=mX6LR{FJu^L1WF zdr*(>+3EhH3Jjbrm8V{arP`Jn_78UNg}R=U^t-byd3dt)j2a4NyEloCcer3A7wTWB z?XXB=cfQwbVs3?xe3d*_9hH>tZdI{YP}Ka)gzc)W#4nXc>OfKVz*QD zZ1&P&N=Ec;(`CX}jALCssnk~5sl^@%v_JB3@RrOQfpiG53vVKDMz68!ZJIizZTa(s z?K>1%Zrri}m+^vwZu0ySVc6PT`HT;#IPW@p7gFvsM9+gWXkJv*{u`pTK2DwM47Op6 z$&U~I(vk^&P4b@tY<2|KVC99!DK3I6z-?21`gw{AHeUO#Nx-wg-rN(vm3}_O`5j7< z&Jg#B!_%#t7TV}x#0TBskMl=gnq)yWjNNutET0DJqF)NU&5&?S>gI|B*7&{5XQ&il zd%%~}q-9tfPCi(Q`!y-&&|f+x(CS81)=p}hxaj!_(aadu@@*T)DSpZqCf{_6Ux)po z-`PQ`6#$3BxySW!W8ON$bh?X?e!#ubU@|d75arOYKc{>rBE&-g_J)_GJWJ4lCji17 zR}#v~!m7pZFvZl3=kMS4x+MEF5X1dXY!o>df_St-77&%`1m+cTS1nP(~J7{@cg5r~j?C3FB^)Cg#ry;&>5J5of`6(KR{{A3J z$vTpQq_#G>myuI6^|6S$K}u%M?BjBh|Bp0%KUCy}yg(t+Ej${WGK3H27Rnw>s1X$% z?Sy6xH%1%7k$u`m;~I14bj^)?)_5J#MPV< z*|yeNUqY>Udi|LPohHB$lLn=z<5ng|OG1Q(ezvT1qA;79)uWAs)@^WbH!>j^5mNUg z#HqtU)kq+u)G`5kPx5sMt&HQ$VP$(e(Zs`Zv7sY!lHkCywQ*anN9pyNBd+hL+YX_3 zNV9M%Uv4zZU=345I<(s0BR}sK|Ckzb8(F$8OVZ#`ySQsMOkuXTx<-jT7OJhCe zvtFuVfBz;4pwj*PqcTiKRYS`$IU40}6;PmQm@snpCxNxykr|#ZNvX2A3>IsX{Q{@x z7rQ@dY!u;{WWoCm_x2g`hA_MOfGJQ(V8ois8vXC@%>@afE1*_!e}QaY}gY7 zybQ7blCRQ|7da`5tTco45*}(aW5Ay9rKZ8tFRFbi#Git>%&abDM#E5}$B-v*->T;7 zPkSR5#=9!dCghy4t^`klavuuTEDLoE=2B-7n~@>uy3$h$2NN+*{G(NuB^E!zXx`aC zsY0_iUaggbd5T&muwpqAB76vU2?7X?SxHH{WN&&GAqMm7gp715hemIGAP?#DmgTy7z{?p z40gksji$;KH-_F4un4fVe=Kgj{L`gg+ZIm#!AhM)N6lUXGa9wRn!O5x>4OiaxF~0p zp$@NH55*Ix0>QxRJ{`(r!{5%pxqmFi;ET7@L&Jh}M2J;tQJ9}w(+sx@l{CGS#ts_G zey)Xo*cHWNvl5A`flD3p9-DYi#Bi7cgw^2iZm4p{IS)>$D+$5SA~*pQZWMTa!mJ;o zS21b1uU~7Fj<`_wGopY)%N#uRFaH6fTb|xZA@Y~5Z4b7 z<}Dd*4IK1V;>~fGe_n0a3RE`0cZ6}VieA-yRe%US(0O)%nG`+aNGyG=jP~-vS;}G; zd-+ro%*13VVq2?bK1SNTod6?z{>K_YAOp>wxm_&EdYcVtv!!w{f&H>B%o+2B3sAs} z8KPwfFjap+Y91dSWMFZ{_K^~coaG(C;{WJebiC^q6o+nxzdG3>5#YW`W@_3ef05jf z60o^npD%gKh;p~fsvS2{q?`%owxzWyi%E{Y_oJ6H54|**G(rxuyW@jRqv4#ADGH8@ z&rWTGR>aLidOt|-eh_Xf~>2kL5nAOuCE3C8?x+Z6&i8N8vY{-3}s!2lG{h7Mnl6~a^?N|~(H zHLUdjR=Xy?6$Y!rUY?3W zokL~_pL#~un&B~+*N1#IWhf;0sKTOOX4A#X@*#8R!<>M#L}bC15#v&pbN+_zSjo9O zrkx^cKE%$t)UV>eBtR6vG9i#~WrO+=H%eIgiTy2R#ICEU9)kXRZJItLJB^o|KHZP4 zKFhA`rGgkF6*Duq7_$(R%d?4opRb+fpTt+fG|SQ*QfAoyOjg0@U23UC6pwO+2+5__ z+d^E9r?R=%X87p<);#=ZS_SJY^O7jzb@rOxh&fh=zc>sStqXsf|E|v5#@n0|E3#`{Iqd-_w5);WL+d;1QRxL-2M*h<*+%IoKWJjQ0>Ql9X7b%*aPD(Lz1 z{{{UK0`9;DN;pNpHkmwCFu|}cKEOrZfDouQ`sC)C6Cvlp`x;RaS&_StX&{urNix_Y^;yWn15hf_KvwXTGg?Ref5#CB?3l` zfX#Er1;=`4Xb52%jD-b*$A5jqB=5?!hAZtrUb9ZN$mq^l_(lX2Umt_wi_T`;MI zI0}^P611p_)((~r&st_d( z(MM!cU8z9UrWnCt0>DMHpYkf@hHY>q5b}~kk3Px8biRA3{p^=N7e}gIy}bWX^Kth_tsn|HBZom z+9!nK%CFF(A>lrZkx&}z(VB#Rb`0;~S{1Qy+t<2rqa5x^zP3FB`2}^F2_SYkkr@pQ z$qGbZ|KOrVHM^9sgs%9%{*#IrQM@2h10~||&qUHsmH(hCa)w5HM4N1ohb%DCV$CM# zECRJukqw^I32|z&K{>CjEt|%TqC~$%V0GO<poRFPvxDb|(Hogun)=1GlbY})BmE*jSAA+?m*H8+}XPE{2$SKa?vs!R- zE@wh3pGHa&-o-O7z1Yv%(M>@Bi_2AHeuqJ^f)&ANxf-TRhh!fxP#svzEfUj>i`0lP zmrP8J5hu%}GLgxUzBj|>nX(0T@q=YW@i5}X2#akp6U=;;xdse7-(DWb1HAVQ43{JH z$aYM?>#(b>#Q~43%A@pX&MYm8GLx)ZW>x_D)!d2&(M-7xU+Hy19_Vj+|>b38?88j>!UK=SKky&fW6C_iSEF#2khGyAQ2!L;%gNKHXFbNPbFfNRn zPh?2BRS=7l{eZx6{Lw*{#%lzpKzFSSszZX)PP_vd*k%)yxvm%Xg#hA`CPU(gIf6w| zdOuY;vRs+SjWPl7wS&7r&^&%PLsFMDa7QtU_rYHjC(f#fgYuhf3QNf>VgHV2^ysjv zI9l&8_INjCm+^^U5W^5CWRds1(71+p0qQ?4`+!RkxCAtm#G=MHMrsu+86y@`JNR2i z&_=|~XIvxVCI~^9L9Wbb*cxO~H6-OhC#YhiZiToEXrza@)!``eNv=AfXJsA>+ziT? zbEm`%HNw+S-D^MsXqt1QGfQ{Y#z_SwjWCj1R+Tc_M7bI1{dHwe46+#%kN-Wcwm6fD=xltx_+QKeU?=18Hhvd4Q2?` z`YC2?)m6nq2A=X7;@W{5dt$^}k49sCKABdEhuMFMaF?_tYXa(S#0ZGw|0O=mM;HX7 z^@k|RmB5FGNPU?%k&nOKh^=TGwl4GdK0Mno>UFDjN$^F1KvJ5*e_6uXYJ|&tG(_>B zY2%fR{{9g7Z!+&18cXcw_E#no5uD$s2&@g z(Ski^=!2}Yv6Pwm9L;JwV*4P@ChFl)GZpH%(~QA*3fT(P4l#eYe|JY|KZvFxQ3XPnxo@sZ}VWDFxq2-Me!qKgL4^< z3Vk`l!5bpf^Bvn`L<2-9D-dQ*%EbOdRDxW^m@8Z7%SVu2Q3Y+d=LLca9{NR0girr5 z_ae210%8n)@oIsWY9?+5)(qWQL5Tw}pv`n82Ic5j|4yAnOr2*C*U51OPHg@|HJg=!hs;j1yV3_C zHduh0u{)Xdq30L6J&){Q(g*=yt@6o+6Abr*j4Q_XUsKa(1%iEBs&a;qYaM6LpX|5g z7a!l$crmmJZ*-?|MZMyR^U!|1=&+nmn9^NV#mRbIFR-FC!aXmuGo-?e>$Rb`RxI9^3MJIqYmcaw%;b!X--9oeVrtAqWZYY-e~ylWRMh+(X$UFHKLH}U3U zM6AD0zmG?c6-i2$0_}x1q1#7wuyxJU0w)Nq~_Y+TOTQ^Uc-`{aVTmI z51&D4SIXhOJX)xoTrQ=5jI1yuqqs`pl_TumUr8Odrib01cm0{7rH++s9DQUa2M>hO&%^ z^a|=u%G|6NHfhs9J-luQAT%&v^qoW2tJR~sH?%DEV^0U~-KwP@qs5>(BR0j|5|8zL zz!uCQb|Z{>H*Q0kyaxC=K<9qI7QJKLki*9`elQs{94cJOfwRcAr?onGCtL#6oB)^P zc;vQGWA?ZSDee|oEhI9$IlD;OUuS3M6G>!Nq~iyT8Y|jreI^8}&`K&hu`z z2Wd9vQE=)n7sS9xTKP~Z^_kI+rd%WOFi39*@1%T~Y$fx~J*R*wC|%WkF53XE(T%_z zz1zRXDD`Y!<^cbc=y^;JfH6V&oxPh4T^4HEni}{9vP=CmaFBeaOVW%7*Jnj7Oi!Ta zP#YKBHAJI5MjMl*P9p`!!r)UsoH_t&v;Cx_l)5#06@a5De1CT4InTPrl}_Y;8-^4| zRZPobClANQO04o=f#@pI9;eJ`VZN!dP^$e{;Ws*q?nvFR%ZzNaP0I;~nyuI_e29s- z?Lg1#x$MOG{jxn9)Ha5b55f8}2C%8`CrZMr+U1P_f@VT28J73{yw=Jud+Z(A~-TR;V(eo@*iDB+}nsq|4 z7K?Fq(~df9!oe=>#SBJ7^a@(&6N3=8pCA8DwmcZ9#nGcJa1@^Nt@L$Z)9Js`DCVvL zhXrxOZucUQ=CRN!Qwv|z*%=;7ETziiTSGbk)s`Sa*P_Gc^*?)XILW)|*V_A%OTXtH zNt^QtR3)RX6pGUDioy+#-vu+Y^0}?FFiOL!r+>_bOZqt%Z#1eib>p*X-G=;0J%!Do zic{}y2i5%8*)+3^E@{QK4lmJXgz&{NRl8D><^S{|s2Z?}`9u)p^SAU5MN|Bqy#{Lp ztq9s%3_jaKpRo#+uuc<;ESzX1p;K zg6wjqV^(x%Acvi%ck0Nryq;_0tGW?U%=9-2>}S>ELROp0FQ?wCk~2os7gYmW zX@ZVu6k#%uZDWYjmoq`v(UOVwbfF7osU!D9YunA7xpD-Fr*JtOV^^>(*%~G`&dy{u zqJhALKMW7LnSY>PZveG9zrUy2rljtyZh#~^ljQ0v57nT^z5pq~ly~DIvIs6eCTZC0 z8cfMVn6C;9Qft53o%YwddwC5bPk|1ns14kx-yQl5WBHq8wb3~4q6;sFw+hH&KOAobkA0z^YXB^dWoG#P{lFWN!#Y$%!6@*x-+@ifE{ z5J6UH#XvT&fLWMSHYvTHW!foo@F`+6QpUY^GCirXacK{(x;O@$v!oQ<9w(`L%&Y5l zXiPk=4n}CJT*lqP)LEdeu0jCL%52v_6vhZEPs4ctkj$WnK`g?o;~7MTbQg)+GfLzz zO&d)m&tkKwW-sY#hqa^ z2FUo;TyWCt{S4UP#lC&1)?OZ?!M1*k?W>bb5f-byk6Jn!U{HAOCKKbs#RK!L3*j@{ z;^feaMnEX|Af+&STqFsMIBBXqT$bP6yNwx2gAmoxa>_{)9Lm%Z(0c$#C0M$Y_r4hC z4mY7~y~Pz<%rS*$*;8@`I`ntC`X(p#aC2goeW})7A02u)b7LN6Sg3&}GQ{WKz~c$1 za1AZynv4p(XP&vHw=yrmaSB_o;^~9LNkdQtG+2WC&4ieLKeiS|+?Q(Y1-CIU!e>j_ z8zwpVe$d}=ZR~o2JlUBK4QZJN?imR#pHoXY4|Gt_B^Ja^5N2PhwU=rv8lVK16gZ|L zpc^K;-qcztgqtkjHX<(R^KNnn_cMG}f;fU@lAt$aF3XMm5)yLF)pRUIbUbAyV&qQ! z#GF#xis$3v9X>TzAr7Zvl;T}n42H~K5p~I43I14PN-+=0NKiPOTnM7z_t;cXs(wdALX_Cjl|oeSF$W2EPkrr?T*k9*9z z&ghU|FrIQoPY*l#=XAz3r%oS?ID(UDo`HbPrlGH#t%?z!!h|+=Cj$`L(7se_7anz} zw9+7ZjbW^k=0jMR05M*kS~e*6`02B_>;dL{9?~^*TnNU5HlKN|2cD+K&r3-?VBx16 z0CD0$gnOg0NLpG9@24;aG5UQq1OfMCi?>9Xq-hoh&!&EpR$0bow|BwvGIW4|r%~!L z)XxYI=NtHzm#BS0*|o<2&pxj)CMy)KG{bR;WJ}PF*VA}NNAUZg7>EFf%MCnwK*NC; zvFj-_nRm%UIv~np%u!v5@D;kqKBR2nl?G2wU;Pob_^20*q4pU~AFH2%3$t4g$ Date: Fri, 30 Jan 2026 10:40:08 +0100 Subject: [PATCH 268/319] The introduction integration --- .../schema-aggregator-announcement.php | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/introductions/application/schema-aggregator-announcement.php diff --git a/src/introductions/application/schema-aggregator-announcement.php b/src/introductions/application/schema-aggregator-announcement.php new file mode 100644 index 00000000000..1041fcb04bb --- /dev/null +++ b/src/introductions/application/schema-aggregator-announcement.php @@ -0,0 +1,70 @@ +current_page_helper = $current_page_helper; + } + + /** + * Returns the ID. + * + * @return string The ID. + */ + public function get_id() { + return self::ID; + } + + /** + * Returns the name of the introduction. + * + * @return string The name. + */ + public function get_name() { + \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); + + return self::ID; + } + + /** + * Returns the requested pagination priority. Lower means earlier. + * + * @return int The priority. + */ + public function get_priority() { + return 20; + } + + /** + * Returns whether this introduction should show. + * + * @return bool Whether this introduction should show. + */ + public function should_show() { + return $this->current_page_helper->is_yoast_seo_page(); + } +} From affdcf17c9d390bbefef4e7f602097c9fb61de3b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 30 Jan 2026 11:18:58 +0100 Subject: [PATCH 269/319] The introduction content --- .../modals/schema-aggregator-announcement.js | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 packages/js/src/introductions/components/modals/schema-aggregator-announcement.js diff --git a/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js b/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js new file mode 100644 index 00000000000..41efcb58e54 --- /dev/null +++ b/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js @@ -0,0 +1,136 @@ +import { ArrowNarrowRightIcon } from "@heroicons/react/solid"; +import { useSelect } from "@wordpress/data"; +import { useMemo } from "@wordpress/element"; +import { __, sprintf } from "@wordpress/i18n"; +import { Button, useModalContext } from "@yoast/ui-library"; +import { safeCreateInterpolateElement } from "../../../helpers/i18n"; +import { STORE_NAME_INTRODUCTIONS } from "../../constants"; +import { Modal } from "../modal"; + + +/** + * @returns {JSX.Element} The element. + */ + +const SchemaAggregatorAnnouncementContent = ( { + thumbnail, + buttonLink, + description, +} ) => { + const { onClose, initialFocus } = useModalContext(); + + return ( + <> +

+ Thumbnail for Yoast SEO Google Docs Add-On +
+ + + Yoast SEO + +
+
+
+
+

+ { + __( "New: Prepare your site for AI powered discovery! ✨", "wordpress-seo" ) + } +

+
+

{ description }

+
+
+
+ +
+ +
+ + ); +}; + +/** + * @returns {JSX.Element} The element. + */ +export const SchemaAggregatorAnnouncement = () => { + const imageLink = useSelect( select => select( STORE_NAME_INTRODUCTIONS ).selectImageLink( "schema-aggregator-thumbnail.png" ), [] ); + const buttonLink = useSelect( select => select( STORE_NAME_INTRODUCTIONS ).selectLink( "?page=wpseo_page_settings#/site-features#card-wpseo-enable_schema_aggregation_endpoint" ), [] ); + const learnMoreLink = useSelect( select => select( STORE_NAME_INTRODUCTIONS ).selectLink( "https://yoa.st/schema-aggregation-activation/" ), [] ); + + const thumbnail = useMemo( () => ( { + src: imageLink, + width: "432", + height: "243", + } ), [ imageLink ] ); + + const LearnMoreButton = () => ; + + const description = useMemo( () => safeCreateInterpolateElement( + sprintf( + /** + * translators: %1$s expands to an opening anchor tag; %2$s expands to the arrow icon ; %3$s expands to a closing anchor tag. + */ + __( "Enable the Schema aggregation endpoint to make your Schema readable by AI systems. %1$s", "wordpress-seo" ), + "" + ), + { + LearnMoreButton: , + } + ), [] ); + + return ( + + + + ); +}; From 3e90bda00dcb914cc4ec70904ce6f00f7a58d16f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 30 Jan 2026 11:19:11 +0100 Subject: [PATCH 270/319] Initialize the introduction --- packages/js/src/introductions/initialize.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/js/src/introductions/initialize.js b/packages/js/src/introductions/initialize.js index 497e650a142..a7eb2f0a5c3 100644 --- a/packages/js/src/introductions/initialize.js +++ b/packages/js/src/introductions/initialize.js @@ -10,6 +10,7 @@ import { Introduction, IntroductionProvider } from "./components"; import { AiBrandInsightsPostLaunch } from "./components/modals/ai-brand-insights-post-launch"; import { BlackFridayAnnouncement } from "./components/modals/black-friday-announcement"; import { DelayedPremiumUpsell } from "./components/modals/delayed-premium-upsell"; +import { SchemaAggregatorAnnouncement } from "./components/modals/schema-aggregator-announcement"; import { STORE_NAME_INTRODUCTIONS } from "./constants"; import { registerStore } from "./store"; @@ -25,6 +26,7 @@ domReady( () => { "ai-brand-insights-post-launch": AiBrandInsightsPostLaunch, "black-friday-announcement": BlackFridayAnnouncement, "delayed-premium-upsell": DelayedPremiumUpsell, + "schema-aggregator-announcement": SchemaAggregatorAnnouncement, }; if ( location.href.indexOf( "page=wpseo_dashboard#/first-time-configuration" ) !== -1 ) { From 3f1d628806f2b335c575e85492058489e572d79e Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 30 Jan 2026 11:30:18 +0100 Subject: [PATCH 271/319] Remove deprecated get_name method --- .../application/ai-brand-insights-post-launch.php | 11 ----------- .../application/ai-brand-insights-pre-launch.php | 13 ------------- .../application/ai-fix-assessments-upsell.php | 11 ----------- .../application/black-friday-announcement.php | 11 ----------- .../application/delayed-premium-upsell.php | 11 ----------- .../application/google-docs-addon-upsell.php | 11 ----------- .../application/schema-aggregator-announcement.php | 11 ----------- src/introductions/domain/introduction-interface.php | 10 ---------- 8 files changed, 89 deletions(-) diff --git a/src/introductions/application/ai-brand-insights-post-launch.php b/src/introductions/application/ai-brand-insights-post-launch.php index a0b3daae4f3..ddfbe8a58bd 100644 --- a/src/introductions/application/ai-brand-insights-post-launch.php +++ b/src/introductions/application/ai-brand-insights-post-launch.php @@ -39,17 +39,6 @@ public function get_id() { return self::ID; } - /** - * Returns the name of the introduction. - * - * @return string The name. - */ - public function get_name() { - \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); - - return self::ID; - } - /** * Returns the requested pagination priority. Lower means earlier. * diff --git a/src/introductions/application/ai-brand-insights-pre-launch.php b/src/introductions/application/ai-brand-insights-pre-launch.php index 1106643da56..d24bec5c51d 100644 --- a/src/introductions/application/ai-brand-insights-pre-launch.php +++ b/src/introductions/application/ai-brand-insights-pre-launch.php @@ -43,19 +43,6 @@ public function get_id() { return self::ID; } - /** - * Returns the name of the introduction. - * - * @codeCoverageIgnore - * - * @return string The name. - */ - public function get_name() { - \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); - - return self::ID; - } - /** * Returns the requested pagination priority. Lower means earlier. * diff --git a/src/introductions/application/ai-fix-assessments-upsell.php b/src/introductions/application/ai-fix-assessments-upsell.php index 4ef10fbe507..e2609ef8e7f 100644 --- a/src/introductions/application/ai-fix-assessments-upsell.php +++ b/src/introductions/application/ai-fix-assessments-upsell.php @@ -49,17 +49,6 @@ public function get_id() { return self::ID; } - /** - * Returns the name of the introduction. - * - * @return string The name. - */ - public function get_name() { - \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); - - return self::ID; - } - /** * Returns the requested pagination priority. Lower means earlier. * diff --git a/src/introductions/application/black-friday-announcement.php b/src/introductions/application/black-friday-announcement.php index bc1dd1b76a4..f024d4d9556 100644 --- a/src/introductions/application/black-friday-announcement.php +++ b/src/introductions/application/black-friday-announcement.php @@ -61,17 +61,6 @@ public function get_id() { return self::ID; } - /** - * Returns the name of the introduction. - * - * @return string The name. - */ - public function get_name() { - \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); - - return self::ID; - } - /** * Returns the requested pagination priority. Lower means earlier. * diff --git a/src/introductions/application/delayed-premium-upsell.php b/src/introductions/application/delayed-premium-upsell.php index 21baacaf5a1..bfce0b1a474 100644 --- a/src/introductions/application/delayed-premium-upsell.php +++ b/src/introductions/application/delayed-premium-upsell.php @@ -68,17 +68,6 @@ public function get_id(): string { return self::ID; } - /** - * Returns the name of the introduction. - * - * @return string The name. - */ - public function get_name(): string { - \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); - - return self::ID; - } - /** * Returns the requested pagination priority. Lower means earlier. * diff --git a/src/introductions/application/google-docs-addon-upsell.php b/src/introductions/application/google-docs-addon-upsell.php index dc7efe6415d..49446700cc4 100644 --- a/src/introductions/application/google-docs-addon-upsell.php +++ b/src/introductions/application/google-docs-addon-upsell.php @@ -59,17 +59,6 @@ public function get_id() { return self::ID; } - /** - * Returns the name of the introduction. - * - * @return string The name. - */ - public function get_name() { - \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); - - return self::ID; - } - /** * Returns the requested pagination priority. Lower means earlier. * diff --git a/src/introductions/application/schema-aggregator-announcement.php b/src/introductions/application/schema-aggregator-announcement.php index 1041fcb04bb..d9d6cead958 100644 --- a/src/introductions/application/schema-aggregator-announcement.php +++ b/src/introductions/application/schema-aggregator-announcement.php @@ -39,17 +39,6 @@ public function get_id() { return self::ID; } - /** - * Returns the name of the introduction. - * - * @return string The name. - */ - public function get_name() { - \_deprecated_function( __METHOD__, 'Yoast SEO Premium 21.6', 'Please use get_id() instead' ); - - return self::ID; - } - /** * Returns the requested pagination priority. Lower means earlier. * diff --git a/src/introductions/domain/introduction-interface.php b/src/introductions/domain/introduction-interface.php index ed895b00068..fb0118ef241 100644 --- a/src/introductions/domain/introduction-interface.php +++ b/src/introductions/domain/introduction-interface.php @@ -14,16 +14,6 @@ interface Introduction_Interface { */ public function get_id(); - /** - * Returns the unique name. - * - * @deprecated 21.6 - * @codeCoverageIgnore - * - * @return string - */ - public function get_name(); - /** * Returns the requested pagination priority. Lower means earlier. * From d51034bba15ceb59cd879864f31851aace8f804b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Fri, 30 Jan 2026 11:45:31 +0100 Subject: [PATCH 272/319] Add unit tests --- .../Schema_Aggregator_Announcement_Test.php | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 tests/Unit/Introductions/Application/Schema_Aggregator_Announcement_Test.php diff --git a/tests/Unit/Introductions/Application/Schema_Aggregator_Announcement_Test.php b/tests/Unit/Introductions/Application/Schema_Aggregator_Announcement_Test.php new file mode 100644 index 00000000000..c5a5598d94e --- /dev/null +++ b/tests/Unit/Introductions/Application/Schema_Aggregator_Announcement_Test.php @@ -0,0 +1,121 @@ +current_page_helper = Mockery::mock( Current_Page_Helper::class ); + + $this->instance = new Schema_Aggregator_Announcement( $this->current_page_helper ); + } + + /** + * Tests if the needed attributes are set correctly. + * + * @covers ::__construct + * + * @return void + */ + public function test_constructor() { + $this->assertInstanceOf( + Current_Page_Helper::class, + $this->getPropertyValue( $this->instance, 'current_page_helper' ) + ); + } + + /** + * Tests getting the ID. + * + * @covers ::get_id + * + * @return void + */ + public function test_get_id() { + $this->assertSame( 'schema-aggregator-announcement', $this->instance->get_id() ); + } + + /** + * Tests getting the priority. + * + * @covers ::get_priority + * + * @return void + */ + public function test_get_priority() { + $this->assertSame( 20, $this->instance->get_priority() ); + } + + /** + * Tests the conditional `should_show`. + * + * @covers ::should_show + * + * @dataProvider should_show_data + * + * @param bool $is_yoast_seo_page Whether on a Yoast SEO page. + * @param bool $expected The expected result. + * + * @return void + */ + public function test_should_show( bool $is_yoast_seo_page, bool $expected ) { + $this->current_page_helper->expects( 'is_yoast_seo_page' ) + ->withNoArgs() + ->andReturn( $is_yoast_seo_page ); + + $this->assertSame( $expected, $this->instance->should_show() ); + } + + /** + * Provides the data for `test_should_show`. + * + * @return array> + */ + public static function should_show_data(): array { + return [ + 'on a Yoast admin page' => [ + 'is_yoast_seo_page' => true, + 'expected' => true, + ], + 'not on a Yoast admin page' => [ + 'is_yoast_seo_page' => false, + 'expected' => false, + ], + ]; + } +} From 4ea8b5ff003f711462e8210ac4dbf7b158f5c2db Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" <68744851+pls78@users.noreply.github.com> Date: Tue, 3 Feb 2026 12:12:34 +0100 Subject: [PATCH 273/319] Update packages/js/src/introductions/components/modals/schema-aggregator-announcement.js Co-authored-by: Thijs van der Heijden --- .../components/modals/schema-aggregator-announcement.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js b/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js index 41efcb58e54..58a6580fa5e 100644 --- a/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js +++ b/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js @@ -37,7 +37,7 @@ const SchemaAggregatorAnnouncementContent = ( {
-
+

{ __( "New: Prepare your site for AI powered discovery! ✨", "wordpress-seo" ) From f171b84027de0e6d02f8f0ee1dcdf8d32371071d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 3 Feb 2026 14:42:57 +0100 Subject: [PATCH 274/319] Fix EDD --- .../schema-pieces/edd-schema-piece-repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php index af3915f2836..07d147b3f34 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/edd-schema-piece-repository.php @@ -76,7 +76,7 @@ public function collect( int $post_id ): array { // Ensure each piece has an @id. foreach ( $schema_output as $key => $piece ) { if ( ! isset( $piece['@id'] ) ) { - $schema_output[ $key ]['@id'] = $this->meta->for_current_page()->canonical . '#/schema/edd-product/' . $post_id; + $schema_output[ $key ]['@id'] = $this->meta->for_post( $post_id )->canonical . '#/schema/edd-product/' . $post_id; } } From 1c9d3418eb8eb103486ec54f8af438b96896e645 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 3 Feb 2026 16:06:02 +0100 Subject: [PATCH 275/319] Move introduction to the schema-aggregator folder structure --- .../application/schema-aggregator-announcement.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{introductions => schema-aggregator}/application/schema-aggregator-announcement.php (100%) diff --git a/src/introductions/application/schema-aggregator-announcement.php b/src/schema-aggregator/application/schema-aggregator-announcement.php similarity index 100% rename from src/introductions/application/schema-aggregator-announcement.php rename to src/schema-aggregator/application/schema-aggregator-announcement.php From 0fe229ef2ba840b97680d3f25efebab1a143ddb5 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Tue, 3 Feb 2026 16:15:37 +0100 Subject: [PATCH 276/319] Move unit test --- .../Application/Schema_Aggregator_Announcement_Test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename tests/Unit/{Introductions => Schema_Aggregator}/Application/Schema_Aggregator_Announcement_Test.php (91%) diff --git a/tests/Unit/Introductions/Application/Schema_Aggregator_Announcement_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement_Test.php similarity index 91% rename from tests/Unit/Introductions/Application/Schema_Aggregator_Announcement_Test.php rename to tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement_Test.php index c5a5598d94e..43788eb152c 100644 --- a/tests/Unit/Introductions/Application/Schema_Aggregator_Announcement_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement_Test.php @@ -1,10 +1,10 @@ Date: Tue, 3 Feb 2026 16:15:46 +0100 Subject: [PATCH 277/319] Fix namespaces --- .../application/schema-aggregator-announcement.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/schema-aggregator/application/schema-aggregator-announcement.php b/src/schema-aggregator/application/schema-aggregator-announcement.php index d9d6cead958..cce5e579cc8 100644 --- a/src/schema-aggregator/application/schema-aggregator-announcement.php +++ b/src/schema-aggregator/application/schema-aggregator-announcement.php @@ -1,8 +1,9 @@ Date: Wed, 4 Feb 2026 13:06:26 +0100 Subject: [PATCH 278/319] Refactor default filter to be able to use a filter on multiple schema types. --- .../application/filtering/default-filter.php | 137 +++++++++++++++--- 1 file changed, 114 insertions(+), 23 deletions(-) diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index 428d9329e5e..23639d8dd21 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -2,7 +2,10 @@ // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure. namespace Yoast\WP\SEO\Schema_Aggregator\Application\Filtering; +use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\Schema_Node_Filter_Decider_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\Base_Schema_Node_Property_Filter; +use Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\Schema_Node_Property_Filter_Interface; +use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece; use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Elements_Context_Map\Elements_Context_Map_Repository_Interface; @@ -11,12 +14,17 @@ */ class Default_Filter implements Filtering_Strategy_Interface { + private const NODE_FILTER_NAMESPACE = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\\'; + private const PROPERTY_FILTER_NAMESPACE = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\\'; + private const NODE_FILTER_SUFFIX = '_Schema_Node_Filter'; + private const PROPERTY_FILTER_SUFFIX = '_Schema_Node_Property_Filter'; + /** * The categories to filter. * * @var array */ - private $filter_categories = [ + private const FILTER_CATEGORIES = [ 'action', 'enumeration', 'meta', @@ -49,31 +57,114 @@ public function __construct( Elements_Context_Map_Repository_Interface $elements public function filter( Schema_Piece_Collection $schema ): Schema_Piece_Collection { $filtered_schema = []; $elements_context_map = $this->elements_context_map_repository->get_map(); + foreach ( $schema->to_array() as $schema_piece ) { - $should_keep = true; - foreach ( $this->filter_categories as $category ) { - if ( \in_array( $schema_piece->get_type(), $elements_context_map[ $category ], true ) ) { - $filter_class_name = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\\' . $schema_piece->get_type() . '_Schema_Node_Filter'; - if ( \class_exists( $filter_class_name ) && \is_a( $filter_class_name, 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\Schema_Node_Filter_Decider_Interface', true ) ) { - $should_keep = ( new $filter_class_name() )->should_filter( $schema, $schema_piece ); - } - else { - $should_keep = false; - } - break; - } - } - if ( $should_keep ) { - $properties_filter_class_name = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\\' . $schema_piece->get_type() . '_Schema_Node_Property_Filter'; - if ( \class_exists( $properties_filter_class_name ) && \is_a( $properties_filter_class_name, 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\Schema_Node_Property_Filter_Interface', true ) ) { - $schema_piece = ( new $properties_filter_class_name() )->filter_properties( $schema_piece ); - } - else { - $schema_piece = ( new Base_Schema_Node_Property_Filter() )->filter_properties( $schema_piece ); - } - $filtered_schema[] = $schema_piece; + $piece_types = (array) $schema_piece->get_type(); + + if ( ! $this->should_keep_piece( $piece_types, $elements_context_map, $schema, $schema_piece ) ) { + continue; } + + $filtered_schema[] = $this->apply_property_filters( $schema_piece, $piece_types ); } + return new Schema_Piece_Collection( $filtered_schema ); } + + /** + * Determines if a schema piece should be kept based on all its types. + * + * @param array $types The types to check. + * @param array $elements_context_map The elements context map. + * @param Schema_Piece_Collection $schema The full schema collection. + * @param Schema_Piece $schema_piece The schema piece being checked. + * + * @return bool Whether to keep the schema piece. + */ + private function should_keep_piece( array $types, array $elements_context_map, Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { + foreach ( $types as $type ) { + if ( ! $this->should_keep_type( $type, $elements_context_map, $schema, $schema_piece ) ) { + return false; + } + } + + return true; + } + + /** + * Determines if a schema piece should be kept based on a single type. + * + * @param string $type The type to check. + * @param array $elements_context_map The elements context map. + * @param Schema_Piece_Collection $schema The full schema collection. + * @param Schema_Piece $schema_piece The schema piece being checked. + * + * @return bool Whether to keep the schema piece. + */ + private function should_keep_type( string $type, array $elements_context_map, Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { + foreach ( self::FILTER_CATEGORIES as $category ) { + if ( ! \in_array( $type, $elements_context_map[ $category ], true ) ) { + continue; + } + + $filter = $this->get_node_filter( $type ); + + return $filter !== null ? $filter->should_filter( $schema, $schema_piece ) : false; + } + + return true; + } + + /** + * Gets a node filter instance for the given type. + * + * @param string $type The schema type. + * + * @return Schema_Node_Filter_Decider_Interface|null The filter instance or null if not found. + */ + private function get_node_filter( string $type ): ?Schema_Node_Filter_Decider_Interface { + $filter_class = self::NODE_FILTER_NAMESPACE . $type . self::NODE_FILTER_SUFFIX; + + if ( \class_exists( $filter_class ) && \is_a( $filter_class, Schema_Node_Filter_Decider_Interface::class, true ) ) { + return new $filter_class(); + } + + return null; + } + + /** + * Applies property filters for all types of a schema piece. + * + * @param Schema_Piece $schema_piece The schema piece to filter. + * @param array $types The types of the schema piece. + * + * @return Schema_Piece The filtered schema piece. + */ + private function apply_property_filters( Schema_Piece $schema_piece, array $types ): Schema_Piece { + foreach ( $types as $type ) { + $filter = $this->get_property_filter( $type ); + if ( $filter !== null ) { + return $filter->filter_properties( $schema_piece ); + } + } + + return ( new Base_Schema_Node_Property_Filter() )->filter_properties( $schema_piece ); + } + + /** + * Gets a property filter instance for the given type. + * + * @param string $type The schema type. + * + * @return Schema_Node_Property_Filter_Interface|null The filter instance or null if not found. + */ + private function get_property_filter( string $type ): ?Schema_Node_Property_Filter_Interface { + $filter_class = self::PROPERTY_FILTER_NAMESPACE . $type . self::PROPERTY_FILTER_SUFFIX; + + if ( \class_exists( $filter_class ) && \is_a( $filter_class, Schema_Node_Property_Filter_Interface::class, true ) ) { + return new $filter_class(); + } + + return null; + } } From 5a706a41cea2d515656d3619e54a1047412a8617 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 4 Feb 2026 14:08:03 +0100 Subject: [PATCH 279/319] Fix case where a schema piece would be deleted when one of the types should be filtered an not both. --- .../application/filtering/default-filter.php | 51 +++-- .../Filtering/Default_Filter/Filter_Test.php | 190 +++++++++++++++++- 2 files changed, 218 insertions(+), 23 deletions(-) diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index 23639d8dd21..0ab6cee1a42 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -14,10 +14,10 @@ */ class Default_Filter implements Filtering_Strategy_Interface { - private const NODE_FILTER_NAMESPACE = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\\'; - private const PROPERTY_FILTER_NAMESPACE = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\\'; - private const NODE_FILTER_SUFFIX = '_Schema_Node_Filter'; - private const PROPERTY_FILTER_SUFFIX = '_Schema_Node_Property_Filter'; + private const NODE_FILTER_NAMESPACE = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Filter\\'; + private const PROPERTY_FILTER_NAMESPACE = 'Yoast\WP\SEO\Schema_Aggregator\Application\Filtering\Schema_Node_Property_Filter\\'; + private const NODE_FILTER_SUFFIX = '_Schema_Node_Filter'; + private const PROPERTY_FILTER_SUFFIX = '_Schema_Node_Property_Filter'; /** * The categories to filter. @@ -41,7 +41,8 @@ class Default_Filter implements Filtering_Strategy_Interface { /** * Class constructor. * - * @param Elements_Context_Map_Repository_Interface $elements_context_map_repository The elements-context map repository. + * @param Elements_Context_Map_Repository_Interface $elements_context_map_repository The elements-context map + * repository. */ public function __construct( Elements_Context_Map_Repository_Interface $elements_context_map_repository ) { $this->elements_context_map_repository = $elements_context_map_repository; @@ -74,34 +75,46 @@ public function filter( Schema_Piece_Collection $schema ): Schema_Piece_Collecti /** * Determines if a schema piece should be kept based on all its types. * - * @param array $types The types to check. - * @param array $elements_context_map The elements context map. - * @param Schema_Piece_Collection $schema The full schema collection. - * @param Schema_Piece $schema_piece The schema piece being checked. + * A piece is kept if at least one of its types should be kept. + * + * @param array $types The types to check. + * @param array> $elements_context_map The elements context map. + * @param Schema_Piece_Collection $schema The full schema collection. + * @param Schema_Piece $schema_piece The schema piece being checked. * * @return bool Whether to keep the schema piece. */ - private function should_keep_piece( array $types, array $elements_context_map, Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { + private function should_keep_piece( + array $types, + array $elements_context_map, + Schema_Piece_Collection $schema, + Schema_Piece $schema_piece + ): bool { foreach ( $types as $type ) { - if ( ! $this->should_keep_type( $type, $elements_context_map, $schema, $schema_piece ) ) { - return false; + if ( $this->should_keep_type( $type, $elements_context_map, $schema, $schema_piece ) ) { + return true; } } - return true; + return false; } /** * Determines if a schema piece should be kept based on a single type. * - * @param string $type The type to check. - * @param array $elements_context_map The elements context map. - * @param Schema_Piece_Collection $schema The full schema collection. - * @param Schema_Piece $schema_piece The schema piece being checked. + * @param string $type The type to check. + * @param array> $elements_context_map The elements context map. + * @param Schema_Piece_Collection $schema The full schema collection. + * @param Schema_Piece $schema_piece The schema piece being checked. * * @return bool Whether to keep the schema piece. */ - private function should_keep_type( string $type, array $elements_context_map, Schema_Piece_Collection $schema, Schema_Piece $schema_piece ): bool { + private function should_keep_type( + string $type, + array $elements_context_map, + Schema_Piece_Collection $schema, + Schema_Piece $schema_piece + ): bool { foreach ( self::FILTER_CATEGORIES as $category ) { if ( ! \in_array( $type, $elements_context_map[ $category ], true ) ) { continue; @@ -109,7 +122,7 @@ private function should_keep_type( string $type, array $elements_context_map, Sc $filter = $this->get_node_filter( $type ); - return $filter !== null ? $filter->should_filter( $schema, $schema_piece ) : false; + return ( $filter !== null && $filter->should_filter( $schema, $schema_piece ) ); } return true; diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php index 63b4c50b2fa..7fbdcc6c1ef 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php @@ -23,19 +23,21 @@ final class Filter_Test extends Abstract_Default_Filter_Test { * * @param array> $elements_context_map The elements context map. * @param array> $schema_pieces_data The schema pieces data. + * @param array> $schema_pieces_types The types for each schema piece. * @param array> $expected_data The expected filtered data. * @param int $expected_wp_function_calls The expected number of WordPress function calls. * * @return void */ - public function test_schema_pieces_filter( array $elements_context_map, array $schema_pieces_data, array $expected_data, int $expected_wp_function_calls ): void { + public function test_schema_pieces_filter( array $elements_context_map, array $schema_pieces_data, array $schema_pieces_types, array $expected_data, int $expected_wp_function_calls ): void { $this->elements_context_map_repository ->shouldReceive( 'get_map' ) ->andReturn( $elements_context_map ); $schema_pieces = []; - foreach ( $schema_pieces_data as $data ) { - $schema_pieces[] = new Schema_Piece( $data, $data['@type'] ); + foreach ( $schema_pieces_data as $index => $data ) { + $type = ( $schema_pieces_types[ $index ] ?? $data['@type'] ); + $schema_pieces[] = new Schema_Piece( $data, $type ); } $schema = new Schema_Piece_Collection( $schema_pieces ); @@ -174,7 +176,7 @@ public function schema_piece_properties_filter_data(): array { /** * Data provider for test_filter. * - * @return array>, array>, array>, int>> + * @return array>, array>, array>, array>, int>> */ public function filter_data(): array { return [ @@ -196,6 +198,10 @@ public function filter_data(): array { 'name' => 'Jane Smith', ], ], + [ + 'Article', + 'Person', + ], [ [ '@type' => 'Article', @@ -226,6 +232,10 @@ public function filter_data(): array { 'headline' => 'Test Article', ], ], + [ + 'ReadAction', + 'Article', + ], [ [ '@type' => 'Article', @@ -256,6 +266,10 @@ public function filter_data(): array { 'url' => 'https://example.com/page', ], ], + [ + 'Article', + 'WebPage', + ], [ [ '@type' => 'Article', @@ -297,6 +311,12 @@ public function filter_data(): array { 'name' => 'Jane Smith', ], ], + [ + 'ReadAction', + 'Article', + 'MetaTags', + 'Person', + ], [ [ '@type' => 'Article', @@ -319,6 +339,7 @@ public function filter_data(): array { ], [], [], + [], 0, ], 'Schema pieces with multiple filterable categories' => [ @@ -347,6 +368,12 @@ public function filter_data(): array { 'name' => 'EventScheduled', ], ], + [ + 'ReadAction', + 'WebSite', + 'Article', + 'EventStatusType', + ], [ [ '@type' => 'Article', @@ -355,6 +382,161 @@ public function filter_data(): array { ], 1, ], + 'Schema piece with array type - all types allowed' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => [ 'Article', 'NewsArticle' ], + 'headline' => 'Test News Article', + 'author' => 'John Doe', + ], + ], + [ + [ 'Article', 'NewsArticle' ], + ], + [ + [ + '@type' => [ 'Article', 'NewsArticle' ], + 'headline' => 'Test News Article', + 'author' => 'John Doe', + ], + ], + 0, + ], + 'Schema piece with array type - kept if one type allowed' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => [ 'Article', 'ReadAction' ], + 'headline' => 'Test Article', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + [ + [ 'Article', 'ReadAction' ], + 'Person', + ], + [ + [ + '@type' => [ 'Article', 'ReadAction' ], + 'headline' => 'Test Article', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + 0, + ], + 'Schema piece with array type - filtered if all types filtered' => [ + [ + 'action' => [ 'ReadAction', 'WriteAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => [ 'ReadAction', 'WriteAction' ], + 'target' => 'https://example.com', + ], + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + [ + [ 'ReadAction', 'WriteAction' ], + 'Person', + ], + [ + [ + '@type' => 'Person', + 'name' => 'Jane Smith', + ], + ], + 0, + ], + 'Schema piece with array type - applies first matching property filter' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => [ 'WebPage', 'AboutPage' ], + 'name' => 'About Us', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/about', + ], + ], + [ + [ 'WebPage', 'AboutPage' ], + ], + [ + [ + '@type' => [ 'WebPage', 'AboutPage' ], + 'name' => 'About Us', + 'url' => 'https://example.com/about', + ], + ], + 0, + ], + 'Schema piece with array type - mixed with single type pieces' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => [ 'Article', 'BlogPosting' ], + 'headline' => 'Blog Post', + 'author' => 'Jane Doe', + ], + [ + '@type' => 'ReadAction', + 'target' => 'https://example.com', + ], + [ + '@type' => 'Person', + 'name' => 'John Smith', + ], + ], + [ + [ 'Article', 'BlogPosting' ], + 'ReadAction', + 'Person', + ], + [ + [ + '@type' => [ 'Article', 'BlogPosting' ], + 'headline' => 'Blog Post', + 'author' => 'Jane Doe', + ], + [ + '@type' => 'Person', + 'name' => 'John Smith', + ], + ], + 0, + ], ]; } } From 72a06a88472bbe75a8e8ea9d65479d29900fd1ba Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Wed, 4 Feb 2026 14:34:48 +0100 Subject: [PATCH 280/319] More tests --- .../Filtering/Default_Filter/Filter_Test.php | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php index 7fbdcc6c1ef..e1aa042d1a9 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php @@ -537,6 +537,212 @@ public function filter_data(): array { ], 0, ], + 'Schema piece with WebPage and FAQPage array type - kept because FAQPage is allowed' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [ 'WebPage' ], + ], + [ + [ + '@type' => [ 'WebPage', 'FAQPage' ], + 'name' => 'FAQ', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/faq', + ], + ], + [ + [ 'WebPage', 'FAQPage' ], + ], + [ + [ + '@type' => [ 'WebPage', 'FAQPage' ], + 'name' => 'FAQ', + 'url' => 'https://example.com/faq', + ], + ], + 0, + ], + 'Schema piece with WebPage and ItemPage array type - kept because ItemPage is allowed' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [ 'WebPage' ], + ], + [ + [ + '@type' => [ 'WebPage', 'ItemPage' ], + 'name' => 'Product Page', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/product', + ], + ], + [ + [ 'WebPage', 'ItemPage' ], + ], + [ + [ + '@type' => [ 'WebPage', 'ItemPage' ], + 'name' => 'Product Page', + 'url' => 'https://example.com/product', + ], + ], + 0, + ], + 'Schema piece with array type - WebSite filter with existing filter class' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [ 'WebSite' ], + ], + [ + [ + '@type' => [ 'WebSite', 'Organization' ], + 'name' => 'Example Site', + 'url' => 'https://example.com', + ], + ], + [ + [ 'WebSite', 'Organization' ], + ], + [ + [ + '@type' => [ 'WebSite', 'Organization' ], + 'name' => 'Example Site', + 'url' => 'https://example.com', + ], + ], + 1, + ], + 'Schema piece with array type - property filter found in second type' => [ + [ + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + ], + [ + [ + '@type' => [ 'FAQPage', 'WebPage' ], + 'name' => 'FAQ', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/faq', + ], + ], + [ + [ 'FAQPage', 'WebPage' ], + ], + [ + [ + '@type' => [ 'FAQPage', 'WebPage' ], + 'name' => 'FAQ', + 'url' => 'https://example.com/faq', + ], + ], + 0, + ], + 'Schema piece with single type not in any filter category' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [ 'StatusType' ], + 'meta' => [ 'MetaTags' ], + 'website' => [ 'WebSite' ], + ], + [ + [ + '@type' => 'Product', + 'name' => 'Test Product', + 'price' => 99.99, + ], + ], + [ + 'Product', + ], + [ + [ + '@type' => 'Product', + 'name' => 'Test Product', + 'price' => 99.99, + ], + ], + 0, + ], + 'Schema piece with array of 3+ types - kept if at least one allowed' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [ 'WebPage' ], + ], + [ + [ + '@type' => [ 'WebPage', 'CollectionPage', 'FAQPage' ], + 'name' => 'FAQ Collection', + 'breadcrumb' => [ '@type' => 'BreadcrumbList' ], + 'url' => 'https://example.com/faq', + ], + ], + [ + [ 'WebPage', 'CollectionPage', 'FAQPage' ], + ], + [ + [ + '@type' => [ 'WebPage', 'CollectionPage', 'FAQPage' ], + 'name' => 'FAQ Collection', + 'url' => 'https://example.com/faq', + ], + ], + 0, + ], + 'Schema piece with types in different filter categories - filtered if all categories filter' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [ 'WebSite' ], + ], + [ + [ + '@type' => [ 'ReadAction', 'WebSite' ], + 'name' => 'Mixed Types', + 'url' => 'https://example.com', + ], + ], + [ + [ 'ReadAction', 'WebSite' ], + ], + [], + 1, + ], + 'Schema piece with types in different filter categories - kept if one category allows' => [ + [ + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [ 'WebSite' ], + ], + [ + [ + '@type' => [ 'ReadAction', 'Article' ], + 'name' => 'Mixed Types', + 'url' => 'https://example.com', + ], + ], + [ + [ 'ReadAction', 'Article' ], + ], + [ + [ + '@type' => [ 'ReadAction', 'Article' ], + 'name' => 'Mixed Types', + 'url' => 'https://example.com', + ], + ], + 0, + ], ]; } } From f3ffc8cbc7537a6991ae7746b2b5d28ea5cf2f4f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 4 Feb 2026 16:07:26 +0100 Subject: [PATCH 281/319] Re-instate pieces de-duplication and properties merging logic --- .../application/schema-pieces-aggregator.php | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index aa2aa8429c3..42ccb3ab687 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -17,13 +17,22 @@ class Schema_Pieces_Aggregator { */ private $filtering_strategy_factory; + /** + * The properties merger. + * + * @var Properties_Merger + */ + private $properties_merger; + /** * Class constructor * * @param Filtering_Strategy_Factory $filtering_strategy_factory The filtering strategy factory. + * @param Properties_Merger $properties_merger The properties merger. */ - public function __construct( Filtering_Strategy_Factory $filtering_strategy_factory ) { + public function __construct( Filtering_Strategy_Factory $filtering_strategy_factory, Properties_Merger $properties_merger ) { $this->filtering_strategy_factory = $filtering_strategy_factory; + $this->properties_merger = $properties_merger; } /** @@ -45,7 +54,14 @@ public function aggregate( Schema_Piece_Collection $schema_pieces ): Schema_Piec if ( \is_null( $id ) ) { continue; } - $aggregated_schema[ $id ] = $piece; + + if ( isset( $aggregated_schema[ $id ] ) ) { + $aggregated_schema[ $id ] = $this->properties_merger->merge( $aggregated_schema[ $id ], $piece ); + } + else { + // Add new piece. + $aggregated_schema[ $id ] = $piece; + } } From 58581b30fbaf979865e862e93054e403efd1217d Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 4 Feb 2026 16:07:45 +0100 Subject: [PATCH 282/319] Refactor the global state adapter to discriminate between posts and pages --- .../wordpress-global-state-adapter.php | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php b/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php index 22477e97c80..90457a1ceaa 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php @@ -30,6 +30,13 @@ class WordPress_Global_State_Adapter { */ private $previous_queried_object_id; + /** + * Previous query flags + * + * @var array + */ + private $previous_query_flags; + /** * Set WordPress global state * @@ -46,12 +53,31 @@ public function set_global_state( Indexable $indexable ): void { $this->previous_queried_object = ( $wp_query->queried_object ?? null ); $this->previous_queried_object_id = ( $wp_query->queried_object_id ?? null ); + $this->previous_query_flags = [ + 'is_single' => ( $wp_query->is_single ?? false ), + 'is_page' => ( $wp_query->is_page ?? false ), + 'is_singular' => ( $wp_query->is_singular ?? false ), + ]; + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- To setup the post we need to do this explicitly. $post = \get_post( $indexable->object_id ); $wp_query->queried_object = \get_post( $indexable->object_id ); $wp_query->queried_object_id = $indexable->object_id; - $wp_query->is_single = true; - $wp_query->is_singular = true; + + $wp_query->is_single = false; + $wp_query->is_page = false; + $wp_query->is_singular = false; + + if ( $post->post_type === 'page' ) { + $wp_query->is_page = true; + $wp_query->is_singular = true; + } + elseif ( $post->post_type === 'post' ) { + $wp_query->is_single = true; + $wp_query->is_singular = true; + + } + \setup_postdata( $post ); } @@ -74,8 +100,9 @@ public function reset_global_state(): void { if ( isset( $wp_query ) && \is_object( $wp_query ) ) { $wp_query->queried_object = $this->previous_queried_object; $wp_query->queried_object_id = $this->previous_queried_object_id; - $wp_query->is_single = false; - $wp_query->is_singular = false; + $wp_query->is_single = $this->previous_query_flags['is_single']; + $wp_query->is_page = $this->previous_query_flags['is_page']; + $wp_query->is_singular = $this->previous_query_flags['is_singular']; } } } From 9d60f3505814ca7f5b3390d0b176b9090a7e3861 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 4 Feb 2026 16:09:57 +0100 Subject: [PATCH 283/319] Adapt unit tests --- ..._State_Adapter_Reset_Global_State_Test.php | 100 ++++++++++--- ...al_State_Adapter_Set_Global_State_Test.php | 136 ++++++++++++++++-- 2 files changed, 206 insertions(+), 30 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php index fb1b6107a4b..53c922aea2f 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php @@ -35,13 +35,15 @@ public function test_reset_global_state_restores_previous_post() { 'queried_object_id' => 456, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -81,13 +83,15 @@ public function test_reset_global_state_restores_previous_queried_object() { 'queried_object_id' => 789, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -124,13 +128,15 @@ public function test_reset_global_state_restores_previous_queried_object_id() { 'queried_object_id' => 789, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -154,11 +160,11 @@ public function test_reset_global_state_restores_previous_queried_object_id() { } /** - * Tests that reset_global_state resets is_single and is_singular flags. + * Tests that reset_global_state properly restores previous query flags. * * @return void */ - public function test_reset_global_state_resets_is_single_and_is_singular() { + public function test_reset_global_state_restores_previous_query_flags() { global $post, $wp_query; $post = null; @@ -167,13 +173,15 @@ public function test_reset_global_state_resets_is_single_and_is_singular() { 'queried_object_id' => null, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class ); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -186,16 +194,71 @@ public function test_reset_global_state_resets_is_single_and_is_singular() { $this->instance->set_global_state( $indexable ); + // After setting global state for post $this->assertTrue( $wp_query->is_single ); $this->assertTrue( $wp_query->is_singular ); + $this->assertFalse( $wp_query->is_page ); Functions\expect( 'wp_reset_postdata' ) ->once(); $this->instance->reset_global_state(); + // Should be restored to original values $this->assertFalse( $wp_query->is_single ); $this->assertFalse( $wp_query->is_singular ); + $this->assertFalse( $wp_query->is_page ); + } + + /** + * Tests that reset_global_state properly restores previous query flags for pages. + * + * @return void + */ + public function test_reset_global_state_restores_previous_query_flags_for_pages() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => null, + 'is_single' => true, + 'is_singular' => false, + 'is_page' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_page = Mockery::mock( WP_Post::class )->makePartial(); + $new_page->ID = 123; + $new_page->post_type = 'page'; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_page ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_page ); + + $this->instance->set_global_state( $indexable ); + + // After setting global state for page + $this->assertFalse( $wp_query->is_single ); + $this->assertTrue( $wp_query->is_singular ); + $this->assertTrue( $wp_query->is_page ); + + Functions\expect( 'wp_reset_postdata' ) + ->once(); + + $this->instance->reset_global_state(); + + // Should be restored to original values + $this->assertTrue( $wp_query->is_single ); + $this->assertFalse( $wp_query->is_singular ); + $this->assertFalse( $wp_query->is_page ); } /** @@ -212,13 +275,15 @@ public function test_reset_global_state_with_null_previous_values() { 'queried_object_id' => null, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -262,8 +327,9 @@ public function test_reset_global_state_with_missing_wp_query() { $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -300,13 +366,15 @@ public function test_reset_global_state_calls_wp_reset_postdata() { 'queried_object_id' => null, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php index 4607d332f20..1c32a49fd79 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php @@ -21,11 +21,11 @@ final class WordPress_Global_State_Adapter_Set_Global_State_Test extends Abstract_WordPress_Global_State_Adapter_Test { /** - * Tests setting global state with a valid indexable. + * Tests setting global state with a valid post indexable. * * @return void */ - public function test_set_global_state_with_valid_indexable() { + public function test_set_global_state_with_valid_post_indexable() { global $post, $wp_query; $initial_post = Mockery::mock( WP_Post::class ); @@ -36,13 +36,15 @@ public function test_set_global_state_with_valid_indexable() { 'queried_object_id' => 999, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $mock_post = Mockery::mock( WP_Post::class ); - $mock_post->ID = 123; + $mock_post = Mockery::mock( WP_Post::class )->makePartial(); + $mock_post->ID = 123; + $mock_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -60,9 +62,67 @@ public function test_set_global_state_with_valid_indexable() { $this->assertSame( 123, $wp_query->queried_object_id ); $this->assertTrue( $wp_query->is_single ); $this->assertTrue( $wp_query->is_singular ); + $this->assertFalse( $wp_query->is_page ); $this->assertSame( $initial_post, $this->getPropertyValue( $this->instance, 'previous_post' ) ); $this->assertSame( $initial_post, $this->getPropertyValue( $this->instance, 'previous_queried_object' ) ); $this->assertSame( 999, $this->getPropertyValue( $this->instance, 'previous_queried_object_id' ) ); + + // Check that previous query flags are stored. + $previous_flags = $this->getPropertyValue( $this->instance, 'previous_query_flags' ); + $this->assertFalse( $previous_flags['is_single'] ); + $this->assertFalse( $previous_flags['is_singular'] ); + $this->assertFalse( $previous_flags['is_page'] ); + } + + /** + * Tests setting global state with a valid page indexable. + * + * @return void + */ + public function test_set_global_state_with_valid_page_indexable() { + global $post, $wp_query; + + $initial_post = Mockery::mock( WP_Post::class ); + $initial_post->ID = 999; + $post = $initial_post; + $wp_query = (object) [ + 'queried_object' => $initial_post, + 'queried_object_id' => 999, + 'is_single' => true, + 'is_singular' => true, + 'is_page' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $mock_page = Mockery::mock( WP_Post::class )->makePartial(); + $mock_page->ID = 123; + $mock_page->post_type = 'page'; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $mock_page ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $mock_page ); + + $this->instance->set_global_state( $indexable ); + + $this->assertSame( $mock_page, $post ); + $this->assertSame( $mock_page, $wp_query->queried_object ); + $this->assertSame( 123, $wp_query->queried_object_id ); + $this->assertFalse( $wp_query->is_single ); + $this->assertTrue( $wp_query->is_singular ); + $this->assertTrue( $wp_query->is_page ); + + // Check that previous query flags are stored. + $previous_flags = $this->getPropertyValue( $this->instance, 'previous_query_flags' ); + $this->assertTrue( $previous_flags['is_single'] ); + $this->assertTrue( $previous_flags['is_singular'] ); + $this->assertFalse( $previous_flags['is_page'] ); } /** @@ -82,13 +142,15 @@ public function test_set_global_state_stores_previous_post() { 'queried_object_id' => null, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -121,13 +183,15 @@ public function test_set_global_state_stores_previous_queried_object() { 'queried_object_id' => 789, 'is_single' => false, 'is_singular' => false, + 'is_page' => false, ]; $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -162,8 +226,9 @@ public function test_set_global_state_stores_previous_queried_object_id() { $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -198,8 +263,9 @@ public function test_set_global_state_with_null_previous_values() { $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -232,8 +298,9 @@ public function test_set_global_state_with_missing_wp_query_properties() { $indexable = new Indexable_Mock(); $indexable->object_id = 123; - $new_post = Mockery::mock( WP_Post::class ); - $new_post->ID = 123; + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; Functions\expect( 'get_post' ) ->twice() @@ -250,4 +317,45 @@ public function test_set_global_state_with_missing_wp_query_properties() { $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_queried_object' ) ); $this->assertNull( $this->getPropertyValue( $this->instance, 'previous_queried_object_id' ) ); } + + /** + * Tests that set_global_state stores previous query flags correctly. + * + * @return void + */ + public function test_set_global_state_stores_previous_query_flags() { + global $post, $wp_query; + + $post = null; + $wp_query = (object) [ + 'queried_object' => null, + 'queried_object_id' => null, + 'is_single' => true, + 'is_singular' => true, + 'is_page' => false, + ]; + + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + + $new_post = Mockery::mock( WP_Post::class )->makePartial(); + $new_post->ID = 123; + $new_post->post_type = 'post'; + + Functions\expect( 'get_post' ) + ->twice() + ->with( 123 ) + ->andReturn( $new_post ); + + Functions\expect( 'setup_postdata' ) + ->once() + ->with( $new_post ); + + $this->instance->set_global_state( $indexable ); + + $previous_flags = $this->getPropertyValue( $this->instance, 'previous_query_flags' ); + $this->assertTrue( $previous_flags['is_single'] ); + $this->assertTrue( $previous_flags['is_singular'] ); + $this->assertFalse( $previous_flags['is_page'] ); + } } From 546e9f83852bedcbcff246ec3bad8a9d52f99d3d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 5 Feb 2026 10:33:38 +0100 Subject: [PATCH 284/319] Loosen our filtering a bit for website specific nodes to keep the integrity of the schema web. --- .../application/filtering/default-filter.php | 2 +- .../base-schema-node-property-filter.php | 2 +- .../default-elements-context-map.php | 30 ++--- .../Filtering/Default_Filter/Filter_Test.php | 109 ++++++++++-------- .../Base_Schema_Node_Property_Filter_Test.php | 46 ++++---- ...bPage_Schema_Node_Property_Filter_Test.php | 17 ++- 6 files changed, 113 insertions(+), 93 deletions(-) diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index 428d9329e5e..ac6a6f7e57e 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -20,7 +20,7 @@ class Default_Filter implements Filtering_Strategy_Interface { 'action', 'enumeration', 'meta', - 'website', + 'website-meta', ]; /** diff --git a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php index 08f9367fe94..8f193506fef 100644 --- a/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php +++ b/src/schema-aggregator/application/filtering/schema-node-property-filter/base-schema-node-property-filter.php @@ -16,7 +16,7 @@ class Base_Schema_Node_Property_Filter implements Schema_Node_Property_Filter_In * * @var array */ - private const PROPERTIES_AVOID_LIST = [ 'potentialAction', 'isPartOf', 'mainEntityOfPage', 'primaryImageOfPage' ]; + private const PROPERTIES_AVOID_LIST = [ 'potentialAction', 'primaryImageOfPage' ]; /** * Filters any schema piece properties. diff --git a/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php b/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php index bf6d03d4039..07b13c5983a 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/default-elements-context-map.php @@ -15,7 +15,7 @@ class Default_Elements_Context_Map { * @var array > */ private static $map = [ - 'action' => [ + 'action' => [ 'Action', 'AcceptAction', 'AchieveAction', @@ -131,7 +131,7 @@ class Default_Elements_Context_Map { 'WinAction', 'WriteAction', ], - 'commerce' => [ + 'commerce' => [ 'Product', 'Car', 'Drug', @@ -176,7 +176,7 @@ class Default_Elements_Context_Map { 'CreditCard', 'PaymentService', ], - 'content' => [ + 'content' => [ 'CreativeWork', 'AmpStory', 'AnalysisNewsArticle', @@ -335,7 +335,7 @@ class Default_Elements_Context_Map { 'TouristTrip', 'TrainTrip', ], - 'data' => [ + 'data' => [ 'Intangible', 'ActionAccessSpecification', 'AlignmentObject', @@ -453,7 +453,7 @@ class Default_Elements_Context_Map { 'XPathType', 'Time', ], - 'entity' => [ + 'entity' => [ 'Thing', 'Person', 'Patient', @@ -690,7 +690,7 @@ class Default_Elements_Context_Map { 'TouristDestination', 'Taxon', ], - 'enumeration' => [ + 'enumeration' => [ 'RespiratoryTherapy', 'Enumeration', 'ActionStatusType', @@ -1251,7 +1251,7 @@ class Default_Elements_Context_Map { 'Nonprofit527', 'WarrantyScope', ], - 'event' => [ + 'event' => [ 'Event', 'BusinessEvent', 'ChildrensEvent', @@ -1277,7 +1277,7 @@ class Default_Elements_Context_Map { 'TheaterEvent', 'VisualArtsEvent', ], - 'medical' => [ + 'medical' => [ 'MedicalEntity', 'AnatomicalStructure', 'Artery', @@ -1343,15 +1343,11 @@ class Default_Elements_Context_Map { 'Substance', 'SuperficialAnatomy', ], - 'meta' => [ 'Class', 'Property' ], - 'website' => [ + 'meta' => [ 'Class', 'Property' ], + 'website' => [ 'WebSite', 'WebPage', 'WebPageElement', - 'SiteNavigationElement', - 'BreadcrumbList', - 'ItemList', - 'ListItem', 'AboutPage', 'CheckoutPage', 'CollectionPage', @@ -1362,6 +1358,12 @@ class Default_Elements_Context_Map { 'QAPage', 'RealEstateListing', 'SearchResultsPage', + ], + 'website-meta' => [ + 'SiteNavigationElement', + 'BreadcrumbList', + 'ItemList', + 'ListItem', 'WPAdBlock', 'WPFooter', 'WPHeader', diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php index 63b4c50b2fa..d4af894fd91 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php @@ -101,10 +101,11 @@ public function schema_piece_properties_filter_data(): array { return [ 'WebPage with specific property filter (removes breadcrumb and base properties)' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + 'website-meta' => [], ], [ '@type' => 'WebPage', @@ -118,18 +119,21 @@ public function schema_piece_properties_filter_data(): array { 'description' => 'Page description', ], [ - '@type' => 'WebPage', - 'name' => 'Test Page', - 'url' => 'https://example.com/page', - 'description' => 'Page description', + '@type' => 'WebPage', + 'name' => 'Test Page', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'url' => 'https://example.com/page', + 'description' => 'Page description', ], ], 'Article with base property filter only (removes base properties, no specific filter)' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + 'website-meta' => [], ], [ '@type' => 'Article', @@ -142,18 +146,21 @@ public function schema_piece_properties_filter_data(): array { 'datePublished' => '2023-01-01', ], [ - '@type' => 'Article', - 'headline' => 'Test Article', - 'author' => 'John Doe', - 'datePublished' => '2023-01-01', + '@type' => 'Article', + 'headline' => 'Test Article', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'author' => 'John Doe', + 'datePublished' => '2023-01-01', ], ], 'Person with no properties to filter (no specific or base filters needed)' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + 'website-meta' => [], ], [ '@type' => 'Person', @@ -180,10 +187,11 @@ public function filter_data(): array { return [ 'Schema pieces with no filterable categories' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + 'website-meta' => [], ], [ [ @@ -211,10 +219,11 @@ public function filter_data(): array { ], 'Schema pieces with filterable categories but no existing filters' => [ [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + 'website-meta' => [], ], [ [ @@ -236,10 +245,11 @@ public function filter_data(): array { ], 'Schema pieces with properties to be filtered' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + 'website-meta' => [], ], [ [ @@ -260,6 +270,7 @@ public function filter_data(): array { [ '@type' => 'Article', 'headline' => 'Test Article', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], 'author' => 'John Doe', ], [ @@ -272,10 +283,11 @@ public function filter_data(): array { ], 'Mixed schema pieces with both node and property filtering' => [ [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [], - 'meta' => [ 'MetaTags' ], - 'website' => [], + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [ 'MetaTags' ], + 'website' => [], + 'website-meta' => [], ], [ [ @@ -312,10 +324,11 @@ public function filter_data(): array { ], 'Empty schema collection' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website' => [], + 'website-meta' => [], ], [], [], @@ -323,10 +336,11 @@ public function filter_data(): array { ], 'Schema pieces with multiple filterable categories' => [ [ - 'action' => [ 'ReadAction', 'WriteAction' ], - 'enumeration' => [ 'EventStatusType' ], - 'meta' => [], - 'website' => [ 'WebSite' ], + 'action' => [ 'ReadAction', 'WriteAction' ], + 'enumeration' => [ 'EventStatusType' ], + 'meta' => [], + 'website' => [ 'WebSite' ], + 'website-meta' => [], ], [ [ @@ -348,12 +362,17 @@ public function filter_data(): array { ], ], [ + [ + '@type' => 'WebSite', + 'name' => 'Example Site', + 'url' => 'https://example.com', + ], [ '@type' => 'Article', 'headline' => 'Test Article', ], ], - 1, + 0, ], ]; } diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php index 0e06c45a4d3..8f58ee6f95e 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/Base_Schema_Node_Property_Filter_Test.php @@ -69,9 +69,11 @@ public function filter_properties_data(): array { 'author' => 'John Doe', ], [ - '@type' => 'Article', - 'headline' => 'An example headline', - 'author' => 'John Doe', + '@type' => 'Article', + 'headline' => 'An example headline', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'author' => 'John Doe', ], ], 'Schema piece with some properties to be removed' => [ @@ -87,6 +89,7 @@ public function filter_properties_data(): array { '@type' => 'WebPage', 'name' => 'Example Page', 'description' => 'A sample page', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], 'url' => 'https://example.com/page', ], ], @@ -121,9 +124,10 @@ public function filter_properties_data(): array { 'author' => 'Test Author', ], [ - '@type' => 'Article', - 'headline' => 'Test Article', - 'author' => 'Test Author', + '@type' => 'Article', + 'headline' => 'Test Article', + 'mainEntityOfPage' => null, + 'author' => 'Test Author', ], ], 'Schema piece with empty arrays for avoided properties' => [ @@ -136,9 +140,10 @@ public function filter_properties_data(): array { 'url' => 'https://example.com', ], [ - '@type' => 'WebSite', - 'name' => 'Example Site', - 'url' => 'https://example.com', + '@type' => 'WebSite', + 'name' => 'Example Site', + 'isPartOf' => [], + 'url' => 'https://example.com', ], ], 'Schema piece with mixed data types for avoided properties' => [ @@ -152,23 +157,12 @@ public function filter_properties_data(): array { 'mainEntityOfPage' => false, ], [ - '@type' => 'Product', - 'name' => 'Test Product', - 'price' => 99.99, - 'inStock' => true, - ], - ], - 'Schema piece with only one avoided property' => [ - [ - '@type' => 'BlogPosting', - 'headline' => 'Blog Post', - 'isPartOf' => [ '@type' => 'Blog' ], - 'datePublished' => '2023-01-01', - ], - [ - '@type' => 'BlogPosting', - 'headline' => 'Blog Post', - 'datePublished' => '2023-01-01', + '@type' => 'Product', + 'name' => 'Test Product', + 'price' => 99.99, + 'isPartOf' => 123, + 'inStock' => true, + 'mainEntityOfPage' => false, ], ], ]; diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php index e88e15ac3eb..9e8c880f022 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Property_Filter/WebPage_Schema_Node_Property_Filter_Test.php @@ -70,9 +70,12 @@ public function filter_properties_data(): array { 'url' => 'https://example.com/page', ], [ - '@type' => 'WebPage', - 'name' => 'Example Page', - 'url' => 'https://example.com/page', + '@type' => 'WebPage', + 'name' => 'Example Page', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/page' ], + 'url' => 'https://example.com/page', + ], ], 'WebPage with some base properties and breadcrumb to be removed' => [ @@ -116,9 +119,11 @@ public function filter_properties_data(): array { 'datePublished' => '2023-01-01', ], [ - '@type' => 'WebPage', - 'name' => 'Another Page', - 'datePublished' => '2023-01-01', + '@type' => 'WebPage', + 'name' => 'Another Page', + 'isPartOf' => [ '@id' => 'https://example.com/#website' ], + 'mainEntityOfPage' => [ '@id' => 'https://example.com/another' ], + 'datePublished' => '2023-01-01', ], ], 'WebPage without properties to be removed' => [ From 2efda8811157e91ccd73fabf52cc2a4fbf3a6e0f Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 5 Feb 2026 11:06:18 +0100 Subject: [PATCH 285/319] Fix cs --- .../application/schema-pieces-aggregator.php | 5 ++--- ...ordPress_Global_State_Adapter_Reset_Global_State_Test.php | 4 ---- .../WordPress_Global_State_Adapter_Set_Global_State_Test.php | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/schema-aggregator/application/schema-pieces-aggregator.php b/src/schema-aggregator/application/schema-pieces-aggregator.php index 42ccb3ab687..1306b5b6005 100644 --- a/src/schema-aggregator/application/schema-pieces-aggregator.php +++ b/src/schema-aggregator/application/schema-pieces-aggregator.php @@ -28,11 +28,11 @@ class Schema_Pieces_Aggregator { * Class constructor * * @param Filtering_Strategy_Factory $filtering_strategy_factory The filtering strategy factory. - * @param Properties_Merger $properties_merger The properties merger. + * @param Properties_Merger $properties_merger The properties merger. */ public function __construct( Filtering_Strategy_Factory $filtering_strategy_factory, Properties_Merger $properties_merger ) { $this->filtering_strategy_factory = $filtering_strategy_factory; - $this->properties_merger = $properties_merger; + $this->properties_merger = $properties_merger; } /** @@ -62,7 +62,6 @@ public function aggregate( Schema_Piece_Collection $schema_pieces ): Schema_Piec // Add new piece. $aggregated_schema[ $id ] = $piece; } - } // Return only the values to get rid of the keys (which are @id) and wrap in a collection. diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php index 53c922aea2f..63a5f4386fd 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php @@ -194,7 +194,6 @@ public function test_reset_global_state_restores_previous_query_flags() { $this->instance->set_global_state( $indexable ); - // After setting global state for post $this->assertTrue( $wp_query->is_single ); $this->assertTrue( $wp_query->is_singular ); $this->assertFalse( $wp_query->is_page ); @@ -204,7 +203,6 @@ public function test_reset_global_state_restores_previous_query_flags() { $this->instance->reset_global_state(); - // Should be restored to original values $this->assertFalse( $wp_query->is_single ); $this->assertFalse( $wp_query->is_singular ); $this->assertFalse( $wp_query->is_page ); @@ -245,7 +243,6 @@ public function test_reset_global_state_restores_previous_query_flags_for_pages( $this->instance->set_global_state( $indexable ); - // After setting global state for page $this->assertFalse( $wp_query->is_single ); $this->assertTrue( $wp_query->is_singular ); $this->assertTrue( $wp_query->is_page ); @@ -255,7 +252,6 @@ public function test_reset_global_state_restores_previous_query_flags_for_pages( $this->instance->reset_global_state(); - // Should be restored to original values $this->assertTrue( $wp_query->is_single ); $this->assertFalse( $wp_query->is_singular ); $this->assertFalse( $wp_query->is_page ); diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php index 1c32a49fd79..a89f36ea17d 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php @@ -326,7 +326,7 @@ public function test_set_global_state_with_missing_wp_query_properties() { public function test_set_global_state_stores_previous_query_flags() { global $post, $wp_query; - $post = null; + $post = null; $wp_query = (object) [ 'queried_object' => null, 'queried_object_id' => null, From 98e01e01f3d717f9eceb54d57449b8ac4e4aae30 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 5 Feb 2026 12:15:04 +0100 Subject: [PATCH 286/319] Make sure to loop through all pieces. --- .../application/filtering/default-filter.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/schema-aggregator/application/filtering/default-filter.php b/src/schema-aggregator/application/filtering/default-filter.php index 0ab6cee1a42..2460a54b91c 100644 --- a/src/schema-aggregator/application/filtering/default-filter.php +++ b/src/schema-aggregator/application/filtering/default-filter.php @@ -154,14 +154,22 @@ private function get_node_filter( string $type ): ?Schema_Node_Filter_Decider_In * @return Schema_Piece The filtered schema piece. */ private function apply_property_filters( Schema_Piece $schema_piece, array $types ): Schema_Piece { + $filtered_piece = $schema_piece; + $filter_was_found = false; + foreach ( $types as $type ) { $filter = $this->get_property_filter( $type ); if ( $filter !== null ) { - return $filter->filter_properties( $schema_piece ); + $filtered_piece = $filter->filter_properties( $filtered_piece ); + $filter_was_found = true; } } - return ( new Base_Schema_Node_Property_Filter() )->filter_properties( $schema_piece ); + if ( ! $filter_was_found ) { + return ( new Base_Schema_Node_Property_Filter() )->filter_properties( $schema_piece ); + } + + return $filtered_piece; } /** From 47eeb0c2f2b064fbf64af686f8dbdf9e6e109261 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 5 Feb 2026 13:14:12 +0100 Subject: [PATCH 287/319] Only do a different set for pages. --- .../schema-pieces/wordpress-global-state-adapter.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php b/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php index 90457a1ceaa..1074dc6dd57 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/wordpress-global-state-adapter.php @@ -66,15 +66,13 @@ public function set_global_state( Indexable $indexable ): void { $wp_query->is_single = false; $wp_query->is_page = false; - $wp_query->is_singular = false; + $wp_query->is_singular = true; - if ( $post->post_type === 'page' ) { - $wp_query->is_page = true; - $wp_query->is_singular = true; + if ( $indexable->object_sub_type === 'page' ) { + $wp_query->is_page = true; } - elseif ( $post->post_type === 'post' ) { - $wp_query->is_single = true; - $wp_query->is_singular = true; + else { + $wp_query->is_single = true; } From 5189c36c7315156c71ebc0358009c93e58e149a9 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 5 Feb 2026 13:33:30 +0100 Subject: [PATCH 288/319] Update tests --- .../Filtering/Default_Filter/Filter_Test.php | 168 ++++-------------- 1 file changed, 34 insertions(+), 134 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php index 511218b8ef6..c0894653974 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php @@ -106,7 +106,6 @@ public function schema_piece_properties_filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [], 'website-meta' => [], ], [ @@ -134,7 +133,6 @@ public function schema_piece_properties_filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [], 'website-meta' => [], ], [ @@ -161,7 +159,6 @@ public function schema_piece_properties_filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [], 'website-meta' => [], ], [ @@ -192,7 +189,6 @@ public function filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [], 'website-meta' => [], ], [ @@ -228,7 +224,6 @@ public function filter_data(): array { 'action' => [ 'ReadAction' ], 'enumeration' => [], 'meta' => [], - 'website' => [], 'website-meta' => [], ], [ @@ -258,7 +253,6 @@ public function filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [], 'website-meta' => [], ], [ @@ -300,7 +294,6 @@ public function filter_data(): array { 'action' => [ 'ReadAction' ], 'enumeration' => [], 'meta' => [ 'MetaTags' ], - 'website' => [], 'website-meta' => [], ], [ @@ -347,7 +340,6 @@ public function filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [], 'website-meta' => [], ], [], @@ -355,59 +347,13 @@ public function filter_data(): array { [], 0, ], - 'Schema pieces with multiple filterable categories' => [ + 'Schema piece with array type - all types allowed' => [ [ - 'action' => [ 'ReadAction', 'WriteAction' ], - 'enumeration' => [ 'EventStatusType' ], + 'action' => [], + 'enumeration' => [], 'meta' => [], - 'website' => [ 'WebSite' ], 'website-meta' => [], ], - [ - [ - '@type' => 'ReadAction', - 'target' => 'https://example.com', - ], - [ - '@type' => 'WebSite', - 'name' => 'Example Site', - 'url' => 'https://example.com', - ], - [ - '@type' => 'Article', - 'headline' => 'Test Article', - ], - [ - '@type' => 'EventStatusType', - 'name' => 'EventScheduled', - ], - ], - [ - 'ReadAction', - 'WebSite', - 'Article', - 'EventStatusType', - ], - [ - [ - '@type' => 'WebSite', - 'name' => 'Example Site', - 'url' => 'https://example.com', - ], - [ - '@type' => 'Article', - 'headline' => 'Test Article', - ], - ], - 0, - ], - 'Schema piece with array type - all types allowed' => [ - [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], - ], [ [ '@type' => [ 'Article', 'NewsArticle' ], @@ -429,10 +375,10 @@ public function filter_data(): array { ], 'Schema piece with array type - kept if one type allowed' => [ [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website-meta' => [], ], [ [ @@ -462,10 +408,10 @@ public function filter_data(): array { ], 'Schema piece with array type - filtered if all types filtered' => [ [ - 'action' => [ 'ReadAction', 'WriteAction' ], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [ 'ReadAction', 'WriteAction' ], + 'enumeration' => [], + 'meta' => [], + 'website-meta' => [], ], [ [ @@ -491,10 +437,10 @@ public function filter_data(): array { ], 'Schema piece with array type - applies first matching property filter' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website-meta' => [], ], [ [ @@ -518,10 +464,10 @@ public function filter_data(): array { ], 'Schema piece with array type - mixed with single type pieces' => [ [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website-meta' => [], ], [ [ @@ -561,7 +507,7 @@ public function filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [ 'WebPage' ], + 'website-meta' => [], ], [ [ @@ -588,7 +534,7 @@ public function filter_data(): array { 'action' => [], 'enumeration' => [], 'meta' => [], - 'website' => [ 'WebPage' ], + 'website-meta' => [], ], [ [ @@ -610,38 +556,12 @@ public function filter_data(): array { ], 0, ], - 'Schema piece with array type - WebSite filter with existing filter class' => [ - [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [ 'WebSite' ], - ], - [ - [ - '@type' => [ 'WebSite', 'Organization' ], - 'name' => 'Example Site', - 'url' => 'https://example.com', - ], - ], - [ - [ 'WebSite', 'Organization' ], - ], - [ - [ - '@type' => [ 'WebSite', 'Organization' ], - 'name' => 'Example Site', - 'url' => 'https://example.com', - ], - ], - 1, - ], 'Schema piece with array type - property filter found in second type' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], - 'website' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], + 'website-meta' => [], ], [ [ @@ -665,10 +585,10 @@ public function filter_data(): array { ], 'Schema piece with single type not in any filter category' => [ [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [ 'StatusType' ], - 'meta' => [ 'MetaTags' ], - 'website' => [ 'WebSite' ], + 'action' => [ 'ReadAction' ], + 'enumeration' => [ 'StatusType' ], + 'meta' => [ 'MetaTags' ], + 'website-meta' => [], ], [ [ @@ -694,7 +614,7 @@ public function filter_data(): array { 'action' => [ 'ReadAction' ], 'enumeration' => [], 'meta' => [], - 'website' => [ 'WebPage' ], + 'website-meta' => [], ], [ [ @@ -716,32 +636,12 @@ public function filter_data(): array { ], 0, ], - 'Schema piece with types in different filter categories - filtered if all categories filter' => [ - [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [], - 'meta' => [], - 'website' => [ 'WebSite' ], - ], - [ - [ - '@type' => [ 'ReadAction', 'WebSite' ], - 'name' => 'Mixed Types', - 'url' => 'https://example.com', - ], - ], - [ - [ 'ReadAction', 'WebSite' ], - ], - [], - 1, - ], 'Schema piece with types in different filter categories - kept if one category allows' => [ [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [], - 'meta' => [], - 'website' => [ 'WebSite' ], + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], + 'website-meta' => [], ], [ [ From 0433edad93160501d94d6aa98fc268350270bb92 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 5 Feb 2026 13:37:42 +0100 Subject: [PATCH 289/319] Fix cs --- .../Filtering/Default_Filter/Filter_Test.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php index c0894653974..51c60340600 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php @@ -504,9 +504,9 @@ public function filter_data(): array { ], 'Schema piece with WebPage and FAQPage array type - kept because FAQPage is allowed' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], 'website-meta' => [], ], [ @@ -531,9 +531,9 @@ public function filter_data(): array { ], 'Schema piece with WebPage and ItemPage array type - kept because ItemPage is allowed' => [ [ - 'action' => [], - 'enumeration' => [], - 'meta' => [], + 'action' => [], + 'enumeration' => [], + 'meta' => [], 'website-meta' => [], ], [ @@ -611,9 +611,9 @@ public function filter_data(): array { ], 'Schema piece with array of 3+ types - kept if at least one allowed' => [ [ - 'action' => [ 'ReadAction' ], - 'enumeration' => [], - 'meta' => [], + 'action' => [ 'ReadAction' ], + 'enumeration' => [], + 'meta' => [], 'website-meta' => [], ], [ From c4bcef41447bfa3247216f308851fa2c70ea9f9d Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 5 Feb 2026 16:05:49 +0100 Subject: [PATCH 290/319] Fix unit tests --- ..._State_Adapter_Reset_Global_State_Test.php | 40 +++++++++++-------- ...al_State_Adapter_Set_Global_State_Test.php | 40 +++++++++++-------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php index 63a5f4386fd..f9260d8f98a 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Reset_Global_State_Test.php @@ -38,8 +38,9 @@ public function test_reset_global_state_restores_previous_post() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -86,8 +87,9 @@ public function test_reset_global_state_restores_previous_queried_object() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -131,8 +133,9 @@ public function test_reset_global_state_restores_previous_queried_object_id() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -176,8 +179,9 @@ public function test_reset_global_state_restores_previous_query_flags() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class ); $new_post->ID = 123; @@ -225,8 +229,9 @@ public function test_reset_global_state_restores_previous_query_flags_for_pages( 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'page'; $new_page = Mockery::mock( WP_Post::class )->makePartial(); $new_page->ID = 123; @@ -274,8 +279,9 @@ public function test_reset_global_state_with_null_previous_values() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -320,8 +326,9 @@ public function test_reset_global_state_with_missing_wp_query() { $wp_query = (object) []; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -365,8 +372,9 @@ public function test_reset_global_state_calls_wp_reset_postdata() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php index a89f36ea17d..3e561653e88 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/WordPress_Global_State_Adapter_Set_Global_State_Test.php @@ -39,8 +39,9 @@ public function test_set_global_state_with_valid_post_indexable() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $mock_post = Mockery::mock( WP_Post::class )->makePartial(); $mock_post->ID = 123; @@ -93,8 +94,9 @@ public function test_set_global_state_with_valid_page_indexable() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'page'; $mock_page = Mockery::mock( WP_Post::class )->makePartial(); $mock_page->ID = 123; @@ -145,8 +147,9 @@ public function test_set_global_state_stores_previous_post() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -186,8 +189,9 @@ public function test_set_global_state_stores_previous_queried_object() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -223,8 +227,9 @@ public function test_set_global_state_stores_previous_queried_object_id() { 'is_singular' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -260,8 +265,9 @@ public function test_set_global_state_with_null_previous_values() { 'is_singular' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -295,8 +301,9 @@ public function test_set_global_state_with_missing_wp_query_properties() { $wp_query = new stdClass(); - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; @@ -335,8 +342,9 @@ public function test_set_global_state_stores_previous_query_flags() { 'is_page' => false, ]; - $indexable = new Indexable_Mock(); - $indexable->object_id = 123; + $indexable = new Indexable_Mock(); + $indexable->object_id = 123; + $indexable->object_sub_type = 'post'; $new_post = Mockery::mock( WP_Post::class )->makePartial(); $new_post->ID = 123; From 7e88b83c1672108de628c9e8dbf9d47fbb62a6fd Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Fri, 6 Feb 2026 15:30:41 +0100 Subject: [PATCH 291/319] Add tests --- .../schema_map/schema-map-xml-renderer.php | 4 - .../Abstract_Schema_Map_Builder_Test.php | 54 +++++ .../Schema_Map_Builder/Build_Test.php | 190 ++++++++++++++++++ .../Schema_Map_Builder/Constructor_Test.php | 30 +++ .../Get_Rest_Route_Test.php | 86 ++++++++ .../With_Repository_Test.php | 48 +++++ .../Abstract_Schema_Map_Xml_Renderer_Test.php | 44 ++++ .../Constructor_Test.php | 30 +++ .../Schema_Map_Xml_Renderer/Render_Test.php | 190 ++++++++++++++++++ 9 files changed, 672 insertions(+), 4 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Abstract_Schema_Map_Builder_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Abstract_Schema_Map_Xml_Renderer_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Render_Test.php diff --git a/src/schema-aggregator/application/schema_map/schema-map-xml-renderer.php b/src/schema-aggregator/application/schema_map/schema-map-xml-renderer.php index e2175ada2fc..609a84d232c 100644 --- a/src/schema-aggregator/application/schema_map/schema-map-xml-renderer.php +++ b/src/schema-aggregator/application/schema_map/schema-map-xml-renderer.php @@ -37,10 +37,6 @@ public function __construct( Schema_Map_Config $config ) { * @throws RuntimeException If the input structure is invalid or XML generation fails. */ public function render( array $schema_map ): string { - if ( ! isset( $schema_map ) || ! \is_array( $schema_map ) ) { - throw new RuntimeException( 'Invalid schemamap data structure: missing or invalid "schemamap" key' ); - } - $dom = new DOMDocument( '1.0', 'UTF-8' ); $url_set = $dom->createElement( 'urlset' ); diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Abstract_Schema_Map_Builder_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Abstract_Schema_Map_Builder_Test.php new file mode 100644 index 00000000000..077521982e1 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Abstract_Schema_Map_Builder_Test.php @@ -0,0 +1,54 @@ +config = Mockery::mock( Config::class ); + $this->schema_map_repository = Mockery::mock( Schema_Map_Repository_Interface::class ); + + $this->instance = new Schema_Map_Builder( $this->config ); + $this->instance->with_repository( $this->schema_map_repository ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php new file mode 100644 index 00000000000..70262099784 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php @@ -0,0 +1,190 @@ +> $indexable_counts_data The indexable counts data (post_type => count). + * @param int $per_page The per page threshold. + * @param array> $expected_map The expected schema map output. + * + * @return void + */ + public function test_build( array $indexable_counts_data, int $per_page, array $expected_map ) { + $collection = new Indexable_Count_Collection(); + foreach ( $indexable_counts_data as $data ) { + $collection->add_indexable_count( new Indexable_Count( $data['post_type'], $data['count'] ) ); + } + + foreach ( $indexable_counts_data as $data ) { + $this->config + ->expects( 'get_per_page' ) + ->with( $data['post_type'] ) + ->andReturn( $per_page ); + } + + $this->schema_map_repository + ->allows( 'get_lastmod_for_post_type' ) + ->andReturn( '2025-01-01T00:00:00Z' ); + + Functions\expect( 'rest_url' ) + ->andReturnUsing( + static function ( $route ) { + return 'https://example.com/wp-json/' . $route; + } + ); + + $result = $this->instance->build( $collection ); + + $this->assertSame( \count( $expected_map ), \count( $result ) ); + + foreach ( $expected_map as $index => $expected_entry ) { + $this->assertSame( $expected_entry['post_type'], $result[ $index ]['post_type'] ); + $this->assertSame( $expected_entry['count'], $result[ $index ]['count'] ); + $this->assertStringContainsString( $expected_entry['url_contains'], $result[ $index ]['url'] ); + $this->assertSame( '2025-01-01T00:00:00Z', $result[ $index ]['lastmod'] ); + } + } + + /** + * Tests building the schema map with an empty collection. + * + * @return void + */ + public function test_build_with_empty_collection() { + $collection = new Indexable_Count_Collection(); + + $result = $this->instance->build( $collection ); + + $this->assertSame( [], $result ); + } + + /** + * Data provider for the build test. + * + * @return Generator + */ + public static function build_data_provider() { + yield 'Single post type, single page' => [ + 'indexable_counts_data' => [ + [ + 'post_type' => 'post', + 'count' => 50, + ], + ], + 'per_page' => 100, + 'expected_map' => [ + [ + 'post_type' => 'post', + 'count' => 50, + 'url_contains' => 'get-schema/post', + ], + ], + ]; + + yield 'Single post type, multiple pages' => [ + 'indexable_counts_data' => [ + [ + 'post_type' => 'post', + 'count' => 250, + ], + ], + 'per_page' => 100, + 'expected_map' => [ + [ + 'post_type' => 'post', + 'count' => 100, + 'url_contains' => 'get-schema/post', + ], + [ + 'post_type' => 'post', + 'count' => 100, + 'url_contains' => 'get-schema/post/2', + ], + [ + 'post_type' => 'post', + 'count' => 50, + 'url_contains' => 'get-schema/post/3', + ], + ], + ]; + + yield 'Multiple post types' => [ + 'indexable_counts_data' => [ + [ + 'post_type' => 'post', + 'count' => 50, + ], + [ + 'post_type' => 'page', + 'count' => 30, + ], + ], + 'per_page' => 100, + 'expected_map' => [ + [ + 'post_type' => 'post', + 'count' => 50, + 'url_contains' => 'get-schema/post', + ], + [ + 'post_type' => 'page', + 'count' => 30, + 'url_contains' => 'get-schema/page', + ], + ], + ]; + + yield 'Last page has correct remainder count' => [ + 'indexable_counts_data' => [ + [ + 'post_type' => 'product', + 'count' => 350, + ], + ], + 'per_page' => 100, + 'expected_map' => [ + [ + 'post_type' => 'product', + 'count' => 100, + 'url_contains' => 'get-schema/product', + ], + [ + 'post_type' => 'product', + 'count' => 100, + 'url_contains' => 'get-schema/product/2', + ], + [ + 'post_type' => 'product', + 'count' => 100, + 'url_contains' => 'get-schema/product/3', + ], + [ + 'post_type' => 'product', + 'count' => 50, + 'url_contains' => 'get-schema/product/4', + ], + ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php new file mode 100644 index 00000000000..430329c76b5 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php @@ -0,0 +1,30 @@ +assertInstanceOf( + Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php new file mode 100644 index 00000000000..63b6e4df79b --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php @@ -0,0 +1,86 @@ +once() + ->with( $expected_route ) + ->andReturnUsing( + static function ( $route ) { + return 'https://example.com/wp-json/' . $route; + } + ); + + $result = $this->instance->get_rest_route( $post_type, $page ); + + $this->assertSame( 'https://example.com/wp-json/' . $expected_route, $result ); + } + + /** + * Tests get_rest_route defaults to page 1 when no page is provided. + * + * @return void + */ + public function test_get_rest_route_defaults_to_page_one() { + Functions\expect( 'rest_url' ) + ->once() + ->with( 'yoast/v1/schema-aggregator/get-schema/post' ) + ->andReturn( 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post' ); + + $result = $this->instance->get_rest_route( 'post' ); + + $this->assertSame( 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post', $result ); + } + + /** + * Data provider for the get_rest_route test. + * + * @return Generator + */ + public static function rest_route_data_provider() { + yield 'Page 1 returns route without page parameter' => [ + 'post_type' => 'post', + 'page' => 1, + 'expected_route' => 'yoast/v1/schema-aggregator/get-schema/post', + ]; + + yield 'Page 2 returns route with page parameter' => [ + 'post_type' => 'post', + 'page' => 2, + 'expected_route' => 'yoast/v1/schema-aggregator/get-schema/post/2', + ]; + + yield 'Page 5 returns route with page parameter' => [ + 'post_type' => 'product', + 'page' => 5, + 'expected_route' => 'yoast/v1/schema-aggregator/get-schema/product/5', + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php new file mode 100644 index 00000000000..967bf2cdbfe --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php @@ -0,0 +1,48 @@ +with_repository( $repository ); + + $this->assertSame( $instance, $result ); + } + + /** + * Tests that with_repository sets the schema_map_repository property. + * + * @return void + */ + public function test_with_repository_sets_property() { + $this->assertInstanceOf( + Schema_Map_Repository_Interface::class, + $this->getPropertyValue( $this->instance, 'schema_map_repository' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Abstract_Schema_Map_Xml_Renderer_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Abstract_Schema_Map_Xml_Renderer_Test.php new file mode 100644 index 00000000000..4e9ea912495 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Abstract_Schema_Map_Xml_Renderer_Test.php @@ -0,0 +1,44 @@ +config = Mockery::mock( Schema_Map_Config::class ); + + $this->instance = new Schema_Map_Xml_Renderer( $this->config ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php new file mode 100644 index 00000000000..fdf8d9818f4 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php @@ -0,0 +1,30 @@ +assertInstanceOf( + Schema_Map_Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Render_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Render_Test.php new file mode 100644 index 00000000000..6ffd1d1eada --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Render_Test.php @@ -0,0 +1,190 @@ +config + ->expects( 'get_changefreq' ) + ->once() + ->andReturn( 'daily' ); + + $this->config + ->expects( 'get_priority' ) + ->once() + ->andReturn( '0.8' ); + + $schema_map = [ + [ + 'url' => 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post', + 'lastmod' => '2025-01-01T00:00:00Z', + ], + ]; + + $result = $this->instance->render( $schema_map ); + + $dom = new DOMDocument(); + $dom->loadXML( $result ); + + $url_set = $dom->getElementsByTagName( 'urlset' ); + $this->assertSame( 1, $url_set->length ); + $this->assertSame( 'http://www.sitemaps.org/schemas/sitemap/0.9', $url_set->item( 0 )->getAttribute( 'xmlns' ) ); + + $urls = $dom->getElementsByTagName( 'url' ); + $this->assertSame( 1, $urls->length ); + $this->assertSame( 'structuredData/schema.org', $urls->item( 0 )->getAttribute( 'contentType' ) ); + + $this->assertSame( 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post', $dom->getElementsByTagName( 'loc' )->item( 0 )->textContent ); + $this->assertSame( '2025-01-01T00:00:00Z', $dom->getElementsByTagName( 'lastmod' )->item( 0 )->textContent ); + $this->assertSame( 'daily', $dom->getElementsByTagName( 'changefreq' )->item( 0 )->textContent ); + $this->assertSame( '0.8', $dom->getElementsByTagName( 'priority' )->item( 0 )->textContent ); + } + + /** + * Tests rendering a schema map with multiple entries. + * + * @return void + */ + public function test_render_multiple_entries() { + $this->config + ->expects( 'get_changefreq' ) + ->once() + ->andReturn( 'weekly' ); + + $this->config + ->expects( 'get_priority' ) + ->once() + ->andReturn( '0.5' ); + + $schema_map = [ + [ + 'url' => 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post', + 'lastmod' => '2025-01-01T00:00:00Z', + ], + [ + 'url' => 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/page', + 'lastmod' => '2025-02-01T00:00:00Z', + ], + ]; + + $result = $this->instance->render( $schema_map ); + + $dom = new DOMDocument(); + $dom->loadXML( $result ); + + $urls = $dom->getElementsByTagName( 'url' ); + $this->assertSame( 2, $urls->length ); + + $locs = $dom->getElementsByTagName( 'loc' ); + $this->assertSame( 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post', $locs->item( 0 )->textContent ); + $this->assertSame( 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/page', $locs->item( 1 )->textContent ); + } + + /** + * Tests rendering skips entries missing the url key. + * + * @return void + */ + public function test_render_skips_entry_missing_url() { + $this->config + ->expects( 'get_changefreq' ) + ->once() + ->andReturn( 'daily' ); + + $this->config + ->expects( 'get_priority' ) + ->once() + ->andReturn( '0.8' ); + + $schema_map = [ + [ + 'lastmod' => '2025-01-01T00:00:00Z', + ], + ]; + + $result = $this->instance->render( $schema_map ); + + $dom = new DOMDocument(); + $dom->loadXML( $result ); + + $urls = $dom->getElementsByTagName( 'url' ); + $this->assertSame( 0, $urls->length ); + } + + /** + * Tests rendering skips entries missing the lastmod key. + * + * @return void + */ + public function test_render_skips_entry_missing_lastmod() { + $this->config + ->expects( 'get_changefreq' ) + ->once() + ->andReturn( 'daily' ); + + $this->config + ->expects( 'get_priority' ) + ->once() + ->andReturn( '0.8' ); + + $schema_map = [ + [ + 'url' => 'https://example.com/wp-json/yoast/v1/schema-aggregator/get-schema/post', + ], + ]; + + $result = $this->instance->render( $schema_map ); + + $dom = new DOMDocument(); + $dom->loadXML( $result ); + + $urls = $dom->getElementsByTagName( 'url' ); + $this->assertSame( 0, $urls->length ); + } + + /** + * Tests rendering an empty schema map returns XML with just the urlset root. + * + * @return void + */ + public function test_render_empty_schema_map() { + $this->config + ->expects( 'get_changefreq' ) + ->once() + ->andReturn( 'daily' ); + + $this->config + ->expects( 'get_priority' ) + ->once() + ->andReturn( '0.8' ); + + $result = $this->instance->render( [] ); + + $dom = new DOMDocument(); + $dom->loadXML( $result ); + + $url_set = $dom->getElementsByTagName( 'urlset' ); + $this->assertSame( 1, $url_set->length ); + + $urls = $dom->getElementsByTagName( 'url' ); + $this->assertSame( 0, $urls->length ); + } +} From 0ee0e44caef16fc3ef4dfb6d00454be040b8536c Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 10 Feb 2026 13:16:29 +0100 Subject: [PATCH 292/319] Try to see if headers can be validated. --- ...chema_Response_Header_Integration_Test.php | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php new file mode 100644 index 00000000000..df76cc5799b --- /dev/null +++ b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php @@ -0,0 +1,158 @@ +instance = new Site_Schema_Response_Header_Integration( $schema_map_header_adapter ); + } + + /** + * Tests that serve_custom_response returns false for non-schema-aggregator routes. + * + * @return void + */ + public function test_serve_custom_response_returns_false_for_non_schema_aggregator_route() { + $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); + $response = new WP_REST_Response( [ 'test' => 'data' ] ); + + $result = $this->instance->serve_custom_response( false, $response, $request ); + + $this->assertFalse( $result ); + } + + /** + * Tests that serve_custom_response returns false for error responses. + * + * @return void + */ + public function test_serve_custom_response_returns_false_for_error_response() { + $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-xml' ); + $response = new WP_REST_Response( [ 'error' => 'Something went wrong' ], 500 ); + + $result = $this->instance->serve_custom_response( false, $response, $request ); + + $this->assertFalse( $result ); + } + + /** + * Tests if the headers are correctly set for an XML response. + * + * This test uses runInSeparateProcess to allow header() calls to work. + * + * @runInSeparateProcess + * @preserveGlobalState disabled + * + * @return void + */ + public function test_serve_custom_response_sends_xml_headers() { + $schema_map_header_adapter = new Schema_Map_Header_Adapter(); + $instance = new Site_Schema_Response_Header_Integration( $schema_map_header_adapter ); + + $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-xml' ); + $response = new WP_REST_Response( 'https://example.com/' ); + $response->set_headers( [ + 'Content-Type' => 'application/xml; charset=UTF-8', + ] ); + + + $result = $instance->serve_custom_response( false, $response, $request ); + + + $this->assertTrue( $result ); + $headers = $this->get_sent_headers(); + $this->assertContainsHeader( 'Content-Type: application/xml; charset=UTF-8', $headers ); + } + + /** + * Tests if the headers are correctly set for a JSON response. + * + * This test uses runInSeparateProcess to allow header() calls to work. + * + * @runInSeparateProcess + * @preserveGlobalState disabled + * + * @return void + */ + public function test_serve_custom_response_sends_json_headers() { + $schema_map_header_adapter = new Schema_Map_Header_Adapter(); + $instance = new Site_Schema_Response_Header_Integration( $schema_map_header_adapter ); + + $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-schema' ); + $response = new WP_REST_Response( [ + [ '@type' => 'WebPage', 'name' => 'Test Page' ], + ] ); + $response->set_headers( [ + 'Content-Type' => 'application/json; charset=UTF-8', + ] ); + + + $result = $instance->serve_custom_response( false, $response, $request ); + + $this->assertTrue( $result ); + + $headers = $this->get_sent_headers(); + $this->assertContainsHeader( 'Content-Type: application/json; charset=UTF-8', $headers ); + $this->assertContainsHeader( 'X-Accel-Buffering: no', $headers ); + } + + /** + * Gets the headers that were sent. + * + * @return array List of headers. + */ + private function get_sent_headers(): array { + if ( \function_exists( 'xdebug_get_headers' ) ) { + return \xdebug_get_headers(); + } + } + + /** + * Asserts that a header is present in the list of headers. + * + * @param string $expected_header The expected header string. + * @param array $headers The list of headers. + * + * @return void + */ + private function assertContainsHeader( string $expected_header, array $headers ): void { + $found = false; + foreach ( $headers as $header ) { + if ( \stripos( $header, $expected_header ) !== false ) { + $found = true; + break; + } + } + $this->assertTrue( $found, \sprintf( 'Expected header "%s" not found in headers: %s', $expected_header, \implode( ', ', $headers ) ) ); + } +} From 27d566545aacf494b3f409851ad8bf25ceb14f4f Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 10 Feb 2026 13:22:54 +0100 Subject: [PATCH 293/319] cs --- ...chema_Response_Header_Integration_Test.php | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php index df76cc5799b..772cd449945 100644 --- a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php +++ b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php @@ -81,13 +81,15 @@ public function test_serve_custom_response_sends_xml_headers() { $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-xml' ); $response = new WP_REST_Response( 'https://example.com/' ); - $response->set_headers( [ - 'Content-Type' => 'application/xml; charset=UTF-8', - ] ); - + $response->set_headers( + [ + 'Content-Type' => 'application/xml; charset=UTF-8', + ] + ); + \ob_start(); $result = $instance->serve_custom_response( false, $response, $request ); - + \ob_get_clean(); $this->assertTrue( $result ); $headers = $this->get_sent_headers(); @@ -109,15 +111,27 @@ public function test_serve_custom_response_sends_json_headers() { $instance = new Site_Schema_Response_Header_Integration( $schema_map_header_adapter ); $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-schema' ); - $response = new WP_REST_Response( [ - [ '@type' => 'WebPage', 'name' => 'Test Page' ], - ] ); - $response->set_headers( [ - 'Content-Type' => 'application/json; charset=UTF-8', - ] ); - - + $response = new WP_REST_Response( + [ + [ + '@type' => 'WebPage', + 'name' => 'Test Page', + ], + ] + ); + $response->set_headers( + [ + 'Content-Type' => 'application/json; charset=UTF-8', + ] + ); + + // Start multiple output buffers because the adapter calls ob_flush() internally. Otherwise the output gets spammed with random content. + \ob_start(); + \ob_start(); $result = $instance->serve_custom_response( false, $response, $request ); + // Clean up the buffers - output may have been flushed already due to flush() call. + \ob_end_clean(); + \ob_end_clean(); $this->assertTrue( $result ); @@ -132,9 +146,7 @@ public function test_serve_custom_response_sends_json_headers() { * @return array List of headers. */ private function get_sent_headers(): array { - if ( \function_exists( 'xdebug_get_headers' ) ) { - return \xdebug_get_headers(); - } + return \xdebug_get_headers(); } /** From dd862f89a49cc4f7340e6fc78d6d29f415997392 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 10 Feb 2026 13:34:48 +0100 Subject: [PATCH 294/319] cs --- .../Site_Schema_Response_Header_Integration_Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php index 772cd449945..95ee592fe31 100644 --- a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php +++ b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php @@ -89,7 +89,7 @@ public function test_serve_custom_response_sends_xml_headers() { \ob_start(); $result = $instance->serve_custom_response( false, $response, $request ); - \ob_get_clean(); + \ob_get_clean(); $this->assertTrue( $result ); $headers = $this->get_sent_headers(); From c7667f09dc6775dc65e45dff3964c27dc092a840 Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 10 Feb 2026 13:56:27 +0100 Subject: [PATCH 295/319] Add unit test and code cover ignore --- ...ite-schema-response-header-integration.php | 1 + ...chema_Response_Header_Integration_Test.php | 46 +++++ ...onse_Header_Integration_Construct_Test.php | 32 ++++ ...Header_Integration_Register_Hooks_Test.php | 31 ++++ ...chema_Response_Header_Integration_Test.php | 170 ------------------ 5 files changed, 110 insertions(+), 170 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php delete mode 100644 tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php diff --git a/src/schema-aggregator/user-interface/site-schema-response-header-integration.php b/src/schema-aggregator/user-interface/site-schema-response-header-integration.php index e37356426a8..8b5374da77b 100644 --- a/src/schema-aggregator/user-interface/site-schema-response-header-integration.php +++ b/src/schema-aggregator/user-interface/site-schema-response-header-integration.php @@ -55,6 +55,7 @@ public function register_hooks() { * @param WP_REST_Request $request Request object. * * @return bool True if we served the request, false otherwise. + * @codeCoverageIgnore ignore this since its needs to rely on headers being sent. Which does not work in integration tests. */ public function serve_custom_response( $served, $result, $request ): bool { if ( \strpos( $request->get_route(), '/yoast/v1/schema-aggregator' ) !== 0 ) { diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php new file mode 100644 index 00000000000..4ab172ee96c --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php @@ -0,0 +1,46 @@ +schema_map_header_adapter = Mockery::mock( Schema_Map_Header_Adapter::class ); + + $this->instance = new Site_Schema_Response_Header_Integration( + $this->schema_map_header_adapter + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php new file mode 100644 index 00000000000..70dc4cd3595 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php @@ -0,0 +1,32 @@ +assertInstanceOf( Site_Schema_Response_Header_Integration::class, $this->instance ); + $this->assertInstanceOf( + Schema_Map_Header_Adapter::class, + $this->getPropertyValue( $this->instance, 'schema_map_header_adapter' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php new file mode 100644 index 00000000000..8b0d34f2167 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php @@ -0,0 +1,31 @@ +instance->register_hooks(); + + $this->assertNotFalse( + Monkey\Filters\has( 'rest_pre_serve_request', [ $this->instance, 'serve_custom_response' ] ) + ); + } +} diff --git a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php b/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php deleted file mode 100644 index 95ee592fe31..00000000000 --- a/tests/WP/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration_Test.php +++ /dev/null @@ -1,170 +0,0 @@ -instance = new Site_Schema_Response_Header_Integration( $schema_map_header_adapter ); - } - - /** - * Tests that serve_custom_response returns false for non-schema-aggregator routes. - * - * @return void - */ - public function test_serve_custom_response_returns_false_for_non_schema_aggregator_route() { - $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); - $response = new WP_REST_Response( [ 'test' => 'data' ] ); - - $result = $this->instance->serve_custom_response( false, $response, $request ); - - $this->assertFalse( $result ); - } - - /** - * Tests that serve_custom_response returns false for error responses. - * - * @return void - */ - public function test_serve_custom_response_returns_false_for_error_response() { - $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-xml' ); - $response = new WP_REST_Response( [ 'error' => 'Something went wrong' ], 500 ); - - $result = $this->instance->serve_custom_response( false, $response, $request ); - - $this->assertFalse( $result ); - } - - /** - * Tests if the headers are correctly set for an XML response. - * - * This test uses runInSeparateProcess to allow header() calls to work. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * - * @return void - */ - public function test_serve_custom_response_sends_xml_headers() { - $schema_map_header_adapter = new Schema_Map_Header_Adapter(); - $instance = new Site_Schema_Response_Header_Integration( $schema_map_header_adapter ); - - $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-xml' ); - $response = new WP_REST_Response( 'https://example.com/' ); - $response->set_headers( - [ - 'Content-Type' => 'application/xml; charset=UTF-8', - ] - ); - - \ob_start(); - $result = $instance->serve_custom_response( false, $response, $request ); - \ob_get_clean(); - - $this->assertTrue( $result ); - $headers = $this->get_sent_headers(); - $this->assertContainsHeader( 'Content-Type: application/xml; charset=UTF-8', $headers ); - } - - /** - * Tests if the headers are correctly set for a JSON response. - * - * This test uses runInSeparateProcess to allow header() calls to work. - * - * @runInSeparateProcess - * @preserveGlobalState disabled - * - * @return void - */ - public function test_serve_custom_response_sends_json_headers() { - $schema_map_header_adapter = new Schema_Map_Header_Adapter(); - $instance = new Site_Schema_Response_Header_Integration( $schema_map_header_adapter ); - - $request = new WP_REST_Request( 'GET', '/yoast/v1/schema-aggregator/get-schema' ); - $response = new WP_REST_Response( - [ - [ - '@type' => 'WebPage', - 'name' => 'Test Page', - ], - ] - ); - $response->set_headers( - [ - 'Content-Type' => 'application/json; charset=UTF-8', - ] - ); - - // Start multiple output buffers because the adapter calls ob_flush() internally. Otherwise the output gets spammed with random content. - \ob_start(); - \ob_start(); - $result = $instance->serve_custom_response( false, $response, $request ); - // Clean up the buffers - output may have been flushed already due to flush() call. - \ob_end_clean(); - \ob_end_clean(); - - $this->assertTrue( $result ); - - $headers = $this->get_sent_headers(); - $this->assertContainsHeader( 'Content-Type: application/json; charset=UTF-8', $headers ); - $this->assertContainsHeader( 'X-Accel-Buffering: no', $headers ); - } - - /** - * Gets the headers that were sent. - * - * @return array List of headers. - */ - private function get_sent_headers(): array { - return \xdebug_get_headers(); - } - - /** - * Asserts that a header is present in the list of headers. - * - * @param string $expected_header The expected header string. - * @param array $headers The list of headers. - * - * @return void - */ - private function assertContainsHeader( string $expected_header, array $headers ): void { - $found = false; - foreach ( $headers as $header ) { - if ( \stripos( $header, $expected_header ) !== false ) { - $found = true; - break; - } - } - $this->assertTrue( $found, \sprintf( 'Expected header "%s" not found in headers: %s', $expected_header, \implode( ', ', $headers ) ) ); - } -} From df0ac0982e7f020fa931760f6da157b035c2f3d5 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 11 Feb 2026 14:26:56 +0100 Subject: [PATCH 296/319] Add WooCommerce and EDD as dev dependencies We also want them installed in the vendor folder --- composer.json | 6 +++++- composer.lock | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index af91404aa37..0a0994414d8 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,9 @@ "psr/log": "^1.0", "symfony/config": "^5.4.46", "symfony/dependency-injection": "^5.4.48", + "wpackagist-plugin/easy-digital-downloads": "dev-trunk", "wpackagist-plugin/google-site-kit": "dev-trunk", + "wpackagist-plugin/woocommerce": "dev-trunk", "yoast/wp-test-utils": "^1.2", "yoast/yoastcs": "^3.2.0" }, @@ -86,7 +88,9 @@ "extra": { "installer-paths": { "vendor/{$name}": [ - "wpackagist-plugin/google-site-kit" + "wpackagist-plugin/easy-digital-downloads", + "wpackagist-plugin/google-site-kit", + "wpackagist-plugin/woocommerce" ] } }, diff --git a/composer.lock b/composer.lock index 59ccd194209..2f5599b3ca1 100644 --- a/composer.lock +++ b/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": "f5e005b8bffa35368fcae0b8114b69c4", + "content-hash": "9a54667eb432cd5eb3bd9e7d7760d0c5", "packages": [ { "name": "composer/installers", @@ -5014,6 +5014,25 @@ ], "time": "2024-03-25T16:39:00+00:00" }, + { + "name": "wpackagist-plugin/easy-digital-downloads", + "version": "dev-trunk", + "source": { + "type": "svn", + "url": "https://plugins.svn.wordpress.org/easy-digital-downloads/", + "reference": "trunk" + }, + "dist": { + "type": "zip", + "url": "https://downloads.wordpress.org/plugin/easy-digital-downloads.zip?timestamp=1770453369" + }, + "require": { + "composer/installers": "^1.0 || ^2.0" + }, + "type": "wordpress-plugin", + "homepage": "https://wordpress.org/plugins/easy-digital-downloads/", + "time": "2026-02-07T08:36:09+00:00" + }, { "name": "wpackagist-plugin/google-site-kit", "version": "dev-trunk", @@ -5033,6 +5052,25 @@ "homepage": "https://wordpress.org/plugins/google-site-kit/", "time": "2025-02-25T15:00:59+00:00" }, + { + "name": "wpackagist-plugin/woocommerce", + "version": "dev-trunk", + "source": { + "type": "svn", + "url": "https://plugins.svn.wordpress.org/woocommerce/", + "reference": "trunk" + }, + "dist": { + "type": "zip", + "url": "https://downloads.wordpress.org/plugin/woocommerce.zip?timestamp=1770770357" + }, + "require": { + "composer/installers": "^1.0 || ^2.0" + }, + "type": "wordpress-plugin", + "homepage": "https://wordpress.org/plugins/woocommerce/", + "time": "2026-02-11T00:39:17+00:00" + }, { "name": "yoast/phpunit-polyfills", "version": "1.1.5", @@ -5231,7 +5269,9 @@ "aliases": [], "minimum-stability": "dev", "stability-flags": { - "wpackagist-plugin/google-site-kit": 20 + "wpackagist-plugin/easy-digital-downloads": 20, + "wpackagist-plugin/google-site-kit": 20, + "wpackagist-plugin/woocommerce": 20 }, "prefer-stable": true, "prefer-lowest": false, @@ -5243,5 +5283,5 @@ "platform-overrides": { "php": "7.4" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } From 7ba7cd6246625ced65bcdc462d068dba224f7ae8 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 11 Feb 2026 14:36:59 +0100 Subject: [PATCH 297/319] Fix a bug where pages was never retrieved when indexables were not available --- .../indexable-repository/wordpress-query-repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php index 729bad15aa2..87ee30fedfb 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php @@ -67,7 +67,7 @@ public function get( int $page, int $page_size, string $post_type ): array { $post_ids = isset( $query->posts ) && \is_array( $query->posts ) ? $query->posts : []; $public_indexables = []; foreach ( $post_ids as $post_id ) { - $indexable = $this->indexable_repository->find_by_id_and_type( $post_id, $post_type ); + $indexable = $this->indexable_repository->find_by_id_and_type( $post_id, 'post' ); if ( $indexable !== null && ( $indexable->is_public === true || $indexable->is_public === null ) ) { $public_indexables[] = $indexable; } From 38c8b733764163a0b47806642b4ced6ec82eda16 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 11 Feb 2026 14:37:08 +0100 Subject: [PATCH 298/319] Add tests --- .../Collect_Test.php | 144 +++++++ .../Schema_Piece_Repository/Get_Test.php | 366 ++++++++++++++++++ .../Collect_Test.php | 143 +++++++ 3 files changed, 653 insertions(+) create mode 100644 tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php create mode 100644 tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php create mode 100644 tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php new file mode 100644 index 00000000000..af58d917831 --- /dev/null +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php @@ -0,0 +1,144 @@ + + */ + private $created_posts = []; + + /** + * Plugin basename of the plugin dependency this group of tests has. + * + * @var string + */ + public $prereq_plugin_basename = 'easy-digital-downloads/easy-digital-downloads.php'; + + /** + * Sets up the test class. + * + * @return void + */ + public function set_up(): void { + parent::set_up(); + + // This initializes the singleton which loads all required EDD files. + \EDD(); + + /** + * Because EDD hooks on 'init' to register its custom post types, and 'init' has already fired by the time we get here, + * we need to manually register the 'download' post type for our tests by calling edd_setup_edd_post_types. + */ + // Register the download post type (EDD hooks this on 'init' which has already fired). + if ( ! \post_type_exists( 'download' ) ) { + \edd_setup_edd_post_types(); + } + + $meta_surface = \YoastSEO()->classes->get( Meta_Surface::class ); + $this->instance = new Edd_Schema_Piece_Repository( new EDD_Conditional(), $meta_surface ); + } + + /** + * Tears down the test class. + * + * @return void + */ + public function tear_down(): void { + /** + * EDD hooks into the 'delete_post' action to perform cleanup of its custom database tables when a 'download' post is deleted. + * The test environment does not have the EDD custom tables, so these hooks will cause errors when attempting to delete the test posts. + */ + \remove_all_actions( 'delete_post' ); + + foreach ( $this->created_posts as $post_id ) { + \wp_delete_post( $post_id, true ); + } + + parent::tear_down(); + } + + /** + * Tests the collect method returns product schema for a valid EDD download. + * + * @return void + */ + public function test_collect_returns_product_schema(): void { + $post_id = self::factory()->post->create( + [ + 'post_title' => 'Test Download', + 'post_status' => 'publish', + 'post_type' => 'download', + 'post_excerpt' => 'A test digital download.', + ] + ); + $this->created_posts[] = $post_id; + + \update_post_meta( $post_id, 'edd_price', '9.99' ); + + $result = $this->instance->collect( $post_id ); + + $this->assertIsArray( $result ); + $this->assertNotEmpty( $result, 'Expected at least one schema piece for a valid download.' ); + $this->assertCount( 1, $result, 'Expected exactly one schema piece for a simple download.' ); + + $schema = $result[0]; + $this->assertIsArray( $schema ); + $this->assertArrayHasKey( '@type', $schema, 'Schema piece should have a @type key.' ); + $this->assertSame( 'Product', $schema['@type'], 'Schema @type should be Product.' ); + $this->assertArrayHasKey( '@id', $schema, 'Schema piece should have an @id key.' ); + } + + /** + * Tests the collect method returns an empty array for a non-download post. + * + * @return void + */ + public function test_collect_returns_empty_for_non_download_post(): void { + $post_id = self::factory()->post->create( + [ + 'post_title' => 'Regular Post', + 'post_status' => 'publish', + 'post_type' => 'post', + ] + ); + $this->created_posts[] = $post_id; + + $result = $this->instance->collect( $post_id ); + + $this->assertIsArray( $result ); + $this->assertEmpty( $result, 'Expected empty array for a non-download post.' ); + } + + /** + * Tests the collect method returns an empty array for a non-existent post ID. + * + * @return void + */ + public function test_collect_returns_empty_for_non_existent_post(): void { + $result = $this->instance->collect( 999999 ); + + $this->assertIsArray( $result ); + $this->assertEmpty( $result, 'Expected empty array for a non-existent post ID.' ); + } +} diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php new file mode 100644 index 00000000000..5280b4fa2fd --- /dev/null +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php @@ -0,0 +1,366 @@ + + */ + private $created_posts = []; + + /** + * Sets up the test class. + * + * @return void + */ + public function set_up(): void { + parent::set_up(); + + $meta_tags_context_memoizer = \YoastSEO()->classes->get( Meta_Tags_Context_Memoizer::class ); + $indexable_helper = \YoastSEO()->classes->get( Indexable_Helper::class ); + $post_type_helper = \YoastSEO()->classes->get( Post_Type_Helper::class ); + $pure_indexable_repository = \YoastSEO()->classes->get( Pure_Indexable_Repository::class ); + + // Ensure the post watcher is active so indexables are created automatically. + \YoastSEO()->classes->get( Indexable_Post_Watcher::class ); + + $adapter = new Meta_Tags_Context_Memoizer_Adapter(); + $config = new Aggregator_Config( new WooCommerce_Conditional(), $post_type_helper ); + + $article_schema_enhancer = new Article_Schema_Enhancer(); + $article_config = new Article_Config(); + $article_schema_enhancer->set_article_config( $article_config ); + + $person_schema_enhancer = new Person_Schema_Enhancer(); + $person_config = new Person_Config(); + $person_schema_enhancer->set_person_config( $person_config ); + + $enhancement_factory = new Schema_Enhancement_Factory( $article_schema_enhancer, $person_schema_enhancer ); + $indexable_repository = new Indexable_Repository( $pure_indexable_repository ); + $wordpress_query_repository = new WordPress_Query_Repository( \YoastSEO()->classes->get( Indexable_Builder::class ), $pure_indexable_repository ); + $indexable_repository_factory = new Indexable_Repository_Factory( $indexable_repository, $wordpress_query_repository ); + $wordpress_global_state_adapter = new WordPress_Global_State_Adapter(); + $edd_schema_piece_repository = new Edd_Schema_Piece_Repository( new EDD_Conditional(), \YoastSEO()->classes->get( Meta_Surface::class ) ); + $woo_schema_piece_repository = new Woo_Schema_Piece_Repository( new WooCommerce_Conditional() ); + + $this->instance = new Schema_Piece_Repository( + $meta_tags_context_memoizer, + $indexable_helper, + $adapter, + $config, + $enhancement_factory, + $indexable_repository_factory, + $wordpress_global_state_adapter, + $edd_schema_piece_repository, + $woo_schema_piece_repository + ); + + // Delete all indexables before each test to ensure a clean slate. + global $wpdb; + $table = Model::get_table_name( 'Indexable' ); + $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + + $this->create_test_content(); + } + + /** + * Tears down the test class. + * + * @return void + */ + public function tear_down(): void { + foreach ( $this->created_posts as $post_id ) { + \wp_delete_post( $post_id, true ); + } + + parent::tear_down(); + } + + /** + * Tests the get method returns schema pieces for existing content. + * + * @dataProvider get_with_results_data + * + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. + * @param int $min_expected_pieces The minimum expected number of schema pieces. + * @param bool $enabled_indexables Whether indexables are enabled. + * + * @return void + */ + public function test_get_with_results( + int $page, + int $page_size, + string $post_type, + int $min_expected_pieces, + bool $enabled_indexables + ): void { + if ( ! $enabled_indexables ) { + \add_filter( 'Yoast\WP\SEO\should_index_indexables', '__return_false' ); + } + + $result = $this->instance->get( $page, $page_size, $post_type ); + + $this->assertInstanceOf( Schema_Piece_Collection::class, $result ); + + $pieces = $result->to_array(); + + $this->assertNotEmpty( $pieces, 'Expected schema pieces in the collection.' ); + $this->assertGreaterThanOrEqual( + $min_expected_pieces, + \count( $pieces ), + "Should return at least {$min_expected_pieces} schema pieces." + ); + + foreach ( $pieces as $piece ) { + $this->assertInstanceOf( Schema_Piece::class, $piece, 'Each item should be a Schema_Piece instance.' ); + $this->assertNotEmpty( $piece->get_type(), 'Schema piece should have a type.' ); + $this->assertNotEmpty( $piece->get_data(), 'Schema piece should have data.' ); + } + } + + /** + * Tests the get method returns an empty collection when no matching content exists. + * + * @dataProvider get_empty_response_data + * + * @param int $page The page number. + * @param int $page_size The number of items per page. + * @param string $post_type The post type to filter by. + * @param bool $enabled_indexables Whether indexables are enabled. + * + * @return void + */ + public function test_get_empty_response( + int $page, + int $page_size, + string $post_type, + bool $enabled_indexables + ): void { + if ( ! $enabled_indexables ) { + \add_filter( 'Yoast\WP\SEO\should_index_indexables', '__return_false' ); + } + + $result = $this->instance->get( $page, $page_size, $post_type ); + + $this->assertInstanceOf( Schema_Piece_Collection::class, $result ); + $this->assertEmpty( $result->to_array(), 'Expected an empty collection.' ); + } + + /** + * Tests that different pages return different schema pieces. + * + * @dataProvider enabled_indexables_data + * + * @param bool $enabled_indexables Whether indexables are enabled. + * + * @return void + */ + public function test_get_pagination_returns_different_schema_pieces( bool $enabled_indexables ): void { + if ( ! $enabled_indexables ) { + \add_filter( 'Yoast\WP\SEO\should_index_indexables', '__return_false' ); + } + + $page_1_pieces = $this->instance->get( 1, 1, 'post' )->to_array(); + $page_2_pieces = $this->instance->get( 2, 1, 'post' )->to_array(); + + $this->assertNotEmpty( $page_1_pieces, 'First page should return schema pieces.' ); + $this->assertNotEmpty( $page_2_pieces, 'Second page should return schema pieces.' ); + + $page_1_data = \array_map( + static function ( Schema_Piece $piece ) { + return $piece->get_data(); + }, + $page_1_pieces + ); + $page_2_data = \array_map( + static function ( Schema_Piece $piece ) { + return $piece->get_data(); + }, + $page_2_pieces + ); + + $this->assertNotEquals( $page_1_data, $page_2_data, 'Different pages should return different schema pieces.' ); + } + + /** + * Data provider for test_get_with_results. + * + * @return Generator Test data to use. + */ + public static function get_with_results_data(): Generator { + yield 'First page of posts' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'post', + 'min_expected_pieces' => 3, + 'enabled_indexables' => true, + ]; + + yield 'First page of posts with disabled indexables' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'post', + 'min_expected_pieces' => 3, + 'enabled_indexables' => false, + ]; + + yield 'First page of pages' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'page', + 'min_expected_pieces' => 2, + 'enabled_indexables' => true, + ]; + + yield 'First page of pages with disabled indexables' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'page', + 'min_expected_pieces' => 2, + 'enabled_indexables' => false, + ]; + + yield 'Small page size limits indexables processed' => [ + 'page' => 1, + 'page_size' => 1, + 'post_type' => 'post', + 'min_expected_pieces' => 1, + 'enabled_indexables' => true, + ]; + + yield 'Small page size limits indexables processed with disabled indexables' => [ + 'page' => 1, + 'page_size' => 1, + 'post_type' => 'post', + 'min_expected_pieces' => 1, + 'enabled_indexables' => false, + ]; + } + + /** + * Data provider for test_get_empty_response. + * + * @return Generator Test data to use. + */ + public static function get_empty_response_data(): Generator { + yield 'High page number returns empty collection' => [ + 'page' => 100, + 'page_size' => 10, + 'post_type' => 'post', + 'enabled_indexables' => true, + ]; + + yield 'High page number returns empty collection with disabled indexables' => [ + 'page' => 100, + 'page_size' => 10, + 'post_type' => 'post', + 'enabled_indexables' => false, + ]; + + yield 'Non-existent post type returns empty collection' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'non_existent_type', + 'enabled_indexables' => true, + ]; + + yield 'Non-existent post type returns empty collection with disabled indexables' => [ + 'page' => 1, + 'page_size' => 10, + 'post_type' => 'non_existent_type', + 'enabled_indexables' => false, + ]; + } + + /** + * Data provider for tests that only need the indexables enabled/disabled flag. + * + * @return Generator Test data to use. + */ + public static function enabled_indexables_data(): Generator { + yield 'Indexables enabled' => [ + 'enabled_indexables' => true, + ]; + + yield 'Indexables disabled' => [ + 'enabled_indexables' => false, + ]; + } + + /** + * Creates test content. + * + * @return void + */ + private function create_test_content(): void { + $post_ids = self::factory()->post->create_many( + 3, + [ + 'post_title' => 'Test Post', + 'post_status' => 'publish', + 'post_type' => 'post', + 'post_content' => 'Test post content for schema aggregation.', + ] + ); + $this->created_posts = \array_merge( $this->created_posts, $post_ids ); + + $page_ids = self::factory()->post->create_many( + 2, + [ + 'post_title' => 'Test Page', + 'post_status' => 'publish', + 'post_type' => 'page', + 'post_content' => 'Test page content for schema aggregation.', + ] + ); + $this->created_posts = \array_merge( $this->created_posts, $page_ids ); + } +} diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php new file mode 100644 index 00000000000..2a26f85cb56 --- /dev/null +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php @@ -0,0 +1,143 @@ + + */ + private $created_posts = []; + + /** + * Plugin basename of the plugin dependency this group of tests has. + * + * @var string + */ + public $prereq_plugin_basename = 'woocommerce/woocommerce.php'; + + /** + * Sets up the test class. + * + * @return void + */ + public function set_up(): void { + parent::set_up(); + + /** + * Bootstrap WooCommerce: create DB tables, set up product factory, and fire required actions. + * We can't use WC()->init() here because it requires the DI container which is not available in the test environment. + * We then need to call the required actions that are normally triggered during WC()->init() manually. + */ + WC_Install::create_tables(); + \WC()->product_factory = new WC_Product_Factory(); + \do_action( 'woocommerce_after_register_taxonomy' ); + \do_action( 'woocommerce_after_register_post_type' ); + \do_action( 'woocommerce_init' ); + + /** + * The wpseo_schema_product filter that is triggered by woocommerce_structured_data_product is defined in Yoast WooCommerce SEO. + * To avoid requiring the entire plugin, we can directly hook into woocommerce_structured_data_product here to capture the schema output. + */ + \add_filter( + 'woocommerce_structured_data_product', + static function ( $markup ) { + return \apply_filters( 'wpseo_schema_product', $markup ); + } + ); + + $this->instance = new Woo_Schema_Piece_Repository( new WooCommerce_Conditional() ); + } + + /** + * Tears down the test class. + * + * @return void + */ + public function tear_down(): void { + foreach ( $this->created_posts as $post_id ) { + \wp_delete_post( $post_id, true ); + } + + parent::tear_down(); + } + + /** + * Tests the collect method returns product schema for a valid WooCommerce product. + * + * @return void + */ + public function test_collect_returns_product_schema(): void { + $product = new WC_Product_Simple(); + $product->set_name( 'Test Product' ); + $product->set_regular_price( '19.99' ); + $product->set_status( 'publish' ); + $product->save(); + + $this->created_posts[] = $product->get_id(); + + $result = $this->instance->collect( $product->get_id() ); + + $this->assertIsArray( $result ); + $this->assertNotEmpty( $result, 'Expected at least one schema piece for a valid product.' ); + $this->assertCount( 1, $result, 'Expected exactly one schema piece for a simple product.' ); + + $schema = $result[0]; + $this->assertIsArray( $schema ); + $this->assertArrayHasKey( '@type', $schema, 'Schema piece should have a @type key.' ); + } + + /** + * Tests the collect method returns an empty array for a non-product post. + * + * @return void + */ + public function test_collect_returns_empty_for_non_product_post(): void { + $post_id = self::factory()->post->create( + [ + 'post_title' => 'Regular Post', + 'post_status' => 'publish', + 'post_type' => 'post', + ] + ); + $this->created_posts[] = $post_id; + + $result = $this->instance->collect( $post_id ); + + $this->assertIsArray( $result ); + $this->assertEmpty( $result, 'Expected empty array for a non-product post.' ); + } + + /** + * Tests the collect method returns an empty array for a non-existent post ID. + * + * @return void + */ + public function test_collect_returns_empty_for_non_existent_post(): void { + $result = $this->instance->collect( 999999 ); + + $this->assertIsArray( $result ); + $this->assertEmpty( $result, 'Expected empty array for a non-existent post ID.' ); + } +} From edbfc01b0e36c01616ed313fed0958e886bea02b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 11 Feb 2026 16:47:00 +0100 Subject: [PATCH 299/319] Move cleaning up in the tear_down method --- .../Schema_Pieces/Schema_Piece_Repository/Get_Test.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php index 5280b4fa2fd..392219ec195 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php @@ -101,11 +101,6 @@ public function set_up(): void { $woo_schema_piece_repository ); - // Delete all indexables before each test to ensure a clean slate. - global $wpdb; - $table = Model::get_table_name( 'Indexable' ); - $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. - $this->create_test_content(); } @@ -119,6 +114,11 @@ public function tear_down(): void { \wp_delete_post( $post_id, true ); } + // Delete all indexables to ensure a clean slate for the next test. + global $wpdb; + $table = Model::get_table_name( 'Indexable' ); + $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + parent::tear_down(); } From a5c929102cdf1d3b519579a67b273755375b1f97 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 11 Feb 2026 16:47:13 +0100 Subject: [PATCH 300/319] Add WooCommerce-specific tear-down --- .../Woo_Schema_Piece_Repository/Collect_Test.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php index 2a26f85cb56..5b34fb4a12c 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php @@ -76,10 +76,14 @@ static function ( $markup ) { * @return void */ public function tear_down(): void { + global $wpdb; + foreach ( $this->created_posts as $post_id ) { \wp_delete_post( $post_id, true ); } + $wpdb->query( "DELETE FROM {$wpdb->prefix}wc_product_meta_lookup" ); + parent::tear_down(); } From 7eb13ee081ed8c28199f2cfeec57b931dc3b3f41 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Wed, 11 Feb 2026 17:02:28 +0100 Subject: [PATCH 301/319] Revert "Move cleaning up in the tear_down method" This reverts commit edbfc01b0e36c01616ed313fed0958e886bea02b. --- .../Schema_Pieces/Schema_Piece_Repository/Get_Test.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php index 392219ec195..5280b4fa2fd 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php @@ -101,6 +101,11 @@ public function set_up(): void { $woo_schema_piece_repository ); + // Delete all indexables before each test to ensure a clean slate. + global $wpdb; + $table = Model::get_table_name( 'Indexable' ); + $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + $this->create_test_content(); } @@ -114,11 +119,6 @@ public function tear_down(): void { \wp_delete_post( $post_id, true ); } - // Delete all indexables to ensure a clean slate for the next test. - global $wpdb; - $table = Model::get_table_name( 'Indexable' ); - $wpdb->query( "DELETE FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. - parent::tear_down(); } From 662a504989345e8d464bbf6665a2d52b75dba7bc Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 12 Feb 2026 11:01:13 +0100 Subject: [PATCH 302/319] Add missing unit tests --- .../Constructor_Test.php | 36 ++++++ .../Abstract_Schema_Piece_Repository_Test.php | 118 ++++++++++++++++++ .../Constructor_Test.php | 75 +++++++++++ .../Constructor_Test.php | 30 +++++ ...o_Schema_Piece_Repository_Collect_Test.php | 22 ++++ 5 files changed, 281 insertions(+) create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php new file mode 100644 index 00000000000..edb5579130d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php @@ -0,0 +1,36 @@ +assertInstanceOf( + EDD_Conditional::class, + $this->getPropertyValue( $this->instance, 'edd_conditional' ) + ); + + $this->assertInstanceOf( + Meta_Surface::class, + $this->getPropertyValue( $this->instance, 'meta' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php new file mode 100644 index 00000000000..cfb09bc0ff1 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php @@ -0,0 +1,118 @@ +memoizer = Mockery::mock( Meta_Tags_Context_Memoizer::class ); + $this->indexable_helper = Mockery::mock( Indexable_Helper::class ); + $this->adapter = Mockery::mock( Meta_Tags_Context_Memoizer_Adapter::class ); + $this->config = Mockery::mock( Aggregator_Config::class ); + $this->enhancement_factory = Mockery::mock( Schema_Enhancement_Factory::class ); + $this->indexable_repository_factory = Mockery::mock( Indexable_Repository_Factory::class ); + $this->global_state_adapter = Mockery::mock( WordPress_Global_State_Adapter::class ); + $this->external_repository = Mockery::mock( External_Schema_Piece_Repository_Interface::class ); + + $this->instance = new Schema_Piece_Repository( + $this->memoizer, + $this->indexable_helper, + $this->adapter, + $this->config, + $this->enhancement_factory, + $this->indexable_repository_factory, + $this->global_state_adapter, + $this->external_repository + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php new file mode 100644 index 00000000000..f81ab215cd4 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php @@ -0,0 +1,75 @@ +assertInstanceOf( + Meta_Tags_Context_Memoizer::class, + $this->getPropertyValue( $this->instance, 'memoizer' ) + ); + + $this->assertInstanceOf( + Indexable_Helper::class, + $this->getPropertyValue( $this->instance, 'indexable_helper' ) + ); + + $this->assertInstanceOf( + Meta_Tags_Context_Memoizer_Adapter::class, + $this->getPropertyValue( $this->instance, 'adapter' ) + ); + + $this->assertInstanceOf( + Aggregator_Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + + $this->assertInstanceOf( + Schema_Enhancement_Factory::class, + $this->getPropertyValue( $this->instance, 'enhancement_factory' ) + ); + + $this->assertInstanceOf( + Indexable_Repository_Factory::class, + $this->getPropertyValue( $this->instance, 'indexable_repository_factory' ) + ); + + $this->assertInstanceOf( + WordPress_Global_State_Adapter::class, + $this->getPropertyValue( $this->instance, 'global_state_adapter' ) + ); + + $external_repositories = $this->getPropertyValue( $this->instance, 'external_repositories' ); + $this->assertIsArray( $external_repositories ); + $this->assertCount( 1, $external_repositories ); + $this->assertInstanceOf( + External_Schema_Piece_Repository_Interface::class, + $external_repositories[0] + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php new file mode 100644 index 00000000000..58226a0b374 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php @@ -0,0 +1,30 @@ +assertInstanceOf( + WooCommerce_Conditional::class, + $this->getPropertyValue( $this->instance, 'woocommerce_conditional' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php index b898a0a9fe6..dd00226aa6c 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Woo_Schema_Piece_Repository_Collect_Test.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\Infrastructure\Schema_Pieces\Woo_Schema_Piece_Repository; use Brain\Monkey\Functions; +use Exception; /** * Test class for the collect method. @@ -73,4 +74,25 @@ public function test_collect_returns_empty_array_when_product_is_null() { $this->assertSame( [], $result ); } + + /** + * Tests that collect returns empty array when an exception is thrown. + * + * @return void + */ + public function test_collect_handles_exceptions_gracefully() { + $this->woocommerce_conditional + ->expects( 'is_met' ) + ->once() + ->andReturn( true ); + + Functions\expect( 'wc_get_product' ) + ->once() + ->with( 123 ) + ->andThrow( new Exception( 'WooCommerce error' ) ); + + $result = $this->instance->collect( 123 ); + + $this->assertSame( [], $result ); + } } From df3dc6a05d168055804ab6f2036a63c2691a6bf9 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 12 Feb 2026 11:01:26 +0100 Subject: [PATCH 303/319] Fix @cover annotations --- .../Indexable_Repository/WordPress_Query_Repository_Test.php | 2 ++ .../Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php | 2 ++ .../Schema_Pieces/Schema_Piece_Repository/Get_Test.php | 2 ++ .../Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php | 2 ++ 4 files changed, 8 insertions(+) diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php index 8507371eaf0..102cbe8d463 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php @@ -13,6 +13,8 @@ /** * Integration Test Class for WordPress_Query_Repository. * + * @group schema-aggregator + * * @covers \Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\WordPress_Query_Repository::get */ final class WordPress_Query_Repository_Test extends TestCase { diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php index af58d917831..61beca13013 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php @@ -10,6 +10,8 @@ /** * Integration Test Class for Edd_Schema_Piece_Repository::collect. * + * @group schema-aggregator + * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Edd_Schema_Piece_Repository::collect */ final class Collect_Test extends TestCase { diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php index 5280b4fa2fd..34b7e73156e 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php @@ -34,6 +34,8 @@ /** * Integration Test Class for Schema_Piece_Repository. * + * @group schema-aggregator + * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Schema_Piece_Repository::get * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Schema_Piece_Repository::collect_external_schema * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Schema_Piece_Repository::get_all_schema_types diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php index 5b34fb4a12c..8af458c3c8a 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php @@ -12,6 +12,8 @@ /** * Integration Test Class for Woo_Schema_Piece_Repository::collect. * + * @group schema-aggregator + * * @covers Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces\Woo_Schema_Piece_Repository::collect */ final class Collect_Test extends TestCase { From 7143dde1175bb7aa748f3ab9dfc59a0adcdea2ae Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Thu, 12 Feb 2026 12:57:55 +0100 Subject: [PATCH 304/319] Add global indexable alert. --- .../indexables-disabled-alert.php | 128 ++++++++++++++++++ ...bstract_Indexables_Disabled_Alert_Test.php | 69 ++++++++++ ..._Disabled_Alert_Add_Notifications_Test.php | 104 ++++++++++++++ ...xables_Disabled_Alert_Constructor_Test.php | 40 ++++++ ...s_Disabled_Alert_Get_Conditionals_Test.php | 29 ++++ ...les_Disabled_Alert_Register_Hooks_Test.php | 33 +++++ 6 files changed, 403 insertions(+) create mode 100644 src/alerts/application/indexables-disabled/indexables-disabled-alert.php create mode 100644 tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php create mode 100644 tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php create mode 100644 tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php create mode 100644 tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Get_Conditionals_Test.php create mode 100644 tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php diff --git a/src/alerts/application/indexables-disabled/indexables-disabled-alert.php b/src/alerts/application/indexables-disabled/indexables-disabled-alert.php new file mode 100644 index 00000000000..19ff67cc52e --- /dev/null +++ b/src/alerts/application/indexables-disabled/indexables-disabled-alert.php @@ -0,0 +1,128 @@ +notification_center = $notification_center; + $this->indexable_helper = $indexable_helper; + $this->short_link_helper = $short_link_helper; + } + + /** + * Returns the conditionals based on which this loadable should be active. + * + * @return array + */ + public static function get_conditionals() { + return [ Admin_Conditional::class ]; + } + + /** + * Initializes the integration. + * + * @return void + */ + public function register_hooks() { + \add_action( 'admin_init', [ $this, 'add_notifications' ] ); + } + + /** + * Adds or removes notification based on whether indexables are disabled. + * + * @return void + */ + public function add_notifications() { + if ( $this->indexable_helper->should_index_indexables() ) { + $this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID ); + return; + } + + $notification = $this->get_indexables_disabled_notification(); + + $this->notification_center->add_notification( $notification ); + } + + /** + * Builds the indexables-disabled notification. + * + * @return Yoast_Notification The indexables-disabled notification. + */ + private function get_indexables_disabled_notification(): Yoast_Notification { + $message = $this->get_message(); + + return new Yoast_Notification( + $message, + [ + 'id' => self::NOTIFICATION_ID, + 'type' => Yoast_Notification::WARNING, + 'capabilities' => [ 'wpseo_manage_options' ], + ] + ); + } + + /** + * Returns the notification message as an HTML string. + * + * @return string The HTML string representation of the notification. + */ + private function get_message(): string { + $shortlink = $this->short_link_helper->get( 'https://yoa.st/indexables-disabled' ); + + $message = \sprintf( + /* translators: %1$s expands to "Yoast", %2$s expands to an opening anchor tag, %3$s expands to a closing anchor tag. */ + \esc_html__( '%1$s indexables are disabled because your site is in a non-production environment or custom code is blocking them. This may affect your SEO features. %2$sLearn more about this%3$s.', 'wordpress-seo' ), + 'Yoast', + '', + '' + ); + + return $message; + } +} diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php new file mode 100644 index 00000000000..302586da498 --- /dev/null +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php @@ -0,0 +1,69 @@ +stubTranslationFunctions(); + $this->stubEscapeFunctions(); + + $this->notification_center = Mockery::mock( Yoast_Notification_Center::class ); + $this->indexable_helper = Mockery::mock( Indexable_Helper::class ); + $this->short_link_helper = Mockery::mock( Short_Link_Helper::class ); + + $this->instance = new Indexables_Disabled_Alert( + $this->notification_center, + $this->indexable_helper, + $this->short_link_helper + ); + } +} diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php new file mode 100644 index 00000000000..845def76fb2 --- /dev/null +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php @@ -0,0 +1,104 @@ +ID = 1; + + Functions\expect( 'get_current_user_id' ) + ->andReturn( $admin_user->ID ); + + $this->indexable_helper + ->expects( 'should_index_indexables' ) + ->once() + ->andReturn( $should_index_indexables ); + + $this->notification_center + ->expects( 'remove_notification_by_id' ) + ->times( $remove_notification_times ) + ->with( 'wpseo-indexables-disabled' ); + + $this->short_link_helper + ->expects( 'get' ) + ->with( 'https://yoa.st/indexables-disabled' ) + ->times( $get_shortlink_times ) + ->andReturn( $shortlink ); + + $this->notification_center + ->expects( 'add_notification' ) + ->times( $add_notification_times ) + ->withArgs( + static function ( $notification ) use ( $expected_message ) { + $notification_array = $notification->to_array(); + return $notification_array['message'] === $expected_message; + } + ); + + $this->instance->add_notifications(); + } + + /** + * Data provider for the test_add_notifications test. + * + * @return Generator Test data to use. + */ + public static function add_notifications_data() { + yield 'Indexables enabled - removes notification' => [ + 'should_index_indexables' => true, + 'remove_notification_times' => 1, + 'get_shortlink_times' => 0, + 'shortlink' => 'irrelevant', + 'add_notification_times' => 0, + 'expected_message' => 'irrelevant', + ]; + + yield 'Indexables disabled - adds notification' => [ + 'should_index_indexables' => false, + 'remove_notification_times' => 0, + 'get_shortlink_times' => 1, + 'shortlink' => 'https://yoa.st/indexables-disabled?some=params', + 'add_notification_times' => 1, + 'expected_message' => 'Yoast indexables are disabled because your site is in a non-production environment or custom code is blocking them. This may affect your SEO features. Learn more about this.', + ]; + } +} diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php new file mode 100644 index 00000000000..bb9fb10f318 --- /dev/null +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php @@ -0,0 +1,40 @@ +assertInstanceOf( + Yoast_Notification_Center::class, + $this->getPropertyValue( $this->instance, 'notification_center' ) + ); + $this->assertInstanceOf( + Indexable_Helper::class, + $this->getPropertyValue( $this->instance, 'indexable_helper' ) + ); + $this->assertInstanceOf( + Short_Link_Helper::class, + $this->getPropertyValue( $this->instance, 'short_link_helper' ) + ); + } +} diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Get_Conditionals_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Get_Conditionals_Test.php new file mode 100644 index 00000000000..f958134c9fd --- /dev/null +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Get_Conditionals_Test.php @@ -0,0 +1,29 @@ +assertEquals( $expected, $this->instance->get_conditionals() ); + } +} diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php new file mode 100644 index 00000000000..64b55f04026 --- /dev/null +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php @@ -0,0 +1,33 @@ +instance->register_hooks(); + + $this->assertEquals( + 10, + \has_action( + 'admin_init', + [ $this->instance, 'add_notifications' ] + ) + ); + } +} From 84a86ae6096dc882a08ec0e8d5147493922302b5 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 12 Feb 2026 14:52:18 +0100 Subject: [PATCH 305/319] Ignore some methods for code coverage --- .../elements-context-map/elements-context-map-repository.php | 2 ++ .../user-interface/site-schema-aggregator-xml-route.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php index 3874124468a..bfd57fc3184 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php @@ -45,6 +45,8 @@ public function get_map(): array { /** * Saves the elements-context map. * + * @codeCoverageIgnore -- This is just a setter. + * * @param array> $map The elements-context map to besaved. * * @return void diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php index 7004c4d3e20..a6e30740a22 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-xml-route.php @@ -100,6 +100,8 @@ public function register_routes() { /** * Permission callback for the route. * + * @codeCoverageIgnore -- No sensible tests can be written for this. + * * @return bool True if the user has permission, false otherwise. */ public function get_permission_callback(): bool { From b741d410b52c8d8cb99c729fe25ec90b71394cda Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Thu, 12 Feb 2026 14:52:26 +0100 Subject: [PATCH 306/319] Add unit tests --- ...ct_Schema_Aggregator_Announcement_Test.php | 49 +++++++ .../Constructor_Test.php | 31 +++++ .../Get_Id_Test.php | 26 ++++ .../Get_Priority_Test.php | 26 ++++ .../Should_Show_Test.php | 53 ++++++++ .../Schema_Aggregator_Announcement_Test.php | 121 ------------------ ...t_Elements_Context_Map_Repository_Test.php | 48 +++++++ .../Constructor_Test.php | 30 +++++ .../Get_Map_Test.php | 84 ++++++++++++ .../Filtering_Strategy_Factory_Test.php | 71 ++++++++++ ...rdPress_Current_Site_URL_Provider_Test.php | 44 +++++++ ...ract_Site_Schema_Aggregator_Route_Test.php | 78 +++++++++++ .../Constructor_Test.php | 48 +++++++ .../Get_Conditionals_Test.php | 31 +++++ .../Register_Routes_Test.php | 113 ++++++++++++++++ ..._Site_Schema_Aggregator_Xml_Route_Test.php | 68 ++++++++++ .../Get_Conditionals_Test.php | 31 +++++ .../Register_Routes_Test.php | 39 ++++++ 18 files changed, 870 insertions(+), 121 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Id_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Priority_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Should_Show_Test.php delete mode 100644 tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Get_Map_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/Filtering_Strategy_Factory_Test.php create mode 100644 tests/Unit/Schema_Aggregator/Infrastructure/WordPress_Current_Site_URL_Provider_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Get_Conditionals_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Get_Conditionals_Test.php create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php new file mode 100644 index 00000000000..0dd8f517fc8 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php @@ -0,0 +1,49 @@ +current_page_helper = Mockery::mock( Current_Page_Helper::class ); + + $this->instance = new Schema_Aggregator_Announcement( + $this->current_page_helper + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php new file mode 100644 index 00000000000..82d20a8215e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php @@ -0,0 +1,31 @@ +assertInstanceOf( + Current_Page_Helper::class, + $this->getPropertyValue( $this->instance, 'current_page_helper' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Id_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Id_Test.php new file mode 100644 index 00000000000..f1e3d4a918d --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Id_Test.php @@ -0,0 +1,26 @@ +assertSame( 'schema-aggregator-announcement', $this->instance->get_id() ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Priority_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Priority_Test.php new file mode 100644 index 00000000000..22c05e560d9 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Get_Priority_Test.php @@ -0,0 +1,26 @@ +assertSame( 20, $this->instance->get_priority() ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Should_Show_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Should_Show_Test.php new file mode 100644 index 00000000000..af99908f36e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Should_Show_Test.php @@ -0,0 +1,53 @@ +current_page_helper->expects( 'is_yoast_seo_page' ) + ->withNoArgs() + ->andReturn( $is_yoast_seo_page ); + + $this->assertSame( $expected, $this->instance->should_show() ); + } + + /** + * Provides the data for test_should_show. + * + * @return array> + */ + public static function should_show_data(): array { + return [ + 'on a Yoast admin page' => [ + 'is_yoast_seo_page' => true, + 'expected' => true, + ], + 'not on a Yoast admin page' => [ + 'is_yoast_seo_page' => false, + 'expected' => false, + ], + ]; + } +} diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement_Test.php deleted file mode 100644 index 43788eb152c..00000000000 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement_Test.php +++ /dev/null @@ -1,121 +0,0 @@ -current_page_helper = Mockery::mock( Current_Page_Helper::class ); - - $this->instance = new Schema_Aggregator_Announcement( $this->current_page_helper ); - } - - /** - * Tests if the needed attributes are set correctly. - * - * @covers ::__construct - * - * @return void - */ - public function test_constructor() { - $this->assertInstanceOf( - Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) - ); - } - - /** - * Tests getting the ID. - * - * @covers ::get_id - * - * @return void - */ - public function test_get_id() { - $this->assertSame( 'schema-aggregator-announcement', $this->instance->get_id() ); - } - - /** - * Tests getting the priority. - * - * @covers ::get_priority - * - * @return void - */ - public function test_get_priority() { - $this->assertSame( 20, $this->instance->get_priority() ); - } - - /** - * Tests the conditional `should_show`. - * - * @covers ::should_show - * - * @dataProvider should_show_data - * - * @param bool $is_yoast_seo_page Whether on a Yoast SEO page. - * @param bool $expected The expected result. - * - * @return void - */ - public function test_should_show( bool $is_yoast_seo_page, bool $expected ) { - $this->current_page_helper->expects( 'is_yoast_seo_page' ) - ->withNoArgs() - ->andReturn( $is_yoast_seo_page ); - - $this->assertSame( $expected, $this->instance->should_show() ); - } - - /** - * Provides the data for `test_should_show`. - * - * @return array> - */ - public static function should_show_data(): array { - return [ - 'on a Yoast admin page' => [ - 'is_yoast_seo_page' => true, - 'expected' => true, - ], - 'not on a Yoast admin page' => [ - 'is_yoast_seo_page' => false, - 'expected' => false, - ], - ]; - } -} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php new file mode 100644 index 00000000000..27ac612a848 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php @@ -0,0 +1,48 @@ +map_loader = Mockery::mock( Map_Loader_Interface::class ); + + $this->instance = new Elements_Context_Map_Repository( + $this->map_loader + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php new file mode 100644 index 00000000000..d2b8b1ebd5a --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php @@ -0,0 +1,30 @@ +assertInstanceOf( + Map_Loader_Interface::class, + $this->getPropertyValue( $this->instance, 'map_loader' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Get_Map_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Get_Map_Test.php new file mode 100644 index 00000000000..ffaecb3f595 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Get_Map_Test.php @@ -0,0 +1,84 @@ + 'WebPage', + 'context' => 'ItemPage', + ], + [ + 'element' => 'Product', + 'context' => 'Product', + ], + ]; + + $this->map_loader + ->expects( 'load' ) + ->once() + ->andReturn( $expected_map ); + + $result = $this->instance->get_map(); + + $this->assertSame( $expected_map, $result ); + } + + /** + * Tests that get_map caches the result and does not call the loader again. + * + * @return void + */ + public function test_get_map_caches_result() { + $expected_map = [ + [ + 'element' => 'WebPage', + 'context' => 'ItemPage', + ], + ]; + + $this->map_loader + ->expects( 'load' ) + ->once() + ->andReturn( $expected_map ); + + $first_call = $this->instance->get_map(); + $second_call = $this->instance->get_map(); + + $this->assertSame( $expected_map, $first_call ); + $this->assertSame( $expected_map, $second_call ); + } + + /** + * Tests that get_map returns an empty array when the loader returns one. + * + * @return void + */ + public function test_get_map_returns_empty_array() { + $this->map_loader + ->expects( 'load' ) + ->once() + ->andReturn( [] ); + + $result = $this->instance->get_map(); + + $this->assertSame( [], $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Filtering_Strategy_Factory_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Filtering_Strategy_Factory_Test.php new file mode 100644 index 00000000000..9b934676fe3 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Filtering_Strategy_Factory_Test.php @@ -0,0 +1,71 @@ +once() + ->andReturnFirstArg(); + + $instance = new Filtering_Strategy_Factory(); + $result = $instance->create(); + + $this->assertInstanceOf( Default_Filter::class, $result ); + } + + /** + * Tests that create returns a custom strategy when the filter provides one. + * + * @return void + */ + public function test_create_returns_custom_strategy_from_filter() { + $custom_strategy = Mockery::mock( Filtering_Strategy_Interface::class ); + + Filters\expectApplied( 'wpseo_schema_aggregator_filtering_strategy' ) + ->once() + ->andReturn( $custom_strategy ); + + $instance = new Filtering_Strategy_Factory(); + $result = $instance->create(); + + $this->assertSame( $custom_strategy, $result ); + } + + /** + * Tests that create returns the default filter when the filter returns a non-strategy value. + * + * @return void + */ + public function test_create_returns_default_filter_when_filter_returns_invalid_value() { + Filters\expectApplied( 'wpseo_schema_aggregator_filtering_strategy' ) + ->once() + ->andReturn( 'not a strategy' ); + + $instance = new Filtering_Strategy_Factory(); + $result = $instance->create(); + + $this->assertInstanceOf( Default_Filter::class, $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/WordPress_Current_Site_URL_Provider_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/WordPress_Current_Site_URL_Provider_Test.php new file mode 100644 index 00000000000..ce2156f8b6c --- /dev/null +++ b/tests/Unit/Schema_Aggregator/Infrastructure/WordPress_Current_Site_URL_Provider_Test.php @@ -0,0 +1,44 @@ +once() + ->andReturn( 1 ); + + Functions\expect( 'get_home_url' ) + ->once() + ->with( 1 ) + ->andReturn( 'https://example.com' ); + + Functions\expect( 'trailingslashit' ) + ->once() + ->with( 'https://example.com' ) + ->andReturn( 'https://example.com/' ); + + $instance = new WordPress_Current_Site_URL_Provider(); + $result = $instance->get_current_site_url(); + + $this->assertSame( 'https://example.com/', $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php new file mode 100644 index 00000000000..3c293e2a121 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php @@ -0,0 +1,78 @@ +config = Mockery::mock( Config::class ); + $this->capability_helper = Mockery::mock( Capability_Helper::class ); + $this->command_handler = Mockery::mock( Aggregate_Site_Schema_Command_Handler::class ); + $this->cache_manager = Mockery::mock( Manager::class ); + + $this->instance = new Site_Schema_Aggregator_Route( + $this->config, + $this->capability_helper, + $this->command_handler, + $this->cache_manager + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php new file mode 100644 index 00000000000..88bf7282b50 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php @@ -0,0 +1,48 @@ +assertInstanceOf( + Config::class, + $this->getPropertyValue( $this->instance, 'config' ) + ); + + $this->assertInstanceOf( + Capability_Helper::class, + $this->getPropertyValue( $this->instance, 'capability_helper' ) + ); + + $this->assertInstanceOf( + Aggregate_Site_Schema_Command_Handler::class, + $this->getPropertyValue( $this->instance, 'aggregate_site_schema_command_handler' ) + ); + + $this->assertInstanceOf( + Manager::class, + $this->getPropertyValue( $this->instance, 'cache_manager' ) + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Get_Conditionals_Test.php new file mode 100644 index 00000000000..8a7d298e55e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Get_Conditionals_Test.php @@ -0,0 +1,31 @@ +assertSame( $expected, $this->instance::get_conditionals() ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php new file mode 100644 index 00000000000..8db4b8393b5 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php @@ -0,0 +1,113 @@ +twice() + ->with( + 'yoast/v1', + Mockery::type( 'string' ), + Mockery::type( 'array' ) + ); + + $this->instance->register_routes(); + } + + /** + * Tests that register_routes registers the base post type route. + * + * @return void + */ + public function test_register_routes_registers_post_type_route() { + $captured_config = null; + + Functions\expect( 'register_rest_route' ) + ->once() + ->with( + 'yoast/v1', + 'schema-aggregator/get-schema/(?P[a-z0-9_-]+)', + Mockery::on( + static function ( $config ) use ( &$captured_config ) { + $captured_config = $config; + return true; + } + ) + ); + + Functions\expect( 'register_rest_route' ) + ->once() + ->with( + 'yoast/v1', + 'schema-aggregator/get-schema/(?P[a-z0-9_-]+)/(?P\d+)', + Mockery::type( 'array' ) + ); + + $this->instance->register_routes(); + + $this->assertSame( 'GET', $captured_config['methods'] ); + $this->assertSame( [ $this->instance, 'aggregate_site_schema' ], $captured_config['callback'] ); + $this->assertSame( [ $this->instance, 'get_permission_callback' ], $captured_config['permission_callback'] ); + $this->assertArrayHasKey( 'post_type', $captured_config['args'] ); + $this->assertTrue( $captured_config['args']['post_type']['required'] ); + } + + /** + * Tests that register_routes registers the paginated route with page argument. + * + * @return void + */ + public function test_register_routes_registers_paginated_route() { + $captured_config = null; + + Functions\expect( 'register_rest_route' ) + ->once() + ->with( + 'yoast/v1', + 'schema-aggregator/get-schema/(?P[a-z0-9_-]+)', + Mockery::type( 'array' ) + ); + + Functions\expect( 'register_rest_route' ) + ->once() + ->with( + 'yoast/v1', + 'schema-aggregator/get-schema/(?P[a-z0-9_-]+)/(?P\d+)', + Mockery::on( + static function ( $config ) use ( &$captured_config ) { + $captured_config = $config; + return true; + } + ) + ); + + $this->instance->register_routes(); + + $this->assertSame( 'GET', $captured_config['methods'] ); + $this->assertSame( [ $this->instance, 'aggregate_site_schema' ], $captured_config['callback'] ); + $this->assertSame( [ $this->instance, 'get_permission_callback' ], $captured_config['permission_callback'] ); + $this->assertArrayHasKey( 'post_type', $captured_config['args'] ); + $this->assertArrayHasKey( 'page', $captured_config['args'] ); + $this->assertSame( 1, $captured_config['args']['page']['default'] ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php new file mode 100644 index 00000000000..a8477a384e9 --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php @@ -0,0 +1,68 @@ +command_handler = Mockery::mock( Aggregate_Site_Schema_Map_Command_Handler::class ); + $this->xml_cache_manager = Mockery::mock( Xml_Manager::class ); + $this->aggregator_config = Mockery::mock( Aggregator_Config::class ); + + $this->instance = new Site_Schema_Aggregator_Xml_Route( + $this->command_handler, + $this->xml_cache_manager, + $this->aggregator_config + ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Get_Conditionals_Test.php new file mode 100644 index 00000000000..e5ccedde1ec --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Get_Conditionals_Test.php @@ -0,0 +1,31 @@ +assertSame( $expected, $this->instance::get_conditionals() ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php new file mode 100644 index 00000000000..3f985e5605e --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php @@ -0,0 +1,39 @@ +once() + ->with( + 'yoast/v1', + 'schema-aggregator/get-xml', + [ + 'methods' => 'GET', + 'callback' => [ $this->instance, 'render_schema_xml' ], + 'permission_callback' => [ $this->instance, 'get_permission_callback' ], + ] + ); + + $this->instance->register_routes(); + } +} From 0926b4cf928bb6d651083250b4641d7dd081ca0b Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 12:35:44 +0100 Subject: [PATCH 307/319] Merge trunk --- .github/workflows/browserslist-db.yml | 2 +- .github/workflows/codeql-analysis.yml | 6 +- .github/workflows/cs.yml | 2 +- .github/workflows/deploy.yml | 4 +- .github/workflows/deprecation-check.yml | 2 +- .github/workflows/finish-coveralls.yml | 4 +- .github/workflows/generate_csv.yml | 2 +- .github/workflows/jslint.yml | 2 +- .github/workflows/jstest.yml | 6 +- .github/workflows/lint.yml | 2 +- .github/workflows/security.yml | 2 +- .github/workflows/test.yml | 4 +- admin/ajax.php | 14 +- ...s-admin-asset-analysis-worker-location.php | 2 +- .../class-admin-asset-dev-server-location.php | 4 +- admin/class-admin-asset-manager.php | 20 +- ...ass-admin-editor-specific-replace-vars.php | 8 +- ...n-gutenberg-compatibility-notification.php | 4 +- admin/class-admin-help-panel.php | 4 +- admin/class-admin-init.php | 8 +- admin/class-admin-utils.php | 8 +- admin/class-admin.php | 8 +- ...ass-bulk-description-editor-list-table.php | 2 +- admin/class-bulk-editor-list-table.php | 52 +-- admin/class-bulk-title-editor-list-table.php | 2 +- admin/class-config.php | 2 +- admin/class-database-proxy.php | 8 +- admin/class-export.php | 8 +- admin/class-meta-columns.php | 8 +- admin/class-my-yoast-proxy.php | 2 +- admin/class-option-tabs-formatter.php | 2 +- admin/class-plugin-availability.php | 4 +- admin/class-premium-upsell-admin-block.php | 10 +- admin/class-primary-term-admin.php | 8 +- admin/class-product-upsell-notice.php | 10 +- ...ass-schema-person-upgrade-notification.php | 4 +- admin/class-suggested-plugins.php | 6 +- admin/class-wincher-dashboard-widget.php | 2 +- admin/class-yoast-columns.php | 8 +- admin/class-yoast-dashboard-widget.php | 8 +- admin/class-yoast-form.php | 34 +- admin/class-yoast-input-validation.php | 2 +- admin/class-yoast-network-admin.php | 4 +- admin/class-yoast-network-settings-api.php | 4 +- admin/class-yoast-notification-center.php | 8 +- admin/class-yoast-notification.php | 10 +- admin/class-yoast-notifications.php | 2 +- admin/class-yoast-plugin-conflict.php | 8 +- .../exceptions/class-file-size-exception.php | 4 +- admin/filters/class-abstract-post-filter.php | 4 +- admin/filters/class-cornerstone-filter.php | 8 +- .../views/gsc-display.php | 4 +- .../views/gsc-redirect-nopremium.php | 4 +- .../class-abstract-plugin-importer.php | 24 +- .../import/plugins/class-import-aioseo-v4.php | 14 +- .../class-import-platinum-seo-pack.php | 2 +- .../import/plugins/class-import-squirrly.php | 8 +- .../plugins/class-import-woothemes-seo.php | 4 +- admin/import/plugins/class-import-wpseo.php | 4 +- admin/menu/class-admin-menu.php | 4 +- admin/menu/class-base-menu.php | 12 +- admin/menu/class-network-admin-menu.php | 4 +- admin/menu/class-replacevar-editor.php | 8 +- admin/menu/class-replacevar-field.php | 2 +- .../class-abstract-sectioned-metabox-tab.php | 2 +- admin/metabox/class-metabox-collapsible.php | 2 +- admin/metabox/class-metabox-form-tab.php | 4 +- .../class-metabox-section-additional.php | 4 +- ...ass-metabox-section-inclusive-language.php | 4 +- admin/metabox/class-metabox-section-react.php | 4 +- .../class-metabox-section-readability.php | 4 +- admin/metabox/class-metabox.php | 20 +- admin/notifiers/dismissible-notification.php | 2 +- admin/pages/network.php | 4 +- admin/pages/tools.php | 2 +- admin/roles/class-role-manager-factory.php | 4 +- admin/services/class-file-size.php | 6 +- admin/statistics/class-statistics-service.php | 8 +- admin/taxonomy/class-taxonomy-fields.php | 2 +- admin/taxonomy/class-taxonomy-metabox.php | 4 +- admin/taxonomy/class-taxonomy.php | 4 +- admin/views/class-yoast-feature-toggles.php | 16 +- .../views/class-yoast-integration-toggles.php | 10 +- admin/views/js-templates-primary-term.php | 6 +- admin/views/paper-collapsible.php | 4 +- admin/views/partial-notifications-errors.php | 2 +- .../views/partial-notifications-template.php | 8 +- .../views/partial-notifications-warnings.php | 2 +- admin/views/tabs/dashboard/dashboard.php | 2 +- admin/views/tabs/network/crawl-settings.php | 4 +- admin/views/tabs/network/features.php | 8 +- admin/views/tabs/network/general.php | 6 +- admin/views/tabs/network/integrations.php | 8 +- admin/views/tabs/network/restore-site.php | 2 +- admin/views/tabs/tool/import-seo.php | 6 +- admin/views/tabs/tool/wpseo-export.php | 2 +- admin/views/tabs/tool/wpseo-import.php | 4 +- admin/views/tool-bulk-editor.php | 6 +- admin/views/tool-file-editor.php | 36 +-- admin/watchers/class-slug-change-watcher.php | 6 +- composer.json | 8 +- composer.lock | 296 ++++++++++-------- config/composer/actions.php | 10 +- config/composer/unit-test-generator.php | 12 +- .../container-compiler.php | 2 +- config/dependency-injection/custom-loader.php | 6 +- .../interface-injection-pass.php | 2 +- inc/class-addon-manager.php | 12 +- inc/class-my-yoast-api-request.php | 4 +- inc/class-rewrite.php | 2 +- inc/class-upgrade-history.php | 4 +- inc/class-upgrade.php | 94 +++--- inc/class-wpseo-admin-bar-menu.php | 32 +- inc/class-wpseo-content-images.php | 4 +- inc/class-wpseo-custom-taxonomies.php | 2 +- inc/class-wpseo-image-utils.php | 10 +- inc/class-wpseo-meta.php | 16 +- inc/class-wpseo-rank.php | 24 +- inc/class-wpseo-replace-vars.php | 14 +- inc/class-wpseo-utils.php | 12 +- inc/options/class-wpseo-option-ms.php | 8 +- inc/options/class-wpseo-option-titles.php | 4 +- inc/options/class-wpseo-options.php | 4 +- .../class-post-type-sitemap-provider.php | 18 +- inc/sitemaps/class-sitemap-image-parser.php | 4 +- .../class-sitemaps-cache-validator.php | 8 +- inc/sitemaps/class-sitemaps.php | 12 +- .../class-taxonomy-sitemap-provider.php | 8 +- lib/migrations/adapter.php | 6 +- lib/migrations/table.php | 4 +- lib/model.php | 2 +- lib/orm.php | 8 +- readme.txt | 14 +- .../first-time-configuration-action.php | 2 +- .../aioseo/aioseo-cleanup-action.php | 2 +- .../aioseo/aioseo-posts-importing-action.php | 2 +- .../aioseo/aioseo-validate-data-action.php | 2 +- .../indexable-post-indexation-action.php | 8 +- .../indexable-term-indexation-action.php | 4 +- .../indexing/post-link-indexing-action.php | 6 +- .../indexing/term-link-indexing-action.php | 6 +- .../wincher/wincher-keyphrases-action.php | 30 +- .../application/token-manager.php | 4 +- .../access-token-user-meta-repository.php | 2 +- .../code-verifier-user-meta-repository.php | 2 +- .../refresh-token-user-meta-repository.php | 2 +- .../abstract-callback-route.php | 2 +- .../user-interface/callback-route.php | 2 +- .../user-interface/refresh-callback-route.php | 2 +- .../user-interface/consent-route.php | 4 +- .../user-interface/free-sparks-route.php | 2 +- .../domain/suggestions-bucket.php | 2 +- .../bust-subscription-cache-route.php | 2 +- .../user-interface/get-suggestions-route.php | 6 +- .../user-interface/get-usage-route.php | 4 +- .../application/request-handler.php | 2 +- .../default-seo-data-alert.php | 4 +- .../ping-other-admins-alert.php | 4 +- ...ult-seo-data-cron-callback-integration.php | 2 +- .../user-interface/resolve-alert-route.php | 6 +- .../missing-indexables-collector.php | 2 +- .../domain/missing-indexable-bucket.php | 2 +- .../domain/to-be-cleaned-indexable-bucket.php | 2 +- .../last-completed-indexation-integration.php | 2 +- src/builders/indexable-author-builder.php | 6 +- src/builders/indexable-builder.php | 4 +- src/builders/indexable-home-page-builder.php | 4 +- src/builders/indexable-link-builder.php | 8 +- src/builders/indexable-post-builder.php | 4 +- .../indexable-post-type-archive-builder.php | 4 +- src/builders/indexable-term-builder.php | 6 +- src/commands/cleanup-command.php | 12 +- src/commands/index-command.php | 10 +- src/config/badge-group-names.php | 4 +- src/config/conflicting-plugins.php | 2 +- .../20171228151840_WpYoastIndexable.php | 62 ++-- .../20171228151841_WpYoastPrimaryTerm.php | 10 +- ...191011111109_WpYoastIndexableHierarchy.php | 6 +- .../20200420073606_AddColumnsToIndexables.php | 2 +- ...23747_BreadcrumbTitleAndHierarchyReset.php | 2 +- ...428194858_ExpandIndexableColumnLengths.php | 10 +- ...75614_AddIndexableObjectIdAndTypeIndex.php | 4 +- .../20200609154515_AddHasAncestorsColumn.php | 4 +- ...200616130143_ReplacePermalinkHashIndex.php | 12 +- .../20200617122511_CreateSEOLinksTable.php | 6 +- ...702141921_CreateIndexableSubpagesIndex.php | 8 +- ...ddIndexesForProminentWordsOnIndexables.php | 2 +- ...20201202144329_AddEstimatedReadingTime.php | 2 +- ...6124002_ExpandIndexableIDColumnLengths.php | 2 +- ...41134_ExpandPrimaryTermIDColumnLengths.php | 2 +- ...817092415_AddVersionColumnToIndexables.php | 4 +- .../20211020091404_AddObjectTimestamps.php | 8 +- ...230417083836_AddInclusiveLanguageScore.php | 2 +- .../20260105111111_AddSeoLinksIndex.php | 8 +- src/config/oauth-client.php | 6 +- src/config/schema-types.php | 2 +- src/config/semrush-client.php | 6 +- src/config/wincher-client.php | 6 +- src/config/wincher-pkce-provider.php | 12 +- ...ontent-type-visibility-watcher-actions.php | 4 +- ...tent-type-visibility-dismiss-new-route.php | 4 +- src/context/meta-tags-context.php | 12 +- .../configuration/dashboard-configuration.php | 2 +- .../browser-cache-configuration.php | 2 +- .../infrastructure/integrations/site-kit.php | 16 +- .../readability-score-results-collector.php | 6 +- .../seo-score-results-collector.php | 6 +- .../site-kit-search-console-adapter.php | 4 +- .../taxonomies/taxonomies-collector.php | 2 +- ...site-kit-configuration-dismissal-route.php | 6 +- .../site-kit-consent-management-route.php | 6 +- .../scores/abstract-scores-route.php | 8 +- .../setup/setup-url-interceptor.php | 2 +- .../time-based-seo-metrics-route.php | 6 +- .../tracking/setup-steps-tracking-route.php | 10 +- src/deprecated/frontend/breadcrumbs.php | 4 +- src/deprecated/frontend/frontend.php | 4 +- .../black-friday-checklist-promotion.php | 4 +- .../indexable/author-not-built-exception.php | 6 +- .../indexable/invalid-term-exception.php | 4 +- .../indexable/not-built-exception.php | 2 +- src/exceptions/missing-method.php | 4 +- .../general-page-integration.php | 2 +- src/general/user-interface/opt-in-route.php | 2 +- src/generators/breadcrumbs-generator.php | 6 +- src/generators/open-graph-image-generator.php | 4 +- src/generators/schema-generator.php | 2 +- src/helpers/crawl-cleanup-helper.php | 2 +- src/helpers/current-page-helper.php | 2 +- src/helpers/home-url-helper.php | 8 +- src/helpers/indexing-helper.php | 2 +- src/helpers/notification-helper.php | 2 +- src/helpers/post-type-helper.php | 2 +- src/helpers/redirect-helper.php | 4 +- src/helpers/schema/article-helper.php | 4 +- src/helpers/schema/replace-vars-helper.php | 2 +- src/helpers/social-profiles-helper.php | 2 +- src/helpers/url-helper.php | 4 +- src/helpers/woocommerce-helper.php | 2 +- src/initializers/crawl-cleanup-permalinks.php | 2 +- src/integrations/academy-integration.php | 2 +- .../addon-installation/dialog-integration.php | 6 +- .../installation-integration.php | 10 +- .../admin/check-required-version.php | 6 +- .../admin/crawl-settings-integration.php | 8 +- src/integrations/admin/cron-integration.php | 2 +- .../admin/deactivated-premium-integration.php | 8 +- .../first-time-configuration-integration.php | 6 +- ...-time-configuration-notice-integration.php | 6 +- src/integrations/admin/helpscout-beacon.php | 12 +- .../indexing-notification-integration.php | 2 +- .../admin/indexing-tool-integration.php | 2 +- .../installation-success-integration.php | 6 +- src/integrations/admin/integrations-page.php | 8 +- .../admin/link-count-columns-integration.php | 4 +- .../admin/old-configuration-integration.php | 4 +- .../admin/redirections-tools-page.php | 4 +- .../admin/redirects-page-integration.php | 2 +- .../admin/workouts-integration.php | 18 +- .../blocks/abstract-dynamic-block-v3.php | 2 +- .../blocks/abstract-dynamic-block.php | 2 +- src/integrations/blocks/block-categories.php | 4 +- src/integrations/blocks/breadcrumbs-block.php | 2 +- .../blocks/structured-data-blocks.php | 22 +- src/integrations/cleanup-integration.php | 4 +- src/integrations/front-end-integration.php | 10 +- .../front-end/crawl-cleanup-rss.php | 4 +- .../front-end/crawl-cleanup-searches.php | 2 +- .../front-end/force-rewrite-title.php | 2 +- src/integrations/front-end/redirects.php | 2 +- .../front-end/robots-txt-integration.php | 4 +- .../front-end/wp-robots-integration.php | 2 +- src/integrations/settings-integration.php | 12 +- src/integrations/third-party/elementor.php | 10 +- .../third-party/wpml-wpseo-notification.php | 4 +- .../watchers/addon-update-watcher.php | 8 +- .../watchers/indexable-ancestor-watcher.php | 10 +- .../indexable-author-archive-watcher.php | 2 +- .../watchers/indexable-post-watcher.php | 2 +- .../watchers/option-titles-watcher.php | 4 +- .../search-engines-discouraged-watcher.php | 4 +- .../woocommerce-beta-editor-watcher.php | 2 +- ...product-category-permalink-integration.php | 2 +- .../application/delayed-premium-upsell.php | 4 +- .../application/introductions-collector.php | 4 +- .../domain/introductions-bucket.php | 2 +- .../introductions-integration.php | 4 +- .../introductions-seen-route.php | 6 +- .../wistia-embed-permission-route.php | 12 +- .../file-failure-notification-presenter.php | 4 +- .../markdown-builders/intro-builder.php | 2 +- .../markdown-builders/link-lists-builder.php | 2 +- .../content-types/content-type-entry.php | 4 +- .../domain/markdown/sections/intro.php | 4 +- .../file/wordpress-file-system-adapter.php | 2 +- .../markdown-services/terms-collector.php | 2 +- .../user-interface/available-posts-route.php | 6 +- ...lure-llms-txt-notification-integration.php | 2 +- .../health-check/file-reports.php | 4 +- .../llms-txt-cron-callback-integration.php | 2 +- src/loader.php | 4 +- src/main.php | 2 +- src/memoizers/meta-tags-context-memoizer.php | 2 +- src/memoizers/presentation-memoizer.php | 2 +- src/models/indexable-extension.php | 4 +- .../upgrade-sidebar-menu-integration.php | 2 +- .../indexable-post-type-presentation.php | 2 +- .../abstract-indexable-tag-presenter.php | 2 +- src/presenters/admin/badge-presenter.php | 4 +- src/presenters/admin/beta-badge-presenter.php | 4 +- src/presenters/admin/help-link-presenter.php | 2 +- .../admin/indexing-error-presenter.php | 10 +- ...indexing-failed-notification-presenter.php | 8 +- .../admin/indexing-list-item-presenter.php | 2 +- .../admin/indexing-notification-presenter.php | 4 +- .../admin/light-switch-presenter.php | 4 +- .../admin/migration-error-presenter.php | 12 +- src/presenters/admin/notice-presenter.php | 2 +- .../admin/premium-badge-presenter.php | 4 +- .../search-engines-discouraged-presenter.php | 4 +- .../woocommerce-beta-editor-presenter.php | 4 +- .../debug/marker-close-presenter.php | 2 +- .../debug/marker-open-presenter.php | 2 +- src/presenters/meta-description-presenter.php | 2 +- src/presenters/open-graph/image-presenter.php | 2 +- src/presenters/score-icon-presenter.php | 2 +- .../domain/black-friday-promotion.php | 2 +- .../indexable-cleanup-repository.php | 34 +- .../indexable-hierarchy-repository.php | 2 +- src/repositories/indexable-repository.php | 4 +- src/repositories/seo-links-repository.php | 2 +- src/routes/abstract-action-route.php | 2 +- src/routes/alert-dismissal-route.php | 2 +- src/routes/first-time-configuration-route.php | 2 +- src/routes/importing-route.php | 10 +- src/routes/indexing-route.php | 2 +- src/routes/integrations-route.php | 2 +- src/routes/semrush-route.php | 2 +- src/routes/supported-features-route.php | 2 +- src/routes/workouts-route.php | 4 +- .../configuration/schema-configuration.php | 2 +- .../health-check/default-tagline-reports.php | 2 +- .../health-check/links-table-reports.php | 6 +- .../health-check/page-comments-reports.php | 2 +- .../postname-permalink-reports.php | 4 +- src/services/health-check/report-builder.php | 2 +- .../aioseo/aioseo-replacevar-service.php | 4 +- .../aioseo-social-images-provider-service.php | 2 +- .../importing/importable-detector-service.php | 2 +- src/surfaces/meta-surface.php | 16 +- .../application/tasks/complete-ftc.php | 2 +- .../application/tasks/create-new-content.php | 6 +- .../application/tasks/delete-hello-world.php | 6 +- .../application/tasks/enable-llms-txt.php | 4 +- .../tasks/set-search-appearance-templates.php | 6 +- .../tasks-collectors/tasks-collector.php | 6 +- .../tasks/complete-task-route.php | 6 +- .../user-interface/tasks/get-tasks-route.php | 6 +- .../infrastructure/tracking-link-adapter.php | 2 +- .../user-interface/action-tracking-route.php | 6 +- .../application/custom-meta-collector.php | 2 +- .../infrastructure/cleanup-repository.php | 2 +- .../user-interface/cleanup-integration.php | 2 +- src/values/oauth/oauth-token.php | 2 +- src/wrappers/wp-remote-handler.php | 2 +- .../Constructor_Test.php | 4 +- .../Code_Verifier_Handler/Generate_Test.php | 2 +- .../Token_Manager/Constructor_Test.php | 16 +- .../Get_Or_Request_Access_Token_Test.php | 50 +-- .../Token_Manager/Has_Token_Expired_Test.php | 6 +- .../Token_Manager/Token_Invalidate_Test.php | 16 +- .../Token_Manager/Token_Refresh_Test.php | 24 +- .../Token_Manager/Token_Request_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Store_Token_Test.php | 2 +- .../Constructor_Test.php | 4 +- .../Store_Code_Verifier_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Store_Token_Test.php | 2 +- .../Abstract_Callback_Route_Test.php | 2 +- .../Callback_Route/Callback_Test.php | 2 +- .../Callback_Route/Constructor_Test.php | 6 +- .../Callback_Route/Register_Routes_Test.php | 2 +- .../Abstract_Refresh_Callback_Route_Test.php | 2 +- .../Register_Routes_Test.php | 2 +- .../Consent_Handler/Constructor_Test.php | 2 +- .../Constructor_Test.php | 6 +- .../Enqueue_Assets_Test.php | 2 +- .../Consent_Route/Constructor_Test.php | 2 +- .../Consent_Route/Register_Routes_Test.php | 2 +- .../Free_Sparks_Handler/Constructor_Test.php | 2 +- .../Free_Sparks_Route/Constructor_Test.php | 2 +- .../Register_Routes_Test.php | 2 +- .../Abstract_Suggestions_Provider_Test.php | 2 +- .../Suggestions_Provider/Constructor_Test.php | 8 +- .../Get_Suggestions_Test.php | 6 +- .../WordPress_URLs/Get_License_Url_Test.php | 2 +- ...Abstract_AI_Generator_Integration_Test.php | 2 +- .../Constructor_Test.php | 14 +- .../Enqueue_Assets_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Register_Routes_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Get_Suggestions_Test.php | 8 +- .../Register_Routes_Test.php | 2 +- .../Abstract_Get_Usage_Route_Test.php | 2 +- .../Get_Usage_Route/Constructor_Test.php | 6 +- .../Get_Usage_Route/Get_Usage_Test.php | 4 +- .../Get_Usage_Route/Register_Routes_Test.php | 2 +- .../Abstract_Request_Handler_Test.php | 2 +- .../Request_Handler/Constructor_Test.php | 4 +- .../API_Client/Perform_Request_Get_Test.php | 4 +- .../API_Client/Perform_Request_Post_Test.php | 4 +- .../Actions/Alert_Dismissal_Action_Test.php | 14 +- .../First_Time_Configuration_Action_Test.php | 18 +- .../Abstract_Aioseo_Importing_Action_Test.php | 2 +- ..._Aioseo_Settings_Importing_Action_Test.php | 4 +- .../Importing/Aioseo_Cleanup_Action_Test.php | 10 +- ...Archive_Settings_Importing_Action_Test.php | 2 +- ...Archive_Settings_Importing_Action_Test.php | 2 +- ...General_Settings_Importing_Action_Test.php | 2 +- .../Aioseo_Posts_Importing_Action_Test.php | 18 +- ...efaults_Settings_Importing_Action_Test.php | 2 +- ...axonomy_Settings_Importing_Action_Test.php | 2 +- .../Aioseo_Validate_Data_Action_Test.php | 2 +- ...tivate_Conflicting_Plugins_Action_Test.php | 2 +- .../Indexables/Indexable_Head_Action_Test.php | 14 +- .../Abstract_Link_Indexing_Action_Test.php | 10 +- ...ndexable_Indexing_Complete_Action_Test.php | 4 +- .../Indexable_Post_Indexation_Action_Test.php | 8 +- ...st_Type_Archive_Indexation_Action_Test.php | 2 +- .../Indexable_Term_Indexation_Action_Test.php | 10 +- .../Indexing_Complete_Action_Test.php | 2 +- .../Post_Link_Indexing_Action_Test.php | 6 +- .../Term_Link_Indexing_Action_Test.php | 6 +- .../SEMrush/SEMrush_Login_Action_Test.php | 14 +- .../SEMrush/SEMrush_Options_Action_Test.php | 6 +- .../SEMrush/SEMrush_Phrases_Action_Test.php | 8 +- .../Wincher/Wincher_Account_Action_Test.php | 36 +-- .../Wincher_Keyphrases_Action_Test.php | 86 ++--- .../Wincher/Wincher_Login_Action_Test.php | 18 +- tests/Unit/Admin/Admin_Features_Test.php | 2 +- .../Capabilities/Capabilities_Utils_Test.php | 4 +- ...enberg_Compatibility_Notification_Test.php | 6 +- .../Import/Plugins/Import_AIOSEO_V4_Test.php | 26 +- .../Admin/Import/Plugins/Importers_Test.php | 2 +- tests/Unit/Admin/Input_Validation_Test.php | 8 +- .../Metabox_Collapsibles_Sections_Test.php | 8 +- .../Admin/Metabox/Metabox_Editor_Test.php | 2 +- .../Metabox_Section_Additional_Test.php | 4 +- tests/Unit/Admin/Metabox/Metabox_Test.php | 6 +- tests/Unit/Admin/MyYoast_Proxy_Test.php | 4 +- tests/Unit/Admin/Plugin_Availability_Test.php | 8 +- .../Suggested_Plugins_Construct_Test.php | 4 +- .../Suggested_Plugins_Register_Hooks_Test.php | 8 +- tests/Unit/Admin/Tracking/Tracking_Test.php | 6 +- .../Unit/Admin/Views/Feature_Toggles_Test.php | 4 +- .../Abstract_Default_SEO_Data_Alert_Test.php | 2 +- ..._SEO_Data_Alert_Add_Notifications_Test.php | 2 +- ...efault_SEO_Data_Alert_Constructor_Test.php | 12 +- ...ult_SEO_Data_Alert_Register_Hooks_Test.php | 4 +- ...stract_Default_SEO_Data_Collector_Test.php | 2 +- ...efault_SEO_Data_Alert_Constructor_Test.php | 2 +- ...EO_Data_Cron_Callback_Integration_Test.php | 2 +- ..._Callback_Integration_Constructor_Test.php | 6 +- ...hedule_Default_SEO_Data_Detection_Test.php | 2 +- ...hedule_Default_SEO_Data_Detection_Test.php | 2 +- ...Abstract_Default_SEO_Data_Watcher_Test.php | 2 +- ...ault_SEO_Data_Watcher_Constructor_Test.php | 4 +- .../Missing_Indexables_Collector_Test.php | 2 +- ...o_Be_Cleaned_Indexables_Collector_Test.php | 2 +- .../Domain/Missing_Indexable_Bucket_Test.php | 2 +- .../Domain/Missing_Indexable_Count_Test.php | 2 +- .../To_Be_Cleaned_Indexable_Bucket_Test.php | 2 +- .../To_Be_Cleaned_Indexable_Count_Test.php | 2 +- ..._Completed_Indexation_Integration_Test.php | 2 +- .../Indexable_Author_Builder_Test.php | 18 +- .../Abstract_Indexable_Builder_TestCase.php | 2 +- .../Builders/Indexable_Builder/Build_Test.php | 6 +- .../Ensure_Indexable_Test.php | 2 +- .../Is_Type_With_No_Id_Test.php | 2 +- .../Maybe_Build_Author_Indexable_Test.php | 2 +- .../Indexable_Builder/Save_Indexable_Test.php | 2 +- .../Set_Indexable_Repository_Test.php | 26 +- .../Indexable_Hierarchy_Builder_Test.php | 86 ++--- .../Indexable_Home_Page_Builder_Test.php | 16 +- ...stract_Indexable_Link_Builder_TestCase.php | 8 +- .../Indexable_Link_Builder/Build_Test.php | 10 +- .../Create_Internal_Link_Test.php | 10 +- .../Indexable_Link_Builder/Delete_Test.php | 2 +- .../Get_Permalink_Test.php | 2 +- ...Update_Incoming_Links_For_Related_Test.php | 2 +- .../Builders/Indexable_Post_Builder_Test.php | 22 +- ...dexable_Post_Type_Archive_Builder_Test.php | 4 +- .../Indexable_Social_Image_Trait_Test.php | 12 +- .../Builders/Indexable_Term_Builder_Test.php | 16 +- .../Builders/Primary_Term_Builder_Test.php | 14 +- tests/Unit/Commands/Index_Command_Test.php | 20 +- ...stimated_Reading_Time_Conditional_Test.php | 2 +- .../Admin/Yoast_Admin_Conditional_Test.php | 2 +- ..._Redirections_Enabled_Conditional_Test.php | 2 +- ...est_Endpoints_Enabled_Conditional_Test.php | 2 +- .../Non_Multisite_Conditional_Test.php | 4 +- .../Robots_Txt_Conditional_Test.php | 6 +- .../Should_Index_Links_Conditional_Test.php | 2 +- ...r_Automatically_Track_Conditional_Test.php | 2 +- .../Conditionals/Wincher_Conditional_Test.php | 4 +- .../Wincher_Enabled_Conditional_Test.php | 2 +- .../Wincher_Token_Conditional_Test.php | 2 +- tests/Unit/Config/Badge_Group_Names_Test.php | 12 +- tests/Unit/Config/OAuth_Client_Test.php | 128 ++++---- tests/Unit/Config/SEMrush_Client_Test.php | 20 +- tests/Unit/Config/Wincher_Client_Test.php | 12 +- ..._Visibility_Dismiss_Notifications_Test.php | 2 +- ...t_Type_Visibility_Watcher_Actions_Test.php | 10 +- ...Type_Visibility_Dismiss_New_Route_Test.php | 10 +- tests/Unit/Context/Meta_Tags_Context_Test.php | 4 +- .../Abstract_Dashboard_Configuration_Test.php | 2 +- ...shboard_Configuration_Constructor_Test.php | 18 +- ...d_Configuration_Get_Configuration_Test.php | 2 +- .../Abstract_Setup_Steps_Tracking_Test.php | 2 +- .../Setup_Steps_Tracking_Constructor_Test.php | 2 +- ...e_Configuration_Get_Configuration_Test.php | 2 +- ...figuration_Repository_Constructor_Test.php | 2 +- ...it_Consent_Repository_Constructor_Test.php | 2 +- .../Readability_Scores_Endpoint_Test.php | 2 +- .../Endpoints/SEO_Scores_Endpoint_Test.php | 2 +- ..._Configuration_Dismissal_Endpoint_Test.php | 2 +- ...e_Kit_Consent_Management_Endpoint_Test.php | 2 +- .../Time_Based_SEO_Metrics_Endpoint_Test.php | 2 +- .../Integrations/Site_Kit_To_Array_Test.php | 4 +- ...w_Link_Score_Group_Link_Collector_Test.php | 6 +- ...s_Tracking_Repository_Constructor_Test.php | 2 +- ...uration_Permanent_Dismissal_Route_Test.php | 2 +- ...Site_Kit_Consent_Management_Route_Test.php | 2 +- .../Set_Site_Kit_Consent_Test.php | 4 +- .../Set_Site_Kit_Permanent_Dismissal_Test.php | 4 +- ...anent_Dismissal_Route_Constructor_Test.php | 2 +- ...t_Dismissal_Route_Register_Routes_Test.php | 2 +- ...sent_Management_Route_Constructor_Test.php | 2 +- ..._Management_Route_Register_Routes_Test.php | 2 +- .../Abstract_Setup_Url_Interceptor_Test.php | 2 +- ...etup_Flow_Interceptor_Constructor_Test.php | 4 +- ...p_Flow_Interceptor_Register_Hooks_Test.php | 4 +- ...Url_Interceptor_Add_Redirect_Page_Test.php | 2 +- ...Setup_Url_Interceptor_Constructor_Test.php | 6 +- ...up_Url_Interceptor_Register_Hooks_Test.php | 8 +- ...ract_Time_Based_SEO_Metrics_Route_Test.php | 2 +- ...sed_SEO_Metrics_Route_Constructor_Test.php | 10 +- ...sed_SEO_Metrics_Route_Get_Metrics_Test.php | 24 +- ...SEO_Metrics_Route_Register_Routes_Test.php | 2 +- ...stract_Setup_Steps_Tracking_Route_Test.php | 2 +- ..._Steps_Tracking_Route_Constructor_Test.php | 2 +- ...ps_Tracking_Route_Register_Routes_Test.php | 2 +- ...Track_Setup_Steps_No_Valid_Params_Test.php | 2 +- .../Track_Setup_Steps_Set_Data_Fails_Test.php | 6 +- ...p_Steps_Set_Data_Throws_Exception_Test.php | 4 +- .../Tracking/Track_Setup_Steps_Test.php | 4 +- tests/Unit/Database/Migration_Runner_Test.php | 2 +- tests/Unit/Database/Migration_Status_Test.php | 6 +- .../Analysis_Features_List_Test.php | 4 +- .../Editors/Domain/Seo/Description_Test.php | 4 +- .../Editors/Domain/Seo/Keyphrase_Test.php | 4 +- tests/Unit/Editors/Domain/Seo/Social_Test.php | 4 +- tests/Unit/Editors/Domain/Seo/Title_Test.php | 4 +- .../Framework/Integrations/Semrush_Test.php | 4 +- .../Framework/Integrations/Wincher_Test.php | 2 +- .../Infrastructure/Request_Post_Test.php | 20 +- .../Aioseo_Validation_Exception_Test.php | 2 +- .../Indexable/Invalid_Term_Exception_Test.php | 2 +- .../Post_Not_Found_Exception_Test.php | 2 +- .../Term_Not_Found_Exception_Test.php | 2 +- .../General_Page_Integration_Test.php | 12 +- .../Opt_In_Route/Constructor_Test.php | 4 +- .../Opt_In_Route/Get_Conditional_Test.php | 2 +- .../Opt_In_Route/Register_Routes_Test.php | 2 +- .../Generators/Breadcrumbs_Generator_Test.php | 4 +- .../Open_Graph_Image_Generator_Test.php | 6 +- tests/Unit/Generators/Schema/Article_Test.php | 2 +- tests/Unit/Generators/Schema/Author_Test.php | 4 +- tests/Unit/Generators/Schema/HowTo_Test.php | 10 +- .../Generators/Schema/Organization_Test.php | 2 +- tests/Unit/Generators/Schema/Person_Test.php | 2 +- tests/Unit/Generators/Schema/WebPage_Test.php | 18 +- tests/Unit/Generators/Schema/Website_Test.php | 4 +- .../Unit/Generators/Schema_Generator_Test.php | 28 +- .../Twitter_Image_Generator_Test.php | 2 +- tests/Unit/Helpers/Aioseo_Helper_Test.php | 2 +- tests/Unit/Helpers/Blocks_Helper_Test.php | 4 +- tests/Unit/Helpers/Capability_Helper_Test.php | 4 +- .../Helpers/Crawl_Cleanup_Helper_Test.php | 12 +- .../Unit/Helpers/Current_Page_Helper_Test.php | 2 +- tests/Unit/Helpers/Date_Helper_Test.php | 10 +- tests/Unit/Helpers/Home_Url_Helper_Test.php | 6 +- tests/Unit/Helpers/Image_Helper_Test.php | 16 +- .../Helpers/Import_Cursor_Helper_Test.php | 4 +- tests/Unit/Helpers/Indexable_Helper_Test.php | 14 +- tests/Unit/Helpers/Indexing_Helper_Test.php | 24 +- tests/Unit/Helpers/Options_Helper_Test.php | 2 +- tests/Unit/Helpers/Pagination_Helper_Test.php | 6 +- tests/Unit/Helpers/Permalink_Helper_Test.php | 20 +- .../Unit/Helpers/Primary_Term_Helper_Test.php | 4 +- tests/Unit/Helpers/Robots_Helper_Test.php | 12 +- tests/Unit/Helpers/Robots_Txt_Helper_Test.php | 4 +- tests/Unit/Helpers/Schema/ID_Helper_Test.php | 4 +- .../Unit/Helpers/Schema/Image_Helper_Test.php | 20 +- .../Helpers/Schema/Language_Helper_Test.php | 2 +- .../Schema/Replace_Vars_Helper_Test.php | 8 +- tests/Unit/Helpers/Score_Icon_Helper_Test.php | 2 +- tests/Unit/Helpers/Short_Link_Helper_Test.php | 2 +- tests/Unit/Helpers/Site_Helper_Test.php | 2 +- .../Helpers/Social_Profiles_Helper_Test.php | 2 +- tests/Unit/Helpers/Url_Helper_Test.php | 14 +- tests/Unit/Helpers/Wincher_Helper_Test.php | 4 +- tests/Unit/Inc/Addon_Manager_Test.php | 82 +++-- tests/Unit/Inc/Options/Option_Social_Test.php | 10 +- .../Unit/Inc/Sitemaps/Sitemaps_Admin_Test.php | 4 +- .../Inc/Sitemaps/Sitemaps_Router_Test.php | 2 +- .../Crawl_Cleanup_Permalinks_Test.php | 2 +- .../Integrations/Academy_Integration_Test.php | 10 +- .../Activation_Cleanup_Integration_Test.php | 2 +- .../Background_Indexing_Integration_Test.php | 22 +- .../Admin/Crawl_Settings_Integration_Test.php | 2 +- .../Admin/Cron_Integration_Test.php | 8 +- .../Deactivated_Premium_Integration_Test.php | 2 +- ..._Configuration_Notice_Integration_Test.php | 4 +- .../Admin/Import_Integration_Test.php | 8 +- ...Indexing_Notification_Integration_Test.php | 22 +- .../Admin/Indexing_Tool_Integration_Test.php | 20 +- .../Installation_Success_Integration_Test.php | 22 +- .../Integrations_Page_Integration_Test.php | 6 +- .../Migration_Error_Integration_Test.php | 4 +- .../Old_Configuration_Integration_Test.php | 12 +- .../Admin/Redirect_Integration_Test.php | 2 +- .../Admin/Redirects_Page_Integration_Test.php | 8 +- .../Blocks/Block_Editor_Integration_Test.php | 4 +- .../Blocks/Structured_Data_Blocks_Test.php | 14 +- .../Breadcrumbs_Integration_Test.php | 2 +- .../Integrations/Cleanup_Integration_Test.php | 2 +- .../Estimated_Reading_Time_Test.php | 4 +- .../Feature_Flag_Integration_Test.php | 6 +- .../Category_Term_Description_Test.php | 4 +- .../Front_End/Comment_Link_Fixer_Test.php | 2 +- .../Front_End/Crawl_Cleanup_Basic_Test.php | 2 +- .../Front_End/Crawl_Cleanup_Rss_Test.php | 2 +- .../Front_End/Crawl_Cleanup_Searches_Test.php | 6 +- .../Front_End/Force_Rewrite_Title_Test.php | 2 +- .../Front_End/Handle_404_Test.php | 2 +- .../Front_End/Indexing_Controls_Test.php | 4 +- .../Front_End/Open_Graph_OEmbed_Test.php | 2 +- .../Front_End/RSS_Footer_Embed_Test.php | 18 +- .../Integrations/Front_End/Redirects_Test.php | 2 +- .../Front_End/Robots_Txt_Integration_Test.php | 14 +- .../Front_End/WP_Robots_Integration_Test.php | 30 +- .../Front_End_Integration_Test.php | 22 +- .../Settings_Integration_Test.php | 42 +-- .../Integrations/Support_Integration_Test.php | 8 +- .../Integrations/Third_Party/AMP_Test.php | 2 +- .../Integrations/Third_Party/BbPress_Test.php | 2 +- .../Exclude_Elementor_Post_Types_Test.php | 2 +- .../Exclude_WooCommerce_Post_Types_Test.php | 2 +- .../Integrations/Third_Party/Jetpack_Test.php | 2 +- .../Integrations/Third_Party/WPML_Test.php | 2 +- .../WPML_WPSEO_Notification_Test.php | 8 +- .../Web_Stories_Post_Edit_Test.php | 2 +- .../Third_Party/Web_Stories_Test.php | 4 +- .../Third_Party/Wincher_Publish_Test.php | 18 +- .../WooCommerce_Permalinks_Test.php | 8 +- .../WooCommerce_Post_Edit_Test.php | 6 +- .../Third_Party/WooCommerce_Test.php | 18 +- .../Watchers/Addon_Update_Watcher_Test.php | 22 +- .../Watchers/Auto_Update_Watcher_Test.php | 4 +- .../Indexable_Ancestor_Watcher_Test.php | 22 +- .../Indexable_Attachment_Watcher_Test.php | 2 +- .../Indexable_Author_Watcher_Test.php | 4 +- ...exable_Category_Permalink_Watcher_Test.php | 4 +- .../Indexable_Date_Archive_Watcher_Test.php | 2 +- .../Indexable_HomeUrl_Watcher_Test.php | 4 +- .../Indexable_Home_Page_Watcher_Test.php | 4 +- .../Indexable_Permalink_Watcher_Test.php | 16 +- .../Indexable_Post_Meta_Watcher_Test.php | 2 +- ...dexable_Post_Type_Archive_Watcher_Test.php | 4 +- ...ndexable_Post_Type_Change_Watcher_Test.php | 4 +- .../Watchers/Indexable_Post_Watcher_Test.php | 12 +- ...ndexable_Static_Home_Page_Watcher_Test.php | 2 +- .../Indexable_System_Page_Watcher_Test.php | 4 +- ...Indexable_Taxonomy_Change_Watcher_Test.php | 4 +- .../Watchers/Indexable_Term_Watcher_Test.php | 8 +- .../Watchers/Option_Titles_Watcher_Test.php | 18 +- ...imary_Category_Quick_Edit_Watcher_Test.php | 4 +- .../Watchers/Primary_Term_Watcher_Test.php | 4 +- ...earch_Engines_Discouraged_Watcher_Test.php | 12 +- .../Woocommerce_Beta_Editor_Watcher_Test.php | 8 +- ...ct_Category_Permalink_Integration_Test.php | 10 +- .../AI_Brand_Insights_Post_Launch_Test.php | 2 +- .../Ai_Fix_Assessments_Upsell_Test.php | 4 +- .../Black_Friday_Announcement_Test.php | 8 +- .../Google_Docs_Addon_Upsell_Test.php | 6 +- .../Domain/Introduction_Item_Test.php | 2 +- .../Domain/Introductions_Bucket_Test.php | 2 +- .../Introductions_Seen_Repository_Test.php | 16 +- ...istia_Embed_Permission_Repository_Test.php | 2 +- .../Introductions_Integration_Test.php | 18 +- .../Introductions_Seen_Route_Test.php | 28 +- .../Wistia_Embed_Permission_Route_Test.php | 22 +- .../Abstract_Llms_Txt_Configuration_Test.php | 2 +- ...lms_Txt_Configuration_Constructor_Test.php | 6 +- ...act_Populate_File_Command_Handler_Test.php | 2 +- .../Populate_File/Constructor_Test.php | 8 +- ...tract_Remove_File_Command_Handler_Test.php | 2 +- .../Commands/Remove_File/Constructor_Test.php | 6 +- .../Constructor_Test.php | 2 +- .../Abstract_Description_Builder_Test.php | 2 +- .../Description_Builder/Constructor_Test.php | 2 +- .../Intro_Builder/Build_Intro_Test.php | 2 +- .../Abstract_Link_Lists_Builder_Test.php | 2 +- .../Link_Lists_Builder/Constructor_Test.php | 4 +- .../Abstract_Markdown_Builder_Test.php | 2 +- .../Markdown_Builder/Constructor_Test.php | 14 +- .../Markdown_Builder/Render_Test.php | 2 +- ...stract_Optional_Link_List_Builder_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Abstract_Title_Builder_Test.php | 2 +- .../Title_Builder/Constructor_Test.php | 2 +- .../Abstract_Content_Types_Collector_Test.php | 2 +- .../Constructor_Test.php | 6 +- .../Abstract_Description_Adapter_Test.php | 2 +- .../Description_Adapter/Constructor_Test.php | 2 +- .../Abstract_Terms_Collector_Test.php | 2 +- .../Terms_Collector/Constructor_Test.php | 2 +- .../Abstract_Title_Adapter_Test.php | 2 +- .../Title_Adapter/Constructor_Test.php | 2 +- .../Abstract_Available_Posts_Route_Test.php | 2 +- ...Available_Posts_Route_Constructor_Test.php | 4 +- .../Available_Posts_Route_Get_Posts_Test.php | 6 +- ...lable_Posts_Route_Register_Routes_Test.php | 2 +- ..._Cleanup_Llms_Txt_On_Deactivation_Test.php | 2 +- .../Constructor_Test.php | 4 +- .../Register_Hooks_Test.php | 4 +- ...ct_Enable_Llms_Txt_Option_Watcher_Test.php | 2 +- .../Constructor_Test.php | 6 +- .../Register_Hooks_Test.php | 4 +- ...Llms_Txt_Notification_Integration_Test.php | 2 +- .../Constructor_Test.php | 6 +- .../Register_Hooks_Test.php | 4 +- ...lms_Txt_Cron_Callback_Integration_Test.php | 2 +- .../Constructor_Test.php | 8 +- .../Register_Hooks_Test.php | 4 +- ...ulation_On_Activation_Integration_Test.php | 2 +- .../Constructor_Test.php | 4 +- .../Register_Hooks_Test.php | 4 +- .../Meta_Tags_Context_Memoizer_Test.php | 12 +- .../Memoizers/Presentation_Memoizer_Test.php | 2 +- tests/Unit/Models/Indexable_Test.php | 4 +- .../Application/Add_Ons_Collector_Test.php | 2 +- .../Plans_Page_Integration_Test.php | 6 +- .../Presentation_Instance_Builder.php | 2 +- .../Canonical_Test.php | 8 +- .../Presentation_Instance_Builder.php | 4 +- .../Twitter_Image_Test.php | 2 +- .../Presentation_Instance_Builder.php | 2 +- .../Indexable_Presentation/Robots_Test.php | 10 +- .../Canonical_Test.php | 8 +- .../Presentation_Instance_Builder.php | 4 +- .../Presentation_Instance_Builder.php | 2 +- .../Presentation_Instance_Builder.php | 2 +- .../Presentation_Instance_Dependencies.php | 8 +- .../Presenters/Admin/Alert_Presenter_Test.php | 2 +- .../Admin/Help_Link_Presenter_Test.php | 2 +- .../Admin/Indexing_Error_Presenter_Test.php | 14 +- .../Indexing_Notification_Presenter_Test.php | 6 +- .../Admin/Migration_Error_Presenter_Test.php | 2 +- .../Admin/Notice_Presenter_Test.php | 2 +- .../Presenters/Breadcrumbs_Presenter_Test.php | 20 +- .../Presenters/Canonical_Presenter_Test.php | 6 +- .../Debug/Marker_Close_Presenter_Test.php | 4 +- .../Debug/Marker_Open_Presenter_Test.php | 6 +- .../Meta_Description_Presenter_Test.php | 8 +- .../Open_Graph/Description_Presenter_Test.php | 4 +- .../Open_Graph/Image_Presenter_Test.php | 10 +- .../Open_Graph/Title_Presenter_Test.php | 10 +- .../Presenters/Rel_Next_Presenter_Test.php | 6 +- .../Presenters/Rel_Prev_Presenter_Test.php | 8 +- .../Unit/Presenters/Robots_Presenter_Test.php | 2 +- .../Presenters/Robots_Txt_Presenter_Test.php | 2 +- .../Slack/Enhanced_Data_Presenter_Test.php | 12 +- .../Unit/Presenters/Title_Presenter_Test.php | 10 +- .../Twitter/Card_Presenter_Test.php | 4 +- .../Twitter/Creator_Presenter_Test.php | 4 +- .../Twitter/Description_Presenter_Test.php | 4 +- .../Twitter/Site_Presenter_Test.php | 6 +- .../Twitter/Title_Presenter_Test.php | 8 +- .../Webmaster/Baidu_Presenter_Test.php | 10 +- .../Webmaster/Bing_Presenter_Test.php | 8 +- .../Webmaster/Google_Presenter_Test.php | 8 +- .../Webmaster/Pinterest_Presenter_Test.php | 8 +- .../Webmaster/Yandex_Presenter_Test.php | 8 +- .../Application/Fake_Expired_Promotion.php | 2 +- .../Promotions/Application/Fake_Promotion.php | 2 +- .../Indexable_Cleanup_Repository_Test.php | 30 +- .../Indexable_Hierarchy_Repository_Test.php | 8 +- .../Indexable_Repository_Test.php | 8 +- .../Routes/Alert_Dismissal_Route_Test.php | 6 +- .../First_Time_Configuration_Route_Test.php | 16 +- tests/Unit/Routes/Importing_Route_Test.php | 8 +- .../Routes/Indexables_Head_Route_Test.php | 6 +- tests/Unit/Routes/Indexing_Route_Test.php | 42 +-- tests/Unit/Routes/SEMrush_Route_Test.php | 14 +- .../Routes/Supported_Features_Route_Test.php | 6 +- tests/Unit/Routes/Wincher_Route_Test.php | 34 +- .../Routes/Yoast_Head_REST_Field_Test.php | 22 +- ...eo_Social_Images_Provider_Service_Test.php | 2 +- .../Conflicting_Plugins_Service_Test.php | 6 +- .../Importable_Detector_Service_Test.php | 16 +- .../Indexable_Version_Manager_Test.php | 2 +- tests/Unit/Surfaces/Meta_Surface_Test.php | 8 +- tests/Unit/Surfaces/Values/Meta_Test.php | 4 +- .../Abstract_Task_List_Configuration_Test.php | 2 +- ...sk_List_Configuration_Constructor_Test.php | 4 +- .../Complete_FTC_Constructor_Test.php | 2 +- .../Create_New_Content_Constructor_Test.php | 2 +- .../Enable_Llms_Txt_Constructor_Test.php | 2 +- .../Enable_Llms_Txt_Is_Valid_Test.php | 4 +- .../Tasks_Repository_Constructor_Test.php | 2 +- ..._Tasks_Integration_Register_Hooks_Test.php | 4 +- ...ached_Tasks_Collector_Constructor_Test.php | 2 +- .../Abstract_Complete_Task_Route_Test.php | 2 +- .../Complete_Task_Route_Constructor_Test.php | 6 +- ...mplete_Task_Route_Register_Routes_Test.php | 2 +- .../Abstract_Get_Tasks_Route_Test.php | 2 +- .../Get_Tasks_Route_Constructor_Test.php | 6 +- .../Get_Tasks_Route_Register_Routes_Test.php | 2 +- tests/Unit/TestCase.php | 4 +- .../Tracking_Link_Adapter_Test.php | 2 +- ...Tracking_On_Page_Load_Integration_Test.php | 2 +- .../Constructor_Test.php | 6 +- .../Abstract_Action_Tracking_Route_Test.php | 2 +- ...Action_Tracking_Route_Constructor_Test.php | 6 +- ...on_Tracking_Route_Register_Routes_Test.php | 2 +- ...ditional_Contactmethods_Collector_Test.php | 2 +- .../Application/Cleanup_Service_Test.php | 8 +- .../Custom_Meta_Collector_Test.php | 2 +- .../Custom_Meta/Author_Metadesc_Test.php | 2 +- .../Custom_Meta/Author_Title_Test.php | 2 +- .../Content_Analysis_Disable_Test.php | 2 +- ...clusive_Language_Analysis_Disable_Test.php | 2 +- .../Keyword_Analysis_Disable_Test.php | 2 +- .../Custom_Meta/Noindex_Author_Test.php | 2 +- .../Cleanup_Repository_Test.php | 6 +- ...tional_Contactmethods_Integration_Test.php | 4 +- .../Cleanup_Integration_Test.php | 4 +- .../Custom_Meta_Integration_Test.php | 4 +- .../User_Profiles_Additions_Ui_Test.php | 6 +- tests/Unit/Values/Images_Test.php | 10 +- tests/Unit/Values/OAuth/OAuth_Token_Test.php | 26 +- tests/Unit/Values/Open_Graph/Images_Test.php | 4 +- tests/Unit/bootstrap.php | 2 +- tests/WP/Admin/Asset_Manager_Test.php | 10 +- tests/WP/Admin/Database_Proxy_Test.php | 38 +-- .../Editor_Specific_Replace_Vars_Test.php | 12 +- .../Exceptions/File_Size_Exception_Test.php | 4 +- .../WP/Admin/Import/Premium_SEO_Pack_Test.php | 10 +- tests/WP/Admin/Import/RankMath_Test.php | 2 +- tests/WP/Admin/Import/Squirrly_Test.php | 10 +- tests/WP/Admin/Import/WPSEO_Test.php | 2 +- tests/WP/Admin/Input_Select_Test.php | 4 +- tests/WP/Admin/Metabox/Metabox_Test.php | 2 +- .../Admin/Recommended_Replace_Vars_Test.php | 2 +- .../Indexable_Ancestor_Watcher_Test.php | 4 +- .../Watchers/Indexable_Post_Watcher_Test.php | 8 +- .../Watchers/Slug_Change_Watcher_Test.php | 2 +- .../Indexable_Author_Builder_Test.php | 12 +- .../Indexable_Date_Archive_Builder_Test.php | 2 +- .../Indexable_Home_Page_Builder_Test.php | 8 +- ...dexable_Post_Type_Archive_Builder_Test.php | 6 +- .../Builders/Indexable_Term_Builder_Test.php | 12 +- .../Dismiss_New_Route_Test.php | 16 +- .../Filter_Pairs_Repository_Test.php | 2 +- .../Taxonomies/Taxonomies_Repository_Test.php | 6 +- .../Analytics_4_Adapter_Construct_Test.php | 2 +- ...pter_Validate_Comparison_Response_Test.php | 2 +- ...4_Adapter_Validate_Daily_Response_Test.php | 2 +- .../Is_Site_Kit_On_Boarded_Test.php | 8 +- .../Search_Console_Adapter_Construct.php | 2 +- ...pter_Validate_Comparison_Response_Test.php | 2 +- ...Console_Adapter_Validate_Response_Test.php | 2 +- ...Site_Kit_Capabilities_Integration_Test.php | 4 +- .../Readability_Scores/Get_Scores_Test.php | 4 +- .../Readability_Scores/Invalid_Term_Test.php | 2 +- .../SEO_Scores/Get_Scores_Test.php | 4 +- .../SEO_Scores/Invalid_Term_Test.php | 2 +- .../Admin/Gutenberg_Compatibility_Double.php | 4 +- .../Frontend/Front_End_Integration_Test.php | 2 +- tests/WP/Frontend/Image_Utils_Test.php | 10 +- tests/WP/Functions_Test.php | 6 +- .../User_Interface/Set_Opt_In_Seen_Test.php | 2 +- .../Generators/Schema/Organization_Test.php | 8 +- tests/WP/Generators/Schema/Person_Test.php | 8 +- tests/WP/Generators/Schema/WebPage_Test.php | 4 +- ..._Time_Configuration_Notice_Helper_Test.php | 6 +- ...et_Attachment_By_Url_Image_Helper_Test.php | 2 +- tests/WP/Inc/Admin_Bar_Menu_Test.php | 4 +- tests/WP/Inc/Meta_Test.php | 4 +- tests/WP/Inc/MyYoast_Api_Request_Test.php | 10 +- tests/WP/Inc/Options/Taxonomy_Meta_Test.php | 10 +- tests/WP/Inc/Post_Type_Test.php | 8 +- tests/WP/Inc/Rank_Test.php | 2 +- tests/WP/Inc/Upgrade_Test.php | 144 ++++----- .../Available_Posts_Repository_Test.php | 4 +- .../Automatic_Post_Collection_Test.php | 8 +- .../Yoast_Notification_Center_Test.php | 16 +- .../Notifications/Yoast_Notification_Test.php | 12 +- .../Primary_Term_Repository_Test.php | 2 +- .../SEO_Links_Repository_Test.php | 26 +- .../WP/Routes/Indexables_Head_Route_Test.php | 4 +- tests/WP/Sitemaps/Cache_Test.php | 16 +- tests/WP/Sitemaps/Cache_Validator_Test.php | 2 +- tests/WP/Sitemaps/Image_Parser_Test.php | 2 +- .../Post_Type_Sitemap_Provider_Test.php | 16 +- tests/WP/Sitemaps/Provider_Overlap_Test.php | 4 +- tests/WP/Sitemaps/Sitemaps_Test.php | 2 +- .../WP/Statistics/Statistics_Service_Test.php | 12 +- .../Taxonomy_Fields_Presenter_Test.php | 22 +- tests/WP/TestCase.php | 2 +- tests/WP/bootstrap.php | 4 +- wp-seo-main.php | 14 +- 926 files changed, 3208 insertions(+), 3274 deletions(-) diff --git a/.github/workflows/browserslist-db.yml b/.github/workflows/browserslist-db.yml index bbb37339e8c..67e8d4dd7f2 100644 --- a/.github/workflows/browserslist-db.yml +++ b/.github/workflows/browserslist-db.yml @@ -21,7 +21,7 @@ jobs: git config --global user.name "${{ github.actor }}" - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 persist-credentials: true diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a0d21ebfd60..2a38009d757 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -26,15 +26,15 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 with: languages: ${{ matrix.language }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml index 63df1f0c457..c7fe3e14b73 100644 --- a/.github/workflows/cs.yml +++ b/.github/workflows/cs.yml @@ -40,7 +40,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: true diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9334681c0c9..51f810fdcb6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -56,7 +56,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -164,7 +164,7 @@ jobs: fi - name: Checkout Yoast Dist repo - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: ${{ env.DIST_ORG }}/${{ github.event.repository.name }} ref: ${{ env.DIST_DEFAULT_BRANCH }} diff --git a/.github/workflows/deprecation-check.yml b/.github/workflows/deprecation-check.yml index 6c186ffe20e..c07c98546c1 100644 --- a/.github/workflows/deprecation-check.yml +++ b/.github/workflows/deprecation-check.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/finish-coveralls.yml b/.github/workflows/finish-coveralls.yml index 53127043f0a..663aad7ad40 100644 --- a/.github/workflows/finish-coveralls.yml +++ b/.github/workflows/finish-coveralls.yml @@ -84,7 +84,7 @@ jobs: # NOTE: The ref value should be different when triggered by pull_request event. # See: https://github.com/lewagon/wait-on-check-action/issues/25. - name: "Wait on tests (PR)" - uses: lewagon/wait-on-check-action@3603e826ee561ea102b58accb5ea55a1a7482343 # v1.4.1 + uses: lewagon/wait-on-check-action@74049309dfeff245fe8009a0137eacf28136cb3c # v1.5.0 if: github.event_name == 'pull_request' with: ref: ${{ github.event.pull_request.head.sha }} @@ -93,7 +93,7 @@ jobs: - name: "Wait on tests (push)" if: github.event_name != 'pull_request' - uses: lewagon/wait-on-check-action@3603e826ee561ea102b58accb5ea55a1a7482343 # v1.4.1 + uses: lewagon/wait-on-check-action@74049309dfeff245fe8009a0137eacf28136cb3c # v1.5.0 with: ref: ${{ github.sha }} repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/generate_csv.yml b/.github/workflows/generate_csv.yml index 4134b9b89b9..053a354a11c 100644 --- a/.github/workflows/generate_csv.yml +++ b/.github/workflows/generate_csv.yml @@ -11,7 +11,7 @@ jobs: steps: # Check out the repository - name: Check out repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/jslint.yml b/.github/workflows/jslint.yml index fea9d465117..b02783e614c 100644 --- a/.github/workflows/jslint.yml +++ b/.github/workflows/jslint.yml @@ -57,7 +57,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/jstest.yml b/.github/workflows/jstest.yml index 954fa155f72..68654e499e1 100644 --- a/.github/workflows/jstest.yml +++ b/.github/workflows/jstest.yml @@ -77,7 +77,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -148,7 +148,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -169,7 +169,7 @@ jobs: # Check out the premium config repo ahead of running the tests to prevent issues with permissions. - name: Checkout premium configuration if: ${{ steps.checks-run.outputs.should == 'true' && matrix.needs_premium_config == true }} - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: Yoast/YoastSEO.js-premium-configuration path: packages/yoastseo/premium-configuration diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 90bb3dfb35e..22ec8ea2ca5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -43,7 +43,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index d56d09f4a27..4c7abb21e57 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 402de5dde47..cd6a9d56b26 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -61,7 +61,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -198,7 +198,7 @@ jobs: run: sudo apt-get install -y subversion - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/admin/ajax.php b/admin/ajax.php index 260ccda53f4..c9ac45d68e8 100644 --- a/admin/ajax.php +++ b/admin/ajax.php @@ -144,7 +144,7 @@ function wpseo_save_what( $what ) { */ function wpseo_upsert_meta( $post_id, $new_meta_value, $orig_meta_value, $meta_key, $return_key ) { - $post_id = intval( $post_id ); + $post_id = (int) $post_id; $sanitized_new_meta_value = wp_strip_all_tags( $new_meta_value ); $orig_meta_value = wp_strip_all_tags( $orig_meta_value ); @@ -171,7 +171,7 @@ function wpseo_upsert_meta( $post_id, $new_meta_value, $orig_meta_value, $meta_k $upsert_results['results'] = sprintf( /* translators: %s expands to post type. */ __( 'Post has an invalid Content Type: %s.', 'wordpress-seo' ), - $the_post->post_type + $the_post->post_type, ); return $upsert_results; @@ -183,7 +183,7 @@ function wpseo_upsert_meta( $post_id, $new_meta_value, $orig_meta_value, $meta_k $upsert_results['results'] = sprintf( /* translators: %s expands to post type name. */ __( 'You can\'t edit %s.', 'wordpress-seo' ), - $post_type_object->label + $post_type_object->label, ); return $upsert_results; @@ -195,7 +195,7 @@ function wpseo_upsert_meta( $post_id, $new_meta_value, $orig_meta_value, $meta_k $upsert_results['results'] = sprintf( /* translators: %s expands to the name of a post type (plural). */ __( 'You can\'t edit %s that aren\'t yours.', 'wordpress-seo' ), - $post_type_object->label + $post_type_object->label, ); return $upsert_results; @@ -310,7 +310,7 @@ function ajax_get_keyword_usage_and_post_types() { wp_die( // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe. - WPSEO_Utils::format_json_encode( $return_object ) + WPSEO_Utils::format_json_encode( $return_object ), ); } @@ -355,7 +355,7 @@ function ajax_get_term_keyword_usage() { wp_die( // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe. - WPSEO_Utils::format_json_encode( $usage ) + WPSEO_Utils::format_json_encode( $usage ), ); } @@ -406,6 +406,6 @@ function ajax_get_keyword_usage() { wp_die( // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe. - WPSEO_Utils::format_json_encode( WPSEO_Meta::keyword_usage( $keyword, $post_id ) ) + WPSEO_Utils::format_json_encode( WPSEO_Meta::keyword_usage( $keyword, $post_id ) ), ); } diff --git a/admin/class-admin-asset-analysis-worker-location.php b/admin/class-admin-asset-analysis-worker-location.php index cb980ad1ca6..478f0a831e6 100644 --- a/admin/class-admin-asset-analysis-worker-location.php +++ b/admin/class-admin-asset-analysis-worker-location.php @@ -43,7 +43,7 @@ public function __construct( $flat_version = '', $name = 'analysis-worker' ) { [ 'name' => $name, 'src' => $analysis_worker, - ] + ], ); } diff --git a/admin/class-admin-asset-dev-server-location.php b/admin/class-admin-asset-dev-server-location.php index cf67ae74f78..ac3018ace1f 100644 --- a/admin/class-admin-asset-dev-server-location.php +++ b/admin/class-admin-asset-dev-server-location.php @@ -30,9 +30,7 @@ final class WPSEO_Admin_Asset_Dev_Server_Location implements WPSEO_Admin_Asset_L * @param string|null $url Where the dev server is located. */ public function __construct( $url = null ) { - if ( $url === null ) { - $url = self::DEFAULT_URL; - } + $url ??= self::DEFAULT_URL; $this->url = $url; } diff --git a/admin/class-admin-asset-manager.php b/admin/class-admin-asset-manager.php index 4fbe131698e..09485b39176 100644 --- a/admin/class-admin-asset-manager.php +++ b/admin/class-admin-asset-manager.php @@ -41,9 +41,7 @@ class WPSEO_Admin_Asset_Manager { * @param string $prefix The prefix for naming assets. */ public function __construct( ?WPSEO_Admin_Asset_Location $asset_location = null, $prefix = self::PREFIX ) { - if ( $asset_location === null ) { - $asset_location = self::create_default_location(); - } + $asset_location ??= self::create_default_location(); $this->asset_location = $asset_location; $this->prefix = $prefix; @@ -102,7 +100,7 @@ public function register_script( WPSEO_Admin_Asset $script ) { $url, $script->get_deps(), $script->get_version(), - $args + $args, ); if ( in_array( 'wp-i18n', $script->get_deps(), true ) ) { @@ -123,7 +121,7 @@ public function register_style( WPSEO_Admin_Asset $style ) { $this->get_url( $style, WPSEO_Admin_Asset::TYPE_CSS ), $style->get_deps(), $style->get_version(), - $style->get_media() + $style->get_media(), ); } @@ -348,7 +346,7 @@ protected function scripts_to_be_registered() { 'ext_length' => 3, 'additional_deps' => $additional_dependencies, 'header_scripts' => $header_scripts, - ] + ], ); $external_scripts = $this->load_generated_asset_file( [ @@ -358,7 +356,7 @@ protected function scripts_to_be_registered() { 'base_dir' => 'externals/', 'additional_deps' => $additional_dependencies, 'header_scripts' => $header_scripts, - ] + ], ); $language_scripts = $this->load_generated_asset_file( [ @@ -368,7 +366,7 @@ protected function scripts_to_be_registered() { 'base_dir' => 'languages/', 'additional_deps' => $additional_dependencies, 'header_scripts' => $header_scripts, - ] + ], ); $renamed_scripts = $this->load_renamed_scripts(); @@ -376,7 +374,7 @@ protected function scripts_to_be_registered() { $plugin_scripts, $external_scripts, $language_scripts, - $renamed_scripts + $renamed_scripts, ); $scripts['installation-success'] = [ @@ -404,7 +402,7 @@ static function ( $dep ) { } return $dep; }, - $scripts['post-edit']['deps'] + $scripts['post-edit']['deps'], ), 'in_footer' => ! in_array( 'post-edit-classic', $header_scripts, true ), 'version' => $scripts['post-edit']['version'], @@ -477,7 +475,7 @@ protected function load_generated_asset_file( $args ) { 'additional_deps' => [], 'base_dir' => '', 'header_scripts' => [], - ] + ], ); $scripts = []; $assets = require $args['asset_file']; diff --git a/admin/class-admin-editor-specific-replace-vars.php b/admin/class-admin-editor-specific-replace-vars.php index 781ce099929..ffbddfa42ef 100644 --- a/admin/class-admin-editor-specific-replace-vars.php +++ b/admin/class-admin-editor-specific-replace-vars.php @@ -41,12 +41,12 @@ class WPSEO_Admin_Editor_Specific_Replace_Vars { public function __construct() { $this->add_for_page_types( [ 'page', 'post', 'custom_post_type' ], - WPSEO_Custom_Fields::get_custom_fields() + WPSEO_Custom_Fields::get_custom_fields(), ); $this->add_for_page_types( [ 'post', 'term-in-custom-taxonomy' ], - WPSEO_Custom_Taxonomies::get_custom_taxonomies() + WPSEO_Custom_Taxonomies::get_custom_taxonomies(), ); } @@ -63,7 +63,7 @@ public function get() { */ $replacement_variables = apply_filters( 'wpseo_editor_specific_replace_vars', - $this->replacement_variables + $this->replacement_variables, ); if ( ! is_array( $replacement_variables ) ) { @@ -85,7 +85,7 @@ public function get() { public function get_generic( $replacement_variables ) { $shared_variables = array_diff( $this->extract_names( $replacement_variables ), - $this->get_unique_replacement_variables() + $this->get_unique_replacement_variables(), ); return array_values( $shared_variables ); diff --git a/admin/class-admin-gutenberg-compatibility-notification.php b/admin/class-admin-gutenberg-compatibility-notification.php index 8f521de3f4a..718569a1950 100644 --- a/admin/class-admin-gutenberg-compatibility-notification.php +++ b/admin/class-admin-gutenberg-compatibility-notification.php @@ -88,7 +88,7 @@ protected function add_notification() { __( '%1$s detected you are using version %2$s of %3$s, please update to the latest version to prevent compatibility issues.', 'wordpress-seo' ), 'Yoast SEO', $this->compatibility_checker->get_installed_version(), - 'Gutenberg' + 'Gutenberg', ); $notification = new Yoast_Notification( @@ -97,7 +97,7 @@ protected function add_notification() { 'id' => $this->notification_id, 'type' => $level, 'priority' => 1, - ] + ], ); $this->notification_center->add_notification( $notification ); diff --git a/admin/class-admin-help-panel.php b/admin/class-admin-help-panel.php index 6fdb6c2f0ca..5fbb4b05c00 100644 --- a/admin/class-admin-help-panel.php +++ b/admin/class-admin-help-panel.php @@ -70,7 +70,7 @@ public function get_button_html() { return sprintf( ' ', esc_attr( $this->id ), - $this->help_button_text + $this->help_button_text, ); } @@ -98,7 +98,7 @@ public function get_panel_html() { $wrapper_start, esc_attr( $this->id ), $this->help_content, - $wrapper_end + $wrapper_end, ); } } diff --git a/admin/class-admin-init.php b/admin/class-admin-init.php index dbd3a983bc2..0856250a5c7 100644 --- a/admin/class-admin-init.php +++ b/admin/class-admin-init.php @@ -306,7 +306,7 @@ public function show_hook_deprecation_warnings() { // Determine which filters have been registered. $deprecated_notices = array_intersect( array_keys( $deprecated_filters ), - array_keys( $wp_filter ) + array_keys( $wp_filter ), ); // Show notice for each deprecated filter or action that has been registered. @@ -316,7 +316,7 @@ public function show_hook_deprecation_warnings() { _deprecated_hook( $deprecated_filter, 'WPSEO ' . $deprecation_info['version'], - $deprecation_info['alternative'] + $deprecation_info['alternative'], ); // phpcs:enable } @@ -347,11 +347,11 @@ public function permalink_settings_notice() { /* translators: %1$s and %2$s expand to items to emphasize the word in the middle. */ esc_html__( 'Changing your permalinks settings can seriously impact your search engine visibility. It should almost %1$s never %2$s be done on a live website.', 'wordpress-seo' ), '', - '' + '', ), esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/why-permalinks/' ) ), // The link's content. - esc_html__( 'Learn about why permalinks are important for SEO.', 'wordpress-seo' ) + esc_html__( 'Learn about why permalinks are important for SEO.', 'wordpress-seo' ), ); } } diff --git a/admin/class-admin-utils.php b/admin/class-admin-utils.php index 4e3baa1aa95..53966320005 100644 --- a/admin/class-admin-utils.php +++ b/admin/class-admin-utils.php @@ -24,7 +24,7 @@ public static function get_install_url( $slug ) { return wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . dirname( $slug ) ), - 'install-plugin_' . dirname( $slug ) + 'install-plugin_' . dirname( $slug ), ); } @@ -42,7 +42,7 @@ public static function get_activation_url( $slug ) { return wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin_status=all&paged=1&s&plugin=' . $slug ), - 'activate-plugin_' . $slug + 'activate-plugin_' . $slug, ); } @@ -63,7 +63,7 @@ public static function get_install_link( $plugin ) { return sprintf( '%s', $install_url, - $plugin['title'] + $plugin['title'], ); } @@ -76,7 +76,7 @@ public static function get_new_tab_message() { return sprintf( '%s', /* translators: Hidden accessibility text. */ - esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) + esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ), ); } } diff --git a/admin/class-admin.php b/admin/class-admin.php index 043ff2f3f31..825960ec56c 100644 --- a/admin/class-admin.php +++ b/admin/class-admin.php @@ -95,7 +95,7 @@ public function __construct() { $integrations = array_merge( $integrations, $this->get_admin_features(), - $this->initialize_cornerstone_content() + $this->initialize_cornerstone_content(), ); foreach ( $integrations as $integration ) { @@ -246,7 +246,7 @@ public function add_action_link( $links, $file ) { $no_deactivation_explanation = '' . sprintf( /* translators: %s expands to Yoast SEO Premium. */ __( 'Required by %s', 'wordpress-seo' ), - 'Yoast SEO Premium' + 'Yoast SEO Premium', ) . ''; array_unshift( $links, $no_deactivation_explanation ); @@ -348,14 +348,14 @@ private function localize_admin_global_script() { /* translators: %1$s: '%%term_title%%' variable used in titles and meta's template that's not compatible with the given template, %2$s: expands to 'HelpScout beacon' */ __( 'Warning: the variable %1$s cannot be used in this template. See the %2$s for more info.', 'wordpress-seo' ), '%s', - 'HelpScout beacon' + 'HelpScout beacon', ), /* translators: %s: expends to Yoast SEO */ 'help_video_iframe_title' => sprintf( __( '%s video tutorial', 'wordpress-seo' ), 'Yoast SEO' ), 'scrollable_table_hint' => __( 'Scroll to see the table content.', 'wordpress-seo' ), 'wincher_is_logged_in' => WPSEO_Options::get( 'wincher_integration_active', true ) ? YoastSEO()->helpers->wincher->login_status() : false, ], - YoastSEO()->helpers->wincher->get_admin_global_links() + YoastSEO()->helpers->wincher->get_admin_global_links(), ); } diff --git a/admin/class-bulk-description-editor-list-table.php b/admin/class-bulk-description-editor-list-table.php index 3b65304b030..0138415aa15 100644 --- a/admin/class-bulk-description-editor-list-table.php +++ b/admin/class-bulk-description-editor-list-table.php @@ -65,7 +65,7 @@ protected function parse_page_specific_column( $column_name, $record, $attribute return sprintf( '', esc_attr( 'wpseo-new-metadesc-' . $record->ID ), - esc_attr( $record->ID ) + esc_attr( $record->ID ), ); case 'col_existing_yoast_seo_metadesc': diff --git a/admin/class-bulk-editor-list-table.php b/admin/class-bulk-editor-list-table.php index 419885814d7..aa155c62db8 100644 --- a/admin/class-bulk-editor-list-table.php +++ b/admin/class-bulk-editor-list-table.php @@ -132,7 +132,7 @@ public function __construct( $args = [] ) { [ 'nonce' => '', 'input_fields' => [], - ] + ], ); $this->input_fields = $args['input_fields']; @@ -178,7 +178,7 @@ protected function populate_editable_post_types() { 'public' => true, 'exclude_from_search' => false, ], - 'object' + 'object', ); $this->all_posts = []; @@ -297,8 +297,8 @@ public function get_views() { WHERE post_status IN (" . implode( ', ', array_fill( 0, count( $states ), '%s' ) ) . ')', - $states - ) + $states, + ), ); $post_status = isset( $_GET['post_status'] ) && is_string( $_GET['post_status'] ) ? sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) : ''; @@ -306,7 +306,7 @@ public function get_views() { $localized_text = sprintf( /* translators: %s expands to the number of posts in localized format. */ _nx( 'All (%s)', 'All (%s)', $total_posts, 'posts', 'wordpress-seo' ), - number_format_i18n( $total_posts ) + number_format_i18n( $total_posts ), ); $status_links['all'] = '' . $localized_text . ''; @@ -323,8 +323,8 @@ public function get_views() { SELECT COUNT(ID) FROM {$subquery} WHERE post_status = %s ", - $status_name - ) + $status_name, + ), ); if ( $total === 0 ) { @@ -344,7 +344,7 @@ public function get_views() { $trashed_posts = $wpdb->get_var( "SELECT COUNT(ID) FROM {$subquery} WHERE post_status IN ('trash') - " + ", ); $current_link_attributes = ''; @@ -355,7 +355,7 @@ public function get_views() { $localized_text = sprintf( /* translators: %s expands to the number of trashed posts in localized format. */ _nx( 'Trash (%s)', 'Trash (%s)', $trashed_posts, 'posts', 'wordpress-seo' ), - number_format_i18n( $trashed_posts ) + number_format_i18n( $trashed_posts ), ); $status_links['trash'] = '' . $localized_text . ''; @@ -377,7 +377,7 @@ public function extra_tablenav( $which ) { [ 'public' => true, 'exclude_from_search' => false, - ] + ], ); $instance_type = esc_attr( $this->page_type ); @@ -401,8 +401,8 @@ public function extra_tablenav( $which ) { WHERE post_status IN (" . implode( ', ', array_fill( 0, count( $states ), '%s' ) ) . ') ORDER BY post_type ASC', - $states - ) + $states, + ), ); $post_type_filter = isset( $_GET['post_type_filter'] ) && is_string( $_GET['post_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type_filter'] ) ) : ''; @@ -417,7 +417,7 @@ public function extra_tablenav( $which ) { '', esc_html( $obj->labels->name ), esc_attr( $post_type->post_type ), - selected( $selected, $post_type->post_type, false ) + selected( $selected, $post_type->post_type, false ), ); } } @@ -426,13 +426,13 @@ public function extra_tablenav( $which ) { '', esc_attr( 'post-type-filter-' . $instance_type ), /* translators: Hidden accessibility text. */ - esc_html__( 'Filter by content type', 'wordpress-seo' ) + esc_html__( 'Filter by content type', 'wordpress-seo' ), ); printf( '', // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $options is properly escaped above. $options, - esc_attr( 'post-type-filter-' . $instance_type ) + esc_attr( 'post-type-filter-' . $instance_type ), ); submit_button( esc_html__( 'Filter', 'wordpress-seo' ), 'button', false, false, [ 'id' => 'post-query-submit' ] ); @@ -565,7 +565,7 @@ protected function count_items( $subquery, $all_states, $post_type_clause ) { "SELECT COUNT(ID) FROM {$subquery} WHERE post_status IN ({$all_states}) {$post_type_clause} - " + ", ); } @@ -617,7 +617,7 @@ protected function set_pagination( $total_items ) { 'total_items' => $total_items, 'total_pages' => ceil( $total_items / $per_page ), 'per_page' => $per_page, - ] + ], ); $this->pagination = [ @@ -714,8 +714,8 @@ protected function get_items( $query ) { $wpdb->prepare( $query, $this->pagination['offset'], - $this->pagination['per_page'] - ) + $this->pagination['per_page'], + ), ); } @@ -743,7 +743,7 @@ protected function get_all_states() { return $wpdb->prepare( implode( ', ', array_fill( 0, count( $states ), '%s' ) ), - $states + $states, ); } @@ -841,7 +841,7 @@ protected function parse_page_title_column( $rec ) { esc_url( get_edit_post_link( $rec->ID, true ) ), /* translators: Hidden accessibility text; %s: post title. */ esc_attr( sprintf( __( 'Edit “%s”', 'wordpress-seo' ), $title ) ), - __( 'Edit', 'wordpress-seo' ) + __( 'Edit', 'wordpress-seo' ), ); } @@ -853,7 +853,7 @@ protected function parse_page_title_column( $rec ) { esc_url( add_query_arg( 'preview', 'true', get_permalink( $rec->ID ) ) ), /* translators: Hidden accessibility text; %s: post title. */ esc_attr( sprintf( __( 'Preview “%s”', 'wordpress-seo' ), $title ) ), - __( 'Preview', 'wordpress-seo' ) + __( 'Preview', 'wordpress-seo' ), ); } } @@ -863,7 +863,7 @@ protected function parse_page_title_column( $rec ) { esc_url( get_permalink( $rec->ID ) ), /* translators: Hidden accessibility text; %s: post title. */ esc_attr( sprintf( __( 'View “%s”', 'wordpress-seo' ), $title ) ), - __( 'View', 'wordpress-seo' ) + __( 'View', 'wordpress-seo' ), ); } } @@ -919,7 +919,7 @@ protected function parse_column( $column_name, $rec ) { '%2$s %3$s', $rec->ID, esc_html__( 'Save', 'wordpress-seo' ), - esc_html__( 'Save all', 'wordpress-seo' ) + esc_html__( 'Save all', 'wordpress-seo' ), ); break; } @@ -1000,7 +1000,7 @@ protected function get_meta_data_result( array $post_ids ) { $where = $wpdb->prepare( 'post_id IN (' . implode( ', ', array_fill( 0, count( $post_ids ), '%d' ) ) . ')', - $post_ids + $post_ids, ); $where .= $wpdb->prepare( ' AND meta_key = %s', WPSEO_Meta::$meta_prefix . $this->target_db_field ); @@ -1039,7 +1039,7 @@ protected function merge_columns( $columns = [] ) { 'col_post_date' => __( 'Publication date', 'wordpress-seo' ), 'col_page_slug' => __( 'Page URL/Slug', 'wordpress-seo' ), ], - $columns + $columns, ); $columns['col_row_action'] = __( 'Action', 'wordpress-seo' ); diff --git a/admin/class-bulk-title-editor-list-table.php b/admin/class-bulk-title-editor-list-table.php index 5314fdb52d0..a523e26ba9d 100644 --- a/admin/class-bulk-title-editor-list-table.php +++ b/admin/class-bulk-title-editor-list-table.php @@ -80,7 +80,7 @@ protected function parse_page_specific_column( $column_name, $record, $attribute return sprintf( '', 'wpseo-new-title-' . $record->ID, - $record->ID + $record->ID, ); } diff --git a/admin/class-config.php b/admin/class-config.php index 609298e1a3a..bef7e30181b 100644 --- a/admin/class-config.php +++ b/admin/class-config.php @@ -63,7 +63,7 @@ public function init() { Plans_Page_Integration::PAGE, Redirects_Page_Integration::PAGE, ], - true + true, ); $new_dashboard_page = ( $page === General_Page_Integration::PAGE && ! is_network_admin() ); if ( $page_exceptions || $new_dashboard_page ) { diff --git a/admin/class-database-proxy.php b/admin/class-database-proxy.php index b9ddcbea873..063f58468c5 100644 --- a/admin/class-database-proxy.php +++ b/admin/class-database-proxy.php @@ -147,14 +147,14 @@ public function upsert( array $data, ?array $where = null, $format = null, $wher $this->get_table_name(), implode( ', ', $keys ), implode( ', ', array_fill( 0, count( $data ), '%s' ) ), - implode( ', ', $update ) + implode( ', ', $update ), ); $result = $this->database->query( $this->database->prepare( $query, - array_values( $data ) - ) + array_values( $data ), + ), ); $this->post_execution(); @@ -210,7 +210,7 @@ public function create_table( array $columns, array $indexes = [] ) { 'CREATE TABLE IF NOT EXISTS %1$s ( %2$s ) %3$s', $this->get_table_name(), implode( ',', array_merge( $columns, $indexes ) ), - $this->database->get_charset_collate() + $this->database->get_charset_collate(), ); $this->pre_execution(); diff --git a/admin/class-export.php b/admin/class-export.php index 6e769b046e0..a9fee859577 100644 --- a/admin/class-export.php +++ b/admin/class-export.php @@ -60,12 +60,12 @@ public function output() { /* translators: %1$s expands to Import settings */ esc_html__( 'Copy all these settings to another site\'s %1$s tab and click "%1$s" there.', - 'wordpress-seo' + 'wordpress-seo', ), esc_html__( 'Import settings', - 'wordpress-seo' - ) + 'wordpress-seo', + ), ); echo '

'; /* translators: %1$s expands to Yoast SEO */ @@ -96,7 +96,7 @@ private function export_header() { /* translators: %1$s expands to Yoast SEO, %2$s expands to Yoast.com */ esc_html__( 'These are settings for the %1$s plugin by %2$s', 'wordpress-seo' ), 'Yoast SEO', - 'Yoast.com' + 'Yoast.com', ); $this->write_line( '; ' . $header ); } diff --git a/admin/class-meta-columns.php b/admin/class-meta-columns.php index 43cf334a628..14ffecf8d72 100644 --- a/admin/class-meta-columns.php +++ b/admin/class-meta-columns.php @@ -418,14 +418,14 @@ protected function collect_filters() { if ( $this->is_valid_filter( $seo_filter ) ) { $active_filters = array_merge( $active_filters, - $this->determine_seo_filters( $seo_filter ) + $this->determine_seo_filters( $seo_filter ), ); } if ( $this->is_valid_filter( $readability_filter ) ) { $active_filters = array_merge( $active_filters, - $this->determine_readability_filters( $readability_filter ) + $this->determine_readability_filters( $readability_filter ), ); } @@ -441,13 +441,13 @@ protected function collect_filters() { $keyphrase_filter = apply_filters( 'wpseo_change_keyphrase_filter_in_request', $this->get_keyword_filter( $current_keyword_filter ), - $current_keyword_filter + $current_keyword_filter, ); if ( is_array( $keyphrase_filter ) ) { $active_filters = array_merge( $active_filters, - [ $keyphrase_filter ] + [ $keyphrase_filter ], ); } } diff --git a/admin/class-my-yoast-proxy.php b/admin/class-my-yoast-proxy.php index a30f5c85d4c..0b708dc7949 100644 --- a/admin/class-my-yoast-proxy.php +++ b/admin/class-my-yoast-proxy.php @@ -66,7 +66,7 @@ public function handle_proxy_page() { $this->render_proxy_page(); // Prevent the WordPress UI from loading. - exit; + exit(); } /** diff --git a/admin/class-option-tabs-formatter.php b/admin/class-option-tabs-formatter.php index 5a54266fc64..b59f6780d9f 100644 --- a/admin/class-option-tabs-formatter.php +++ b/admin/class-option-tabs-formatter.php @@ -50,7 +50,7 @@ public function run( WPSEO_Option_Tabs $option_tabs ) { esc_attr( $tab->get_name() . '-tab' ), esc_url( '#top#' . $tab->get_name() ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: we do this on purpose - $label + $label, ); } echo '

'; diff --git a/admin/class-plugin-availability.php b/admin/class-plugin-availability.php index 8ed9491423c..9a553f4663b 100644 --- a/admin/class-plugin-availability.php +++ b/admin/class-plugin-availability.php @@ -43,7 +43,7 @@ protected function register_yoast_plugins() { 'description' => sprintf( /* translators: %1$s expands to Yoast SEO */ __( 'The premium version of %1$s with more features & support.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ), 'installed' => false, 'slug' => 'wordpress-seo-premium/wp-seo-premium.php', @@ -87,7 +87,7 @@ protected function register_yoast_plugins() { 'description' => sprintf( /* translators: %1$s expands to Yoast SEO */ __( 'Seamlessly integrate WooCommerce with %1$s and get extra features!', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ), '_dependencies' => [ 'WooCommerce' => [ diff --git a/admin/class-premium-upsell-admin-block.php b/admin/class-premium-upsell-admin-block.php index 0eb90bca60b..af364e4bbcd 100644 --- a/admin/class-premium-upsell-admin-block.php +++ b/admin/class-premium-upsell-admin-block.php @@ -80,7 +80,7 @@ public function render() { '%3$s', esc_attr( 'wpseo-' . $this->identifier . '-popup-button' ), esc_url( $url ), - $button_text + $button_text, ); echo '
'; @@ -129,7 +129,7 @@ protected function get_argument_html( $argument ) { '
  • %3$s
  • ', esc_url( $assets_uri . 'packages/js/images/icon-check-circle-green.svg' ), esc_attr( $class . '--argument' ), - $argument + $argument, ); } @@ -179,7 +179,7 @@ private function get_header( bool $is_woocommerce_active ) { $header_text = sprintf( /* translators: %s expands to Yoast WooCommerce SEO */ esc_html__( 'Upgrade to %s', 'wordpress-seo' ), - 'Yoast WooCommerce SEO' + 'Yoast WooCommerce SEO', ); $header_icon = sprintf( '', @@ -190,12 +190,12 @@ private function get_header( bool $is_woocommerce_active ) { $header_text = sprintf( /* translators: %s expands to Yoast SEO Premium*/ esc_html__( 'Upgrade to %s', 'wordpress-seo' ), - 'Yoast SEO Premium' + 'Yoast SEO Premium', ); $header_icon = sprintf( '', - esc_url( $assets_uri . 'packages/js/images/icon-crown.svg' ) + esc_url( $assets_uri . 'packages/js/images/icon-crown.svg' ), ); } return [ $header_text, $header_icon ]; diff --git a/admin/class-primary-term-admin.php b/admin/class-primary-term-admin.php index 85c0c888e2c..a368551b533 100644 --- a/admin/class-primary-term-admin.php +++ b/admin/class-primary-term-admin.php @@ -68,7 +68,7 @@ protected function primary_term_field( $taxonomy_name ) { '', esc_attr( $this->generate_field_id( $taxonomy_name ) ), esc_attr( $this->generate_field_name( $taxonomy_name ) ), - esc_attr( $this->get_primary_term( $taxonomy_name ) ) + esc_attr( $this->get_primary_term( $taxonomy_name ) ), ); } @@ -159,9 +159,7 @@ protected function get_primary_term( $taxonomy_name ) { * @return array */ protected function get_primary_term_taxonomies( $post_id = null ) { - if ( $post_id === null ) { - $post_id = $this->get_current_id(); - } + $post_id ??= $this->get_current_id(); $taxonomies = wp_cache_get( 'primary_term_taxonomies_' . $post_id, 'wpseo' ); if ( $taxonomies !== false ) { @@ -239,7 +237,7 @@ private function map_taxonomies_for_js( $taxonomy ) { 'taxonomy' => $taxonomy->name, 'update_term_meta_cache' => false, 'fields' => 'id=>name', - ] + ], ); $mapped_terms_for_js = []; diff --git a/admin/class-product-upsell-notice.php b/admin/class-product-upsell-notice.php index e5149c179ab..bd16e6e09a3 100644 --- a/admin/class-product-upsell-notice.php +++ b/admin/class-product-upsell-notice.php @@ -84,7 +84,7 @@ public function dismiss_notice_listener() { $this->dismiss_notice(); if ( wp_safe_redirect( admin_url( 'admin.php?page=wpseo_dashboard' ) ) ) { - exit; + exit(); } } @@ -148,7 +148,7 @@ protected function get_premium_upsell_section() { /* translators: %1$s expands anchor to premium plugin page, %2$s expands to */ __( 'By the way, did you know we also have a %1$sPremium plugin%2$s? It offers advanced features, like a redirect manager and support for multiple keyphrases. It also comes with 24/7 personal support.', 'wordpress-seo' ), "", - '' + '', ); } @@ -166,14 +166,14 @@ protected function get_notification() { __( 'We\'ve noticed you\'ve been using %1$s for some time now; we hope you love it! We\'d be thrilled if you could %2$sgive us a 5 stars rating on WordPress.org%3$s!', 'wordpress-seo' ), 'Yoast SEO', '', - '' + '', ) . "\n\n"; $message .= sprintf( /* translators: %1$s is a link start tag to the bugreport guidelines on the Yoast help center, %2$s is the link closing tag. */ __( 'If you are experiencing issues, %1$splease file a bug report%2$s and we\'ll do our best to help you out.', 'wordpress-seo' ), '', - '' + '', ) . "\n\n"; $message .= $this->get_premium_upsell_section() . "\n\n"; @@ -187,7 +187,7 @@ protected function get_notification() { 'id' => 'wpseo-upsell-notice', 'capabilities' => 'wpseo_manage_options', 'priority' => 0.8, - ] + ], ); return $notification; diff --git a/admin/class-schema-person-upgrade-notification.php b/admin/class-schema-person-upgrade-notification.php index c2332c4e543..2bf01677af1 100644 --- a/admin/class-schema-person-upgrade-notification.php +++ b/admin/class-schema-person-upgrade-notification.php @@ -65,7 +65,7 @@ protected function get_notification() { /* translators: %1$s is a link start tag to the Search Appearance settings, %2$s is the link closing tag. */ __( 'You have previously set your site to represent a person. We’ve improved our functionality around Schema and the Knowledge Graph, so you should go in and %1$scomplete those settings%2$s.', 'wordpress-seo' ), '', - '' + '', ); $notification = new Yoast_Notification( @@ -75,7 +75,7 @@ protected function get_notification() { 'id' => 'wpseo-schema-person-upgrade', 'capabilities' => 'wpseo_manage_options', 'priority' => 0.8, - ] + ], ); return $notification; diff --git a/admin/class-suggested-plugins.php b/admin/class-suggested-plugins.php index 2d937be190e..708eac83af0 100644 --- a/admin/class-suggested-plugins.php +++ b/admin/class-suggested-plugins.php @@ -95,7 +95,7 @@ protected function get_yoast_seo_suggested_plugins_notification( $notification_i 'id' => $notification_id, 'type' => Yoast_Notification::WARNING, 'capabilities' => [ 'install_plugins' ], - ] + ], ); } @@ -117,7 +117,7 @@ protected function create_install_suggested_plugin_message( $suggested_plugin ) $install_link, '', $this->create_more_information_link( $suggested_plugin['url'], $suggested_plugin['title'] ), - '' + '', ); } @@ -134,7 +134,7 @@ protected function create_more_information_link( $url, $name ) { '', $url, /* translators: Hidden accessibility text; %1$s expands to the dependency name */ - sprintf( __( 'More information about %1$s', 'wordpress-seo' ), $name ) + sprintf( __( 'More information about %1$s', 'wordpress-seo' ), $name ), ); } } diff --git a/admin/class-wincher-dashboard-widget.php b/admin/class-wincher-dashboard-widget.php index 5f9c793be87..90faf1da8be 100644 --- a/admin/class-wincher-dashboard-widget.php +++ b/admin/class-wincher-dashboard-widget.php @@ -56,7 +56,7 @@ public function add_wincher_dashboard_widget() { 'wpseo-wincher-dashboard-overview', /* translators: %1$s expands to Yoast SEO, %2$s to Wincher */ sprintf( __( '%1$s / %2$s: Top Keyphrases', 'wordpress-seo' ), 'Yoast SEO', 'Wincher' ), - [ $this, 'display_wincher_dashboard_widget' ] + [ $this, 'display_wincher_dashboard_widget' ], ); } diff --git a/admin/class-yoast-columns.php b/admin/class-yoast-columns.php index 989f87b87cf..bf17dcc1d24 100644 --- a/admin/class-yoast-columns.php +++ b/admin/class-yoast-columns.php @@ -34,7 +34,7 @@ public function add_help_tab() { $help_tab_content = sprintf( /* translators: %1$s: Yoast SEO */ __( '%1$s adds several columns to this page.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); if ( $meta_columns_present ) { @@ -42,7 +42,7 @@ public function add_help_tab() { /* translators: %1$s: Link to article about content analysis, %2$s: Anchor closing */ __( 'We\'ve written an article about %1$show to use the SEO score and Readability score%2$s.', 'wordpress-seo' ), '', - '' + '', ); } @@ -53,7 +53,7 @@ public function add_help_tab() { '', '', '', - '' + '', ); } @@ -65,7 +65,7 @@ public function add_help_tab() { 'id' => 'yst-columns', 'content' => '

    ' . $help_tab_content . '

    ', 'priority' => 15, - ] + ], ); } diff --git a/admin/class-yoast-dashboard-widget.php b/admin/class-yoast-dashboard-widget.php index 7b07fd99b78..dfbcb501371 100644 --- a/admin/class-yoast-dashboard-widget.php +++ b/admin/class-yoast-dashboard-widget.php @@ -37,9 +37,7 @@ class Yoast_Dashboard_Widget implements WPSEO_WordPress_Integration { * @param WPSEO_Statistics|null $statistics WPSEO_Statistics instance. */ public function __construct( ?WPSEO_Statistics $statistics = null ) { - if ( $statistics === null ) { - $statistics = new WPSEO_Statistics(); - } + $statistics ??= new WPSEO_Statistics(); $this->statistics = $statistics; $this->asset_manager = new WPSEO_Admin_Asset_Manager(); @@ -77,7 +75,7 @@ public function add_dashboard_widget() { 'wpseo-dashboard-overview', /* translators: %s is the plugin name */ sprintf( __( '%s Posts Overview', 'wordpress-seo' ), 'Yoast SEO' ), - [ $this, 'display_dashboard_widget' ] + [ $this, 'display_dashboard_widget' ], ); } @@ -128,7 +126,7 @@ public function localize_dashboard_script() { 'feed_header' => sprintf( /* translators: %1$s resolves to Yoast.com */ __( 'Latest blog posts on %1$s', 'wordpress-seo' ), - 'Yoast.com' + 'Yoast.com', ), 'feed_footer' => __( 'Read more like this on our SEO blog', 'wordpress-seo' ), 'wp_version' => substr( $GLOBALS['wp_version'], 0, 3 ) . '-' . ( is_plugin_active( 'classic-editor/classic-editor.php' ) ? '1' : '0' ), diff --git a/admin/class-yoast-form.php b/admin/class-yoast-form.php index 70788914112..1bf22c66708 100644 --- a/admin/class-yoast-form.php +++ b/admin/class-yoast-form.php @@ -328,13 +328,13 @@ public function checkbox_list( $variable, $labels, $attr = [] ) { esc_attr( $this->option_name . '[' . $variable . '][' . $name . ']' ), checked( ! empty( $values[ $name ] ), true, false ), esc_attr( $name ), - disabled( ( isset( $attr['disabled'] ) && $attr['disabled'] ), true, false ) + disabled( ( isset( $attr['disabled'] ) && $attr['disabled'] ), true, false ), ); printf( '', esc_attr( $variable . '-' . $name ), // #1 - esc_html( $label ) + esc_html( $label ), ); echo '
    '; } @@ -379,7 +379,7 @@ public function light_switch( $variable, $label, $buttons = [], $reverse = true, $reverse, $help, $strong, - $disabled_attribute + $disabled_attribute, ); // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: All output is properly escaped or hardcoded in the presenter. @@ -424,7 +424,7 @@ public function textinput( $variable, $label, $attr = [] ) { [ 'for' => $variable, 'class' => 'textinput', - ] + ], ); $aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $variable ); @@ -465,7 +465,7 @@ public function number( $variable, $label, $attr = [] ) { [ 'for' => $variable, 'class' => 'textinput ' . $attr['class'], - ] + ], ); $aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $variable ); @@ -510,7 +510,7 @@ public function textinput_extra_content( $variable, $label, $attr = [] ) { [ 'for' => $variable, 'class' => $attr['class'] . '--label', - ] + ], ); if ( isset( $attr['extra_content'] ) ) { @@ -533,7 +533,7 @@ public function textinput_extra_content( $variable, $label, $attr = [] ) { isset( $attr['autocomplete'] ) ? ' autocomplete="' . esc_attr( $attr['autocomplete'] ) . '"' : '', $aria_attributes, esc_attr( $val ), - $this->get_disabled_attribute( $variable, $attr ) + $this->get_disabled_attribute( $variable, $attr ), ); // phpcs:enable // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: output is properly escaped. @@ -572,7 +572,7 @@ public function textarea( $variable, $label, $attr = [] ) { [ 'for' => $variable, 'class' => 'textinput', - ] + ], ); $disabled_attribute = $this->get_disabled_attribute( $variable, $attr ); @@ -593,9 +593,7 @@ public function textarea( $variable, $label, $attr = [] ) { * @return void */ public function hidden( $variable, $id = '', $val = null ) { - if ( $val === null ) { - $val = $this->get_field_value( $variable, '' ); - } + $val ??= $this->get_field_value( $variable, '' ); if ( is_bool( $val ) ) { $val = ( $val === true ) ? 'true' : 'false'; @@ -639,7 +637,7 @@ public function select( $variable, $label, array $select_options, $styled = 'uns [ 'for' => $variable, 'class' => 'select', - ] + ], ); echo $help; // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: The help contains HTML. } @@ -702,7 +700,7 @@ public function file_upload( $variable, $label, $attr = [] ) { [ 'for' => $variable, 'class' => 'select', - ] + ], ); $disabled_attribute = $this->get_disabled_attribute( $variable, $attr ); @@ -751,7 +749,7 @@ public function media_input( $variable, $label, $attr = [] ) { [ 'for' => 'wpseo_' . $variable, 'class' => 'select', - ] + ], ); $id_field_id = 'wpseo_' . $var_esc . '_id'; @@ -838,7 +836,7 @@ public function radio( $variable, $values, $legend = '', $legend_attr = [], $att 'for' => $var_esc . '-' . $key_esc, 'class' => 'radio', 'aria_label' => $aria_label, - ] + ], ); } echo ''; @@ -969,10 +967,10 @@ public function index_switch( $variable, $label, $help = '', $attr = [] ) { sprintf( /* translators: %s expands to an indexable object's name, like a post type or taxonomy */ esc_html__( 'Show %s in search results?', 'wordpress-seo' ), - $label + $label, ), $help, - [ 'disabled' => $is_disabled ] + [ 'disabled' => $is_disabled ], ); } @@ -1008,7 +1006,7 @@ public function show_hide_switch( $variable, $label, $inverse_keys = false, $hel $show_hide_switch, $label, $help, - [ 'disabled' => $is_disabled ] + [ 'disabled' => $is_disabled ], ); } diff --git a/admin/class-yoast-input-validation.php b/admin/class-yoast-input-validation.php index 667ee78f1f9..ad1c261639b 100644 --- a/admin/class-yoast-input-validation.php +++ b/admin/class-yoast-input-validation.php @@ -64,7 +64,7 @@ public static function add_yoast_admin_document_title_errors( $admin_title ) { /* translators: %1$s: amount of errors, %2$s: the admin page title */ _n( 'The form contains %1$s error. %2$s', 'The form contains %1$s errors. %2$s', $error_count, 'wordpress-seo' ), number_format_i18n( $error_count ), - $admin_title + $admin_title, ); } diff --git a/admin/class-yoast-network-admin.php b/admin/class-yoast-network-admin.php index 01f8f2f30bd..cc4169878e7 100644 --- a/admin/class-yoast-network-admin.php +++ b/admin/class-yoast-network-admin.php @@ -210,7 +210,7 @@ public function enqueue_assets() { $asset_manager->localize_script( 'network-admin', 'wpseoNetworkAdminGlobalL10n', - $translations + $translations, ); } @@ -329,6 +329,6 @@ protected function redirect_back( $query_args = [] ) { } wp_safe_redirect( $sendback ); - exit; + exit(); } } diff --git a/admin/class-yoast-network-settings-api.php b/admin/class-yoast-network-settings-api.php index a573d141232..05c0d7e8f2f 100644 --- a/admin/class-yoast-network-settings-api.php +++ b/admin/class-yoast-network-settings-api.php @@ -155,9 +155,7 @@ public function meets_requirements() { */ public static function get() { - if ( self::$instance === null ) { - self::$instance = new self(); - } + self::$instance ??= new self(); return self::$instance; } diff --git a/admin/class-yoast-notification-center.php b/admin/class-yoast-notification-center.php index 3d6f422a679..974abcc1e45 100644 --- a/admin/class-yoast-notification-center.php +++ b/admin/class-yoast-notification-center.php @@ -90,9 +90,7 @@ private function __construct() { */ public static function get() { - if ( self::$instance === null ) { - self::$instance = new self(); - } + self::$instance ??= new self(); return self::$instance; } @@ -544,7 +542,7 @@ public function ajax_get_notifications() { $this->display_notifications( $echo ); // AJAX die. - exit; + exit(); } /** @@ -866,7 +864,7 @@ private function array_to_notification( $notification_data ) { return new Yoast_Notification( $notification_data['message'], - $notification_data['options'] + $notification_data['options'], ); } diff --git a/admin/class-yoast-notification.php b/admin/class-yoast-notification.php index 5c24b02fee7..f33adeaf6f8 100644 --- a/admin/class-yoast-notification.php +++ b/admin/class-yoast-notification.php @@ -359,9 +359,7 @@ public function render() { $message = $this->wrap_yoast_seo_icon( $this->message ); } - if ( $message === null ) { - $message = wpautop( $this->message ); - } + $message ??= wpautop( $this->message ); // Build the output DIV. return '
    ' . $message . '
    ' . PHP_EOL; @@ -388,7 +386,7 @@ private function wrap_yoast_seo_icon( $message ) { '', esc_url( plugin_dir_url( WPSEO_FILE ) . 'packages/js/images/Yoast_SEO_Icon.svg' ), 60, - 60 + 60, ); $out .= '
    '; $out .= $message; @@ -429,9 +427,7 @@ private function normalize_options( $options ) { } // Set to the id of the current user if not supplied. - if ( $options['user_id'] === null ) { - $options['user_id'] = get_current_user_id(); - } + $options['user_id'] ??= get_current_user_id(); return $options; } diff --git a/admin/class-yoast-notifications.php b/admin/class-yoast-notifications.php index c3847e01f43..87c41a8ec70 100644 --- a/admin/class-yoast-notifications.php +++ b/admin/class-yoast-notifications.php @@ -159,7 +159,7 @@ private function output_ajax_response( $type ) { [ 'html' => $html, 'total' => self::get_active_notification_count(), - ] + ], ); // phpcs:enable -- Reason: WPSEO_Utils::format_json_encode is safe. } diff --git a/admin/class-yoast-plugin-conflict.php b/admin/class-yoast-plugin-conflict.php index 838d8a70a73..48ab13f8b00 100644 --- a/admin/class-yoast-plugin-conflict.php +++ b/admin/class-yoast-plugin-conflict.php @@ -102,9 +102,7 @@ public function check_for_conflicts( $plugin_section ) { return false; } - if ( $sections_checked === null ) { - $sections_checked = []; - } + $sections_checked ??= []; if ( ! in_array( $plugin_section, $sections_checked, true ) ) { $sections_checked[] = $plugin_section; @@ -194,8 +192,8 @@ protected function set_error( $plugin_section, $readable_plugin_section ) { [ 'type' => Yoast_Notification::ERROR, 'id' => 'wpseo-conflict-' . $identifier, - ] - ) + ], + ), ); } } diff --git a/admin/exceptions/class-file-size-exception.php b/admin/exceptions/class-file-size-exception.php index 3deddbe215b..addbed6390d 100644 --- a/admin/exceptions/class-file-size-exception.php +++ b/admin/exceptions/class-file-size-exception.php @@ -21,7 +21,7 @@ public static function externally_hosted( $file_url ) { $message = sprintf( /* translators: %1$s expands to the requested url */ __( 'Cannot get the size of %1$s because it is hosted externally.', 'wordpress-seo' ), - $file_url + $file_url, ); return new self( $message ); @@ -38,7 +38,7 @@ public static function unknown_error( $file_url ) { $message = sprintf( /* translators: %1$s expands to the requested url */ __( 'Cannot get the size of %1$s because of unknown reasons.', 'wordpress-seo' ), - $file_url + $file_url, ); return new self( $message ); diff --git a/admin/filters/class-abstract-post-filter.php b/admin/filters/class-abstract-post-filter.php index 08232076870..6c772504ce2 100644 --- a/admin/filters/class-abstract-post-filter.php +++ b/admin/filters/class-abstract-post-filter.php @@ -95,7 +95,7 @@ public function enqueue_explanation_assets() { $asset_manager->localize_script( 'filter-explanation', 'yoastFilterExplanation', - [ 'text' => $explanation ] + [ 'text' => $explanation ], ); } @@ -112,7 +112,7 @@ public function add_filter_link( $views ) { esc_url( $this->get_filter_url() ), ( $this->is_filter_active() ) ? ' class="current" aria-current="page"' : '', $this->get_label(), - $this->get_post_total() + $this->get_post_total(), ); return $views; diff --git a/admin/filters/class-cornerstone-filter.php b/admin/filters/class-cornerstone-filter.php index 198312899d3..f57b6584c3c 100644 --- a/admin/filters/class-cornerstone-filter.php +++ b/admin/filters/class-cornerstone-filter.php @@ -51,7 +51,7 @@ public function filter_posts( $where ) { $where .= $wpdb->prepare( " AND {$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = '1' ) ", - WPSEO_Meta::$meta_prefix . self::META_NAME + WPSEO_Meta::$meta_prefix . self::META_NAME, ); } @@ -104,7 +104,7 @@ protected function get_explanation() { __( 'Mark the most important %1$s as \'cornerstone content\' to improve your site structure. %2$sLearn more about cornerstone content%3$s.', 'wordpress-seo' ), strtolower( $post_type_object->labels->name ), '', - '' + '', ); } @@ -124,8 +124,8 @@ protected function get_post_total() { meta_key = %s AND meta_value = '1' ", $this->get_current_post_type(), - WPSEO_Meta::$meta_prefix . self::META_NAME - ) + WPSEO_Meta::$meta_prefix . self::META_NAME, + ), ); } diff --git a/admin/google_search_console/views/gsc-display.php b/admin/google_search_console/views/gsc-display.php index 510831c2ed0..c11de080357 100644 --- a/admin/google_search_console/views/gsc-display.php +++ b/admin/google_search_console/views/gsc-display.php @@ -31,14 +31,14 @@ /* Translators: %1$s: expands to opening anchor tag, %2$s expands to closing anchor tag. */ __( 'Google has discontinued its Crawl Errors API. Therefore, any possible crawl errors you might have cannot be displayed here anymore. %1$sRead our statement on this for further information%2$s.', 'wordpress-seo' ), '', - WPSEO_Admin_Utils::get_new_tab_message() . '' + WPSEO_Admin_Utils::get_new_tab_message() . '', ); $gsc_notification .= '

    '; $gsc_notification .= sprintf( /* Translators: %1$s: expands to opening anchor tag, %2$s expands to closing anchor tag. */ __( 'To view your current crawl errors, %1$splease visit Google Search Console%2$s.', 'wordpress-seo' ), '', - WPSEO_Admin_Utils::get_new_tab_message() . '' + WPSEO_Admin_Utils::get_new_tab_message() . '', ); ?>
    diff --git a/admin/google_search_console/views/gsc-redirect-nopremium.php b/admin/google_search_console/views/gsc-redirect-nopremium.php index 2db6442beb2..39cd8ecbf05 100644 --- a/admin/google_search_console/views/gsc-redirect-nopremium.php +++ b/admin/google_search_console/views/gsc-redirect-nopremium.php @@ -13,7 +13,7 @@ printf( /* Translators: %s: expands to Yoast SEO Premium */ esc_html__( 'Creating redirects is a %s feature', 'wordpress-seo' ), - 'Yoast SEO Premium' + 'Yoast SEO Premium', ); echo ''; echo '

    '; @@ -21,7 +21,7 @@ /* Translators: %1$s: expands to 'Yoast SEO Premium', %2$s: links to Yoast SEO Premium plugin page. */ esc_html__( 'To be able to create a redirect and fix this issue, you need %1$s. You can buy the plugin, including one year of support and updates, on %2$s.', 'wordpress-seo' ), 'Yoast SEO Premium', - 'yoast.com' + 'yoast.com', ); echo '

    '; echo ''; diff --git a/admin/import/plugins/class-abstract-plugin-importer.php b/admin/import/plugins/class-abstract-plugin-importer.php index 6f5674f2f83..03b1b651b52 100644 --- a/admin/import/plugins/class-abstract-plugin-importer.php +++ b/admin/import/plugins/class-abstract-plugin-importer.php @@ -111,8 +111,8 @@ protected function cleanup() { $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s", - $this->meta_key - ) + $this->meta_key, + ), ); $result = $wpdb->__get( 'result' ); if ( ! $result ) { @@ -161,8 +161,8 @@ protected function detect() { "SELECT COUNT(*) AS `count` FROM {$wpdb->postmeta} WHERE meta_key IN ( " . implode( ', ', array_fill( 0, count( $meta_keys ), '%s' ) ) . ' )', - $meta_keys - ) + $meta_keys, + ), ); if ( $result === '0' ) { @@ -189,8 +189,8 @@ protected function meta_key_clone( $old_key, $new_key, $replace_values = [] ) { $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange -- This is intentional + temporary. "CREATE TEMPORARY TABLE tmp_meta_table SELECT * FROM {$wpdb->postmeta} WHERE meta_key = %s", - $old_key - ) + $old_key, + ), ); if ( $result === false ) { $this->set_missing_db_rights_status(); @@ -201,8 +201,8 @@ protected function meta_key_clone( $old_key, $new_key, $replace_values = [] ) { $wpdb->query( $wpdb->prepare( "DELETE FROM tmp_meta_table WHERE post_id IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s )", - WPSEO_Meta::$meta_prefix . $new_key - ) + WPSEO_Meta::$meta_prefix . $new_key, + ), ); /* @@ -215,8 +215,8 @@ protected function meta_key_clone( $old_key, $new_key, $replace_values = [] ) { $wpdb->query( $wpdb->prepare( 'UPDATE tmp_meta_table SET meta_key = %s', - WPSEO_Meta::$meta_prefix . $new_key - ) + WPSEO_Meta::$meta_prefix . $new_key, + ), ); $this->meta_key_clone_replace( $replace_values ); @@ -320,8 +320,8 @@ protected function meta_key_clone_replace( $replace_values ) { $wpdb->prepare( 'UPDATE tmp_meta_table SET meta_value = %s WHERE meta_value = %s', $new_value, - $old_value - ) + $old_value, + ), ); } } diff --git a/admin/import/plugins/class-import-aioseo-v4.php b/admin/import/plugins/class-import-aioseo-v4.php index 9cd5dc61e2e..5aa76581a77 100644 --- a/admin/import/plugins/class-import-aioseo-v4.php +++ b/admin/import/plugins/class-import-aioseo-v4.php @@ -112,8 +112,8 @@ protected function meta_key_clone_replace( $replace_values ) { $wpdb->prepare( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', $aioseo_variable, - $yoast_variable - ) + $yoast_variable, + ), ); } @@ -149,7 +149,7 @@ protected function get_unique_custom_fields_or_taxonomies( $meta_values, $aioseo preg_match_all( "/#$aioseo_prefix-([\w-]+)/", $meta_value, - $matches + $matches, ); /* @@ -189,8 +189,8 @@ protected function replace_custom_field_or_taxonomy_replace_vars( $unique_custom $wpdb->prepare( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', $aioseo_variable, - $yoast_variable - ) + $yoast_variable, + ), ); } } @@ -211,8 +211,8 @@ protected function get_meta_values_with_custom_field_or_taxonomy( $wpdb, $aioseo return $wpdb->get_col( $wpdb->prepare( 'SELECT meta_value FROM tmp_meta_table WHERE meta_value LIKE %s', - "%#$aioseo_prefix-%" - ) + "%#$aioseo_prefix-%", + ), ); } diff --git a/admin/import/plugins/class-import-platinum-seo-pack.php b/admin/import/plugins/class-import-platinum-seo-pack.php index 16a5ce9e5c0..8240fe8c91e 100644 --- a/admin/import/plugins/class-import-platinum-seo-pack.php +++ b/admin/import/plugins/class-import-platinum-seo-pack.php @@ -128,7 +128,7 @@ protected function find_posts_by_robots_meta( $meta_value ) { 'order' => 'ASC', 'fields' => 'ids', 'nopaging' => true, - ] + ], ); if ( empty( $posts ) ) { return false; diff --git a/admin/import/plugins/class-import-squirrly.php b/admin/import/plugins/class-import-squirrly.php index e5ecc617a82..903eacc3135 100644 --- a/admin/import/plugins/class-import-squirrly.php +++ b/admin/import/plugins/class-import-squirrly.php @@ -89,8 +89,8 @@ protected function retrieve_posts() { return $wpdb->get_results( $wpdb->prepare( $this->retrieve_posts_query(), - get_current_blog_id() - ) + get_current_blog_id(), + ), ); } @@ -196,8 +196,8 @@ private function retrieve_post_data( $post_identifier ) { $data = $wpdb->get_var( $wpdb->prepare( "SELECT seo FROM {$this->table_name} WHERE blog_id = %d AND " . $query_where, - $replacements - ) + $replacements, + ), ); if ( ! $data || is_wp_error( $data ) ) { return false; diff --git a/admin/import/plugins/class-import-woothemes-seo.php b/admin/import/plugins/class-import-woothemes-seo.php index 5ee943c3f4a..8de37133853 100644 --- a/admin/import/plugins/class-import-woothemes-seo.php +++ b/admin/import/plugins/class-import-woothemes-seo.php @@ -130,8 +130,8 @@ private function cleanup_meta_key( $key ) { $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s", - $key - ) + $key, + ), ); return $wpdb->__get( 'result' ); } diff --git a/admin/import/plugins/class-import-wpseo.php b/admin/import/plugins/class-import-wpseo.php index 0d138f2bd9c..d34676b3cbf 100644 --- a/admin/import/plugins/class-import-wpseo.php +++ b/admin/import/plugins/class-import-wpseo.php @@ -197,7 +197,7 @@ private function import_taxonomy_metas() { [ 'taxonomy' => get_taxonomies(), 'hide_empty' => false, - ] + ], ); $tax_meta = get_option( 'wpseo_taxonomy_meta' ); @@ -300,7 +300,7 @@ private function cleanup_term_meta() { [ 'taxonomy' => get_taxonomies(), 'hide_empty' => false, - ] + ], ); foreach ( $terms as $term ) { diff --git a/admin/menu/class-admin-menu.php b/admin/menu/class-admin-menu.php index d6718aecd4d..05318a6ad82 100644 --- a/admin/menu/class-admin-menu.php +++ b/admin/menu/class-admin-menu.php @@ -59,7 +59,7 @@ public function register_settings_page() { $page_identifier, $admin_page_callback, $this->get_icon_svg(), - 99 + 99, ); // Wipe notification bits from hooks. @@ -91,7 +91,7 @@ public function get_submenu_pages() { $this->get_submenu_page( __( 'Search Console', 'wordpress-seo' ), 'wpseo_search_console', - $search_console_callback + $search_console_callback, ), $this->get_submenu_page( __( 'Tools', 'wordpress-seo' ), 'wpseo_tools' ), ]; diff --git a/admin/menu/class-base-menu.php b/admin/menu/class-base-menu.php index 216fc843704..524ce4b0f70 100644 --- a/admin/menu/class-base-menu.php +++ b/admin/menu/class-base-menu.php @@ -46,9 +46,7 @@ abstract public function get_submenu_pages(); * @return array Formatted submenu. */ protected function get_submenu_page( $page_title, $page_slug, $callback = null, $hook = null ) { - if ( $callback === null ) { - $callback = $this->get_admin_page_callback(); - } + $callback ??= $this->get_admin_page_callback(); return [ $this->get_page_identifier(), @@ -133,7 +131,7 @@ protected function register_menu_page( $submenu_page ) { $submenu_page[4], $submenu_page[5], $this->get_icon_svg(), - 99 + 99, ); // If necessary, add hooks for the submenu page. @@ -185,7 +183,7 @@ protected function register_submenu_page( $submenu_page ) { $submenu_page[2], $submenu_page[3], $submenu_page[4], - $submenu_page[5] + $submenu_page[5], ); // If necessary, add hooks for the submenu page. @@ -256,9 +254,7 @@ protected function get_license_page_title() { _deprecated_function( __METHOD__, 'Yoast SEO 25.5' ); - if ( $title === null ) { - $title = __( 'Upgrades', 'wordpress-seo' ); - } + $title ??= __( 'Upgrades', 'wordpress-seo' ); if ( YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-promotion' ) && ! YoastSEO()->helpers->product->is_premium() ) { $title = __( 'Upgrades', 'wordpress-seo' ) . '' . __( '30% OFF', 'wordpress-seo' ) . ''; diff --git a/admin/menu/class-network-admin-menu.php b/admin/menu/class-network-admin-menu.php index ef5879efb31..71890d96102 100644 --- a/admin/menu/class-network-admin-menu.php +++ b/admin/menu/class-network-admin-menu.php @@ -36,7 +36,7 @@ public function register_settings_page() { $this->get_manage_capability(), $this->get_page_identifier(), [ $this, 'network_config_page' ], - $this->get_icon_svg() + $this->get_icon_svg(), ); $submenu_pages = $this->get_submenu_pages(); @@ -55,7 +55,7 @@ public function get_submenu_pages() { $this->get_submenu_page( __( 'General', 'wordpress-seo' ), $this->get_page_identifier(), - [ $this, 'network_config_page' ] + [ $this, 'network_config_page' ], ), ]; diff --git a/admin/menu/class-replacevar-editor.php b/admin/menu/class-replacevar-editor.php index be3a41254f0..fe69d28fb69 100644 --- a/admin/menu/class-replacevar-editor.php +++ b/admin/menu/class-replacevar-editor.php @@ -65,7 +65,7 @@ public function __construct( Yoast_Form $yform, $arguments ) { 'has_new_badge' => false, 'is_disabled' => false, 'has_premium_badge' => false, - ] + ], ); $this->validate_arguments( $arguments ); @@ -122,7 +122,7 @@ public function render() { esc_attr( $this->arguments['description_placeholder'] ), esc_attr( $this->arguments['has_new_badge'] ), esc_attr( $this->arguments['is_disabled'] ), - esc_attr( $this->arguments['has_premium_badge'] ) + esc_attr( $this->arguments['has_premium_badge'] ), ); } @@ -150,8 +150,8 @@ protected function validate_arguments( array $arguments ) { sprintf( /* translators: %1$s expands to the missing field name. */ __( 'Not all required fields are given. Missing field %1$s', 'wordpress-seo' ), - $field_name - ) + $field_name, + ), ); } } diff --git a/admin/menu/class-replacevar-field.php b/admin/menu/class-replacevar-field.php index e94d2c732fb..b201a0e340e 100644 --- a/admin/menu/class-replacevar-field.php +++ b/admin/menu/class-replacevar-field.php @@ -82,7 +82,7 @@ public function render() { esc_attr( $this->field_id ), esc_attr( $this->label ), esc_attr( $this->page_type_recommended ), - esc_attr( $this->page_type_specific ) + esc_attr( $this->page_type_specific ), ); } } diff --git a/admin/metabox/class-abstract-sectioned-metabox-tab.php b/admin/metabox/class-abstract-sectioned-metabox-tab.php index 29ec6e90a14..732486e468d 100644 --- a/admin/metabox/class-abstract-sectioned-metabox-tab.php +++ b/admin/metabox/class-abstract-sectioned-metabox-tab.php @@ -83,7 +83,7 @@ public function display_link() { esc_attr( $this->link_class ), ( $this->link_title !== '' ) ? ' title="' . esc_attr( $this->link_title ) . '"' : '', ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', - $this->link_content + $this->link_content, ); } } diff --git a/admin/metabox/class-metabox-collapsible.php b/admin/metabox/class-metabox-collapsible.php index c5d378cd600..2e7502b029e 100644 --- a/admin/metabox/class-metabox-collapsible.php +++ b/admin/metabox/class-metabox-collapsible.php @@ -67,7 +67,7 @@ public function content() { 'collapsible' => true, 'class' => 'metabox wpseo-form wpseo-collapsible-container', 'paper_id' => 'collapsible-' . $this->name, - ] + ], ); return $collapsible_paper->get_output(); diff --git a/admin/metabox/class-metabox-form-tab.php b/admin/metabox/class-metabox-form-tab.php index df39f8b0fbf..395dbc4ca5e 100644 --- a/admin/metabox/class-metabox-form-tab.php +++ b/admin/metabox/class-metabox-form-tab.php @@ -115,7 +115,7 @@ public function link() { ( $this->link_class !== '' ) ? ' ' . esc_attr( $this->link_class ) : '', ( $this->link_title !== '' ) ? ' title="' . esc_attr( $this->link_title ) . '"' : '', ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', - $this->link_content + $this->link_content, ); } @@ -129,7 +129,7 @@ public function content() { '
    %3$s
    ', esc_attr( 'wpseo_' . $this->name ), esc_attr( $this->name ), - $this->content + $this->content, ); } } diff --git a/admin/metabox/class-metabox-section-additional.php b/admin/metabox/class-metabox-section-additional.php index 7ec559dd772..15e919feb34 100644 --- a/admin/metabox/class-metabox-section-additional.php +++ b/admin/metabox/class-metabox-section-additional.php @@ -87,7 +87,7 @@ public function display_link() { esc_attr( $this->name ), esc_attr( $this->link_class ), ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', - $this->link_content + $this->link_content, ); } @@ -100,7 +100,7 @@ public function display_content() { $html = sprintf( '
    ', esc_attr( $this->name ), - esc_attr( $this->content_class ) + esc_attr( $this->content_class ), ); $html .= $this->content; $html .= '
    '; diff --git a/admin/metabox/class-metabox-section-inclusive-language.php b/admin/metabox/class-metabox-section-inclusive-language.php index 1fddff4a093..291cd46300b 100644 --- a/admin/metabox/class-metabox-section-inclusive-language.php +++ b/admin/metabox/class-metabox-section-inclusive-language.php @@ -27,7 +27,7 @@ public function display_link() { '
  • %2$s
  • ', esc_attr( $this->name ), - esc_html__( 'Inclusive language', 'wordpress-seo' ) + esc_html__( 'Inclusive language', 'wordpress-seo' ), ); } @@ -39,7 +39,7 @@ public function display_link() { public function display_content() { printf( '
    ', - esc_attr( $this->name ) + esc_attr( $this->name ), ); echo '
    ', '
    '; } diff --git a/admin/metabox/class-metabox-section-react.php b/admin/metabox/class-metabox-section-react.php index 70906599753..9e83a8d4f3a 100644 --- a/admin/metabox/class-metabox-section-react.php +++ b/admin/metabox/class-metabox-section-react.php @@ -90,7 +90,7 @@ public function display_link() { esc_attr( $this->name ), esc_attr( $this->link_class ), ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', - wp_kses_post( $this->link_content ) + wp_kses_post( $this->link_content ), ); } @@ -105,7 +105,7 @@ public function display_content() { printf( '
    ', - esc_attr( $this->name ) + esc_attr( $this->name ), ); echo wp_kses_post( $this->content ); echo '
    '; diff --git a/admin/metabox/class-metabox-section-readability.php b/admin/metabox/class-metabox-section-readability.php index cbfea90747f..0d1b6729dbf 100644 --- a/admin/metabox/class-metabox-section-readability.php +++ b/admin/metabox/class-metabox-section-readability.php @@ -27,7 +27,7 @@ public function display_link() { '
  • %2$s
  • ', esc_attr( $this->name ), - esc_html__( 'Readability', 'wordpress-seo' ) + esc_html__( 'Readability', 'wordpress-seo' ), ); } @@ -39,7 +39,7 @@ public function display_link() { public function display_content() { printf( '
    ', - esc_attr( $this->name ) + esc_attr( $this->name ), ); echo '
    ', '
    '; } diff --git a/admin/metabox/class-metabox.php b/admin/metabox/class-metabox.php index 19922ebc5a2..a671adce05a 100644 --- a/admin/metabox/class-metabox.php +++ b/admin/metabox/class-metabox.php @@ -131,7 +131,7 @@ public function internet_explorer_metabox() { $post_type, 'normal', apply_filters( 'wpseo_metabox_prio', 'high' ), - [ '__block_editor_compatible_meta_box' => true ] + [ '__block_editor_compatible_meta_box' => true ], ); } } @@ -148,7 +148,7 @@ public function render_internet_explorer_notice() { '', '', '', - '' + '', ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped above. @@ -202,7 +202,7 @@ public static function translate_meta_boxes() { /* translators: 1: link open tag; 2: link close tag. */ __( 'The canonical URL that this page should point to. Leave empty to default to permalink. %1$sCross domain canonical%2$s supported too.', 'wordpress-seo' ), '', - WPSEO_Admin_Utils::get_new_tab_message() . '' + WPSEO_Admin_Utils::get_new_tab_message() . '', ); WPSEO_Meta::$meta_fields['advanced']['redirect']['title'] = __( '301 Redirect', 'wordpress-seo' ); @@ -251,7 +251,7 @@ public function add_meta_box() { $post_type, 'normal', apply_filters( 'wpseo_metabox_prio', 'high' ), - [ '__block_editor_compatible_meta_box' => true ] + [ '__block_editor_compatible_meta_box' => true ], ); } } @@ -278,7 +278,7 @@ public function get_metabox_script_data() { $permalink = $this->get_permalink(); $post_formatter = new WPSEO_Metabox_Formatter( - new WPSEO_Post_Metabox_Formatter( $this->get_metabox_post(), [], $permalink ) + new WPSEO_Post_Metabox_Formatter( $this->get_metabox_post(), [], $permalink ), ); $values = $post_formatter->get_values(); @@ -422,7 +422,7 @@ private function get_tabs() { $tabs[] = new WPSEO_Metabox_Section_React( 'schema', '' . __( 'Schema', 'wordpress-seo' ), - '' + '', ); } @@ -433,7 +433,7 @@ private function get_tabs() { '', [ 'html_after' => '
    ', - ] + ], ); } @@ -484,7 +484,7 @@ protected function get_additional_tabs() { $tab['name'], $tab['link_content'], $tab['content'], - $options + $options, ); } } @@ -726,7 +726,7 @@ public function save_postdata( $post_id ) { WPSEO_Meta::get_meta_field_defs( 'general', $post->post_type ), WPSEO_Meta::get_meta_field_defs( 'advanced' ), $social_fields, - WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ) + WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ), ); foreach ( $meta_boxes as $key => $meta_box ) { @@ -1101,7 +1101,7 @@ private function get_custom_fields_replace_vars( $post ) { [ $meta->presentation->title, $meta->presentation->meta_description, - ] + ], ); preg_match_all( '/%%cf_([A-Za-z0-9_]+)%%/', $replace_vars_fields, $matches ); diff --git a/admin/notifiers/dismissible-notification.php b/admin/notifiers/dismissible-notification.php index 84a608babd9..c0e89f2d10f 100644 --- a/admin/notifiers/dismissible-notification.php +++ b/admin/notifiers/dismissible-notification.php @@ -121,6 +121,6 @@ protected function set_dismissal_state() { */ protected function redirect_to_dashboard() { wp_safe_redirect( admin_url( 'admin.php?page=wpseo_dashboard' ) ); - exit; + exit(); } } diff --git a/admin/pages/network.php b/admin/pages/network.php index 829282725ac..0b182df9af0 100644 --- a/admin/pages/network.php +++ b/admin/pages/network.php @@ -25,8 +25,8 @@ __( 'Crawl settings', 'wordpress-seo' ), [ 'save_button' => true, - ] - ) + ], + ), ); $network_tabs->add_tab( new WPSEO_Option_Tab( 'restore-site', __( 'Restore Site', 'wordpress-seo' ), [ 'save_button' => false ] ) ); $network_tabs->display( $yform ); diff --git a/admin/pages/tools.php b/admin/pages/tools.php index e4b5d31b241..47a23d82a79 100644 --- a/admin/pages/tools.php +++ b/admin/pages/tools.php @@ -47,7 +47,7 @@ printf( /* translators: %1$s expands to Yoast SEO */ esc_html__( '%1$s comes with some very powerful built-in tools:', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); echo '

    '; diff --git a/admin/roles/class-role-manager-factory.php b/admin/roles/class-role-manager-factory.php index d22753a24be..bbe8cff126e 100644 --- a/admin/roles/class-role-manager-factory.php +++ b/admin/roles/class-role-manager-factory.php @@ -18,9 +18,7 @@ class WPSEO_Role_Manager_Factory { public static function get() { static $manager = null; - if ( $manager === null ) { - $manager = new WPSEO_Role_Manager_WP(); - } + $manager ??= new WPSEO_Role_Manager_WP(); return $manager; } diff --git a/admin/services/class-file-size.php b/admin/services/class-file-size.php index 5b093e4820a..8f648e4fc25 100644 --- a/admin/services/class-file-size.php +++ b/admin/services/class-file-size.php @@ -26,7 +26,7 @@ public function get( WP_REST_Request $request ) { 'type' => 'success', 'size_in_bytes' => $this->get_file_size( $file_url ), ], - 200 + 200, ); } catch ( WPSEO_File_Size_Exception $exception ) { return new WP_REST_Response( @@ -34,7 +34,7 @@ public function get( WP_REST_Request $request ) { 'type' => 'failure', 'response' => $exception->getMessage(), ], - 404 + 404, ); } } @@ -99,7 +99,7 @@ protected function calculate_file_size( $file_url ) { return WPSEO_Image_Utils::get_file_size( [ 'path' => $file_url, - ] + ], ); } } diff --git a/admin/statistics/class-statistics-service.php b/admin/statistics/class-statistics-service.php index 352e29e02ea..161b3d67407 100644 --- a/admin/statistics/class-statistics-service.php +++ b/admin/statistics/class-statistics-service.php @@ -209,22 +209,22 @@ private function labels() { /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag */ __( 'Posts %1$swithout%2$s a focus keyphrase', 'wordpress-seo' ), '', - '' + '', ), WPSEO_Rank::BAD => sprintf( /* translators: %s expands to the score */ __( 'Posts with the SEO score: %s', 'wordpress-seo' ), - '' . __( 'Needs improvement', 'wordpress-seo' ) . '' + '' . __( 'Needs improvement', 'wordpress-seo' ) . '', ), WPSEO_Rank::OK => sprintf( /* translators: %s expands to the score */ __( 'Posts with the SEO score: %s', 'wordpress-seo' ), - '' . __( 'OK', 'wordpress-seo' ) . '' + '' . __( 'OK', 'wordpress-seo' ) . '', ), WPSEO_Rank::GOOD => sprintf( /* translators: %s expands to the score */ __( 'Posts with the SEO score: %s', 'wordpress-seo' ), - '' . __( 'Good', 'wordpress-seo' ) . '' + '' . __( 'Good', 'wordpress-seo' ) . '', ), WPSEO_Rank::NO_INDEX => __( 'Posts that should not show up in search results', 'wordpress-seo' ), ]; diff --git a/admin/taxonomy/class-taxonomy-fields.php b/admin/taxonomy/class-taxonomy-fields.php index 9da698ef4a3..d4801f2e5a8 100644 --- a/admin/taxonomy/class-taxonomy-fields.php +++ b/admin/taxonomy/class-taxonomy-fields.php @@ -209,7 +209,7 @@ protected function get_social_fields() { 'options' => '', 'hide' => false, ], - ] + ], ); } diff --git a/admin/taxonomy/class-taxonomy-metabox.php b/admin/taxonomy/class-taxonomy-metabox.php index 67890f391f7..4a615515275 100644 --- a/admin/taxonomy/class-taxonomy-metabox.php +++ b/admin/taxonomy/class-taxonomy-metabox.php @@ -160,7 +160,7 @@ private function get_tabs() { '', [ 'html_after' => '
    ', - ] + ], ); } @@ -209,7 +209,7 @@ protected function get_additional_tabs() { $tab['name'], $tab['link_content'], $tab['content'], - $options + $options, ); } } diff --git a/admin/taxonomy/class-taxonomy.php b/admin/taxonomy/class-taxonomy.php index a63d3778d05..75794430232 100644 --- a/admin/taxonomy/class-taxonomy.php +++ b/admin/taxonomy/class-taxonomy.php @@ -114,7 +114,7 @@ private function show_internet_explorer_notice() { '', '', '', - '' + '', ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped above. echo new Alert_Presenter( $content ); @@ -299,7 +299,7 @@ public function localize_term_scraper_script( $term_id ) { $taxonomy = get_taxonomy( $term->taxonomy ); $term_formatter = new WPSEO_Metabox_Formatter( - new WPSEO_Term_Metabox_Formatter( $taxonomy, $term ) + new WPSEO_Term_Metabox_Formatter( $taxonomy, $term ), ); return $term_formatter->get_values(); diff --git a/admin/views/class-yoast-feature-toggles.php b/admin/views/class-yoast-feature-toggles.php index 14aca6b9e6c..7785510f5d9 100644 --- a/admin/views/class-yoast-feature-toggles.php +++ b/admin/views/class-yoast-feature-toggles.php @@ -36,9 +36,7 @@ class Yoast_Feature_Toggles { * @return self Main instance. */ public static function instance() { - if ( self::$instance === null ) { - self::$instance = new self(); - } + self::$instance ??= new self(); return self::$instance; } @@ -49,9 +47,7 @@ public static function instance() { * @return array List of sorted Yoast_Feature_Toggle instances. */ public function get_all() { - if ( $this->toggles === null ) { - $this->toggles = $this->load_toggles(); - } + $this->toggles ??= $this->load_toggles(); return $this->toggles; } @@ -157,7 +153,7 @@ protected function load_toggles() { /* translators: 1: Yoast SEO, 2: translated version of "Off" */ __( 'The advanced section of the %1$s meta box allows a user to remove posts from the search results or change the canonical. The settings in the schema tab allows a user to change schema meta data for a post. These are things you might not want any author to do. That\'s why, by default, only editors and administrators can do this. Setting to "%2$s" allows all users to change these settings.', 'wordpress-seo' ), 'Yoast SEO', - __( 'Off', 'wordpress-seo' ) + __( 'Off', 'wordpress-seo' ), ), 'order' => 90, ], @@ -168,7 +164,7 @@ protected function load_toggles() { 'read_more_label' => sprintf( /* translators: 1: Yoast SEO */ __( 'Allow us to track some data about your site to improve our plugin.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ), 'read_more_url' => 'https://yoa.st/usage-tracking-2', 'order' => 95, @@ -179,7 +175,7 @@ protected function load_toggles() { 'label' => sprintf( /* translators: 1: Yoast SEO */ __( 'This %1$s REST API endpoint gives you all the metadata you need for a specific URL. This will make it very easy for headless WordPress sites to use %1$s for all their SEO meta output.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ), 'order' => 100, ], @@ -239,7 +235,7 @@ protected function sitemaps_toggle_after() { $alert = new Alert_Presenter( /* translators: %1$s: expands to an opening anchor tag, %2$s: expands to a closing anchor tag */ sprintf( esc_html__( 'Disabling Yoast SEO\'s XML sitemaps will not disable WordPress\' core sitemaps. In some cases, this %1$s may result in SEO errors on your site%2$s. These may be reported in Google Search Console and other tools.', 'wordpress-seo' ), '', '' ), - 'warning' + 'warning', ); $out .= $alert->present(); $out .= '
    '; diff --git a/admin/views/class-yoast-integration-toggles.php b/admin/views/class-yoast-integration-toggles.php index ac66ee0f016..20bdb2216b7 100644 --- a/admin/views/class-yoast-integration-toggles.php +++ b/admin/views/class-yoast-integration-toggles.php @@ -33,9 +33,7 @@ class Yoast_Integration_Toggles { * @return self Main instance. */ public static function instance() { - if ( self::$instance === null ) { - self::$instance = new self(); - } + self::$instance ??= new self(); return self::$instance; } @@ -46,9 +44,7 @@ public static function instance() { * @return array List of sorted Yoast_Feature_Toggle instances. */ public function get_all() { - if ( $this->toggles === null ) { - $this->toggles = $this->load_toggles(); - } + $this->toggles ??= $this->load_toggles(); return $this->toggles; } @@ -69,7 +65,7 @@ protected function load_toggles() { 'label' => sprintf( /* translators: %s: 'Semrush' */ __( 'The %s integration offers suggestions and insights for keywords related to the entered focus keyphrase.', 'wordpress-seo' ), - 'Semrush' + 'Semrush', ), 'order' => 10, ], diff --git a/admin/views/js-templates-primary-term.php b/admin/views/js-templates-primary-term.php index 684ef87d52b..8947faec111 100644 --- a/admin/views/js-templates-primary-term.php +++ b/admin/views/js-templates-primary-term.php @@ -19,13 +19,13 @@ $yoast_free_js_button_label = sprintf( $yoast_free_js_button_label, '{{data.term}}', - '{{data.taxonomy.title}}' + '{{data.taxonomy.title}}', ); printf( '', esc_attr( $yoast_free_js_button_label ), - esc_html__( 'Make primary', 'wordpress-seo' ) + esc_html__( 'Make primary', 'wordpress-seo' ), ); ?> @@ -38,7 +38,7 @@ $yoast_free_js_taxonomy_title = __( 'Primary %s', 'wordpress-seo' ); $yoast_free_js_taxonomy_title = sprintf( '(' . $yoast_free_js_taxonomy_title . ')', - '{{data.taxonomy.title}}' + '{{data.taxonomy.title}}', ); ?> diff --git a/admin/views/paper-collapsible.php b/admin/views/paper-collapsible.php index e8e3fea4f17..ae2e4ece6a4 100644 --- a/admin/views/paper-collapsible.php +++ b/admin/views/paper-collapsible.php @@ -44,7 +44,7 @@ class=""get_button_html(), esc_html( $title ) . wp_kses_post( $title_after ), - wp_kses_post( $collapsible_config['toggle_icon'] ) + wp_kses_post( $collapsible_config['toggle_icon'] ), ); } else { @@ -72,7 +72,7 @@ class="" diff --git a/admin/views/partial-notifications-errors.php b/admin/views/partial-notifications-errors.php index 8ec3c30faf4..ee9c92d1a58 100644 --- a/admin/views/partial-notifications-errors.php +++ b/admin/views/partial-notifications-errors.php @@ -23,7 +23,7 @@ $yoast_seo_i18n_muted_issues_title = sprintf( /* translators: %d expands the amount of hidden notifications. */ _n( 'You have %d hidden notification:', 'You have %d hidden notifications:', $yoast_seo_dismissed_total, 'wordpress-seo' ), - $yoast_seo_dismissed_total + $yoast_seo_dismissed_total, ); require WPSEO_PATH . 'admin/views/partial-notifications-template.php'; diff --git a/admin/views/partial-notifications-template.php b/admin/views/partial-notifications-template.php index c09dca5b291..7277f61d618 100644 --- a/admin/views/partial-notifications-template.php +++ b/admin/views/partial-notifications-template.php @@ -36,7 +36,7 @@ function _yoast_display_notifications( $notifications_list, $status ) { $button = sprintf( '', /* translators: Hidden accessibility text. */ - esc_html__( 'Hide this item.', 'wordpress-seo' ) + esc_html__( 'Hide this item.', 'wordpress-seo' ), ); break; @@ -44,7 +44,7 @@ function _yoast_display_notifications( $notifications_list, $status ) { $button = sprintf( '', /* translators: Hidden accessibility text. */ - esc_html__( 'Show this item.', 'wordpress-seo' ) + esc_html__( 'Show this item.', 'wordpress-seo' ), ); break; } @@ -57,7 +57,7 @@ function _yoast_display_notifications( $notifications_list, $status ) { // This needs to be fixed in https://github.com/Yoast/wordpress-seo-premium/issues/2548. $notification, // Note: $button is properly escaped above. - $button + $button, ); } @@ -101,7 +101,7 @@ function _yoast_display_notifications( $notifications_list, $status ) { 'content' => _yoast_display_notifications( $yoast_seo_dismissed, 'dismissed' ), 'collapsible' => true, 'collapsible_header_class' => 'yoast-notification', - ] + ], ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: get_output() output is properly escaped. echo $dismissed_paper->get_output(); diff --git a/admin/views/partial-notifications-warnings.php b/admin/views/partial-notifications-warnings.php index e960d6ae61d..f5dfc284510 100644 --- a/admin/views/partial-notifications-warnings.php +++ b/admin/views/partial-notifications-warnings.php @@ -23,7 +23,7 @@ $yoast_seo_i18n_muted_issues_title = sprintf( /* translators: %d expands the amount of hidden notifications. */ _n( 'You have %d hidden notification:', 'You have %d hidden notifications:', $yoast_seo_dismissed_total, 'wordpress-seo' ), - $yoast_seo_dismissed_total + $yoast_seo_dismissed_total, ); require WPSEO_PATH . 'admin/views/partial-notifications-template.php'; diff --git a/admin/views/tabs/dashboard/dashboard.php b/admin/views/tabs/dashboard/dashboard.php index 2c8c96a54da..b419e787f80 100644 --- a/admin/views/tabs/dashboard/dashboard.php +++ b/admin/views/tabs/dashboard/dashboard.php @@ -17,7 +17,7 @@ $wpseo_contributors_phrase = sprintf( /* translators: %1$s expands to Yoast SEO */ __( 'See who contributed to %1$s.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); ?> diff --git a/admin/views/tabs/network/crawl-settings.php b/admin/views/tabs/network/crawl-settings.php index 81ff2d9b71b..ed2f49cb483 100644 --- a/admin/views/tabs/network/crawl-settings.php +++ b/admin/views/tabs/network/crawl-settings.php @@ -22,7 +22,7 @@ printf( /* translators: %s expands to Yoast SEO */ esc_html__( 'This tab allows you to selectively disable %s features for all sites in the network. By default all features are enabled, which allows site admins to choose for themselves if they want to toggle a feature on or off for their site. When you disable a feature here, site admins will not be able to use that feature at all.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); echo '

    '; @@ -30,7 +30,7 @@ /* translators: %1$s opens the link to the Yoast.com article about Crawl settings, %2$s closes the link, */ esc_html__( '%1$sLearn more about crawl settings.%2$s', 'wordpress-seo' ), '', - '' + '', ); echo '

    '; diff --git a/admin/views/tabs/network/features.php b/admin/views/tabs/network/features.php index 05ac5bbf454..5c0cec56d80 100644 --- a/admin/views/tabs/network/features.php +++ b/admin/views/tabs/network/features.php @@ -25,7 +25,7 @@ printf( /* translators: %s expands to Yoast SEO */ esc_html__( 'This tab allows you to selectively disable %s features for all sites in the network. By default all features are enabled, which allows site admins to choose for themselves if they want to toggle a feature on or off for their site. When you disable a feature here, site admins will not be able to use that feature at all.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); foreach ( $feature_toggles as $feature ) { @@ -52,7 +52,7 @@ $help_text .= sprintf( '%2$s', esc_url( WPSEO_Shortlinker::get( $url ) ), - esc_html( $feature->read_more_label ) + esc_html( $feature->read_more_label ), ); } @@ -60,7 +60,7 @@ WPSEO_Option::ALLOW_KEY_PREFIX . $feature->setting, /* translators: Hidden accessibility text; %s expands to a feature's name. */ sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $feature->name ) ), - $help_text + $help_text, ); $name = $feature->name; @@ -102,7 +102,7 @@ 'show_premium_upsell' => $show_premium_upsell, 'premium_upsell_url' => $premium_upsell_url, 'note_when_disabled' => $note_when_disabled, - ] + ], ); } ?> diff --git a/admin/views/tabs/network/general.php b/admin/views/tabs/network/general.php index a73c722b928..f212f9a44e9 100644 --- a/admin/views/tabs/network/general.php +++ b/admin/views/tabs/network/general.php @@ -26,7 +26,7 @@ [ 'admin' => __( 'Site Admins (default)', 'wordpress-seo' ), 'superadmin' => __( 'Super Admins only', 'wordpress-seo' ), - ] + ], ); if ( get_blog_count() <= 100 ) { @@ -35,7 +35,7 @@ $yform->select( 'defaultblog', __( 'New sites in the network inherit their SEO settings from this site', 'wordpress-seo' ), - $network_admin->get_site_choices( true, true ) + $network_admin->get_site_choices( true, true ), ); echo '

    ' . esc_html__( 'Choose the site whose settings you want to use as default for all sites that are added to your network. If you choose \'None\', the normal plugin defaults will be used.', 'wordpress-seo' ) . '

    '; } @@ -46,7 +46,7 @@ /* translators: 1: link open tag; 2: link close tag. */ esc_html__( 'Enter the %1$sSite ID%2$s for the site whose settings you want to use as default for all sites that are added to your network. Leave empty for none (i.e. the normal plugin defaults will be used).', 'wordpress-seo' ), '', - '' + '', ); echo '

    '; } diff --git a/admin/views/tabs/network/integrations.php b/admin/views/tabs/network/integrations.php index be635eeccba..e1000559730 100644 --- a/admin/views/tabs/network/integrations.php +++ b/admin/views/tabs/network/integrations.php @@ -25,7 +25,7 @@ printf( /* translators: %1$s expands to Yoast SEO */ esc_html__( 'This tab allows you to selectively disable %1$s integrations with third-party products for all sites in the network. By default all integrations are enabled, which allows site admins to choose for themselves if they want to toggle an integration on or off for their site. When you disable an integration here, site admins will not be able to use that integration at all.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); foreach ( $integration_toggles as $integration ) { @@ -40,7 +40,7 @@ $help_text .= sprintf( '%2$s', esc_url( WPSEO_Shortlinker::get( $integration->read_more_url ) ), - esc_html( $integration->read_more_label ) + esc_html( $integration->read_more_label ), ); } @@ -48,7 +48,7 @@ WPSEO_Option::ALLOW_KEY_PREFIX . $integration->setting, /* translators: Hidden accessibility text; %s expands to an integration's name. */ sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $integration->name ) ), - $help_text + $help_text, ); $name = $integration->name; @@ -88,7 +88,7 @@ 'preserve_disabled_value' => $preserve_disabled_value, 'show_premium_upsell' => $show_premium_upsell, 'premium_upsell_url' => $premium_upsell_url, - ] + ], ); do_action( 'Yoast\WP\SEO\admin_network_integration_after', $integration ); diff --git a/admin/views/tabs/network/restore-site.php b/admin/views/tabs/network/restore-site.php index ce6701a9851..4484f4f8fc7 100644 --- a/admin/views/tabs/network/restore-site.php +++ b/admin/views/tabs/network/restore-site.php @@ -21,7 +21,7 @@ $yform->select( 'site_id', __( 'Site ID', 'wordpress-seo' ), - $network_admin->get_site_choices( false, true ) + $network_admin->get_site_choices( false, true ), ); } else { diff --git a/admin/views/tabs/tool/import-seo.php b/admin/views/tabs/tool/import-seo.php index a5f666e4b1a..69abf0da650 100644 --- a/admin/views/tabs/tool/import-seo.php +++ b/admin/views/tabs/tool/import-seo.php @@ -20,7 +20,7 @@ printf( /* translators: %s expands to Yoast SEO */ esc_html__( '%s did not detect any plugin data from plugins it can import from.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); echo '

    '; @@ -65,7 +65,7 @@ function wpseo_import_external_select( $name, $plugins ) { printf( /* translators: 1: expands to Yoast SEO */ esc_html__( 'This will import the post metadata like SEO titles and descriptions into your %1$s metadata. It will only do this when there is no existing %1$s metadata yet. The original data will remain in place.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); ?>

    @@ -105,7 +105,7 @@ function wpseo_import_external_select( $name, $plugins ) { /* translators: 1: Link start tag to the First time configuration tab in the General page, 2: Link closing tag. */ esc_html__( 'You should finish the %1$sfirst time configuration%2$s to make sure your SEO data has been optimized and you’ve set the essential Yoast SEO settings for your site.', 'wordpress-seo' ), '', - '' + '', ); ?>

    diff --git a/admin/views/tabs/tool/wpseo-export.php b/admin/views/tabs/tool/wpseo-export.php index d0a4196145e..3946ddaa4ad 100644 --- a/admin/views/tabs/tool/wpseo-export.php +++ b/admin/views/tabs/tool/wpseo-export.php @@ -24,7 +24,7 @@ $wpseo_export_phrase = sprintf( /* translators: %1$s expands to Yoast SEO */ __( 'Export your %1$s settings here, to copy them on another site.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); ?> diff --git a/admin/views/tabs/tool/wpseo-import.php b/admin/views/tabs/tool/wpseo-import.php index 18a5bfe9fb6..35fafc8c00a 100644 --- a/admin/views/tabs/tool/wpseo-import.php +++ b/admin/views/tabs/tool/wpseo-import.php @@ -22,7 +22,7 @@ /* translators: 1: expands to Yoast SEO, 2: expands to Import settings. */ esc_html__( 'Import settings from another %1$s installation by pasting them here and clicking "%2$s".', 'wordpress-seo' ), 'Yoast SEO', - esc_html__( 'Import settings', 'wordpress-seo' ) + esc_html__( 'Import settings', 'wordpress-seo' ), ); ?>

    @@ -37,7 +37,7 @@ printf( /* translators: %s expands to Yoast SEO */ esc_html__( '%s settings to import:', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); ?>
    diff --git a/admin/views/tool-bulk-editor.php b/admin/views/tool-bulk-editor.php index 354ba376092..dab5a8334a7 100644 --- a/admin/views/tool-bulk-editor.php +++ b/admin/views/tool-bulk-editor.php @@ -70,10 +70,10 @@ function yoast_free_bulk_sanitize_input_fields() { wp_redirect( remove_query_arg( [ '_wp_http_referer', '_wpnonce' ], - $request_uri - ) + $request_uri, + ), ); - exit; + exit(); } /** diff --git a/admin/views/tool-file-editor.php b/admin/views/tool-file-editor.php index b0db6a4310d..dcfaf9ce7ab 100644 --- a/admin/views/tool-file-editor.php +++ b/admin/views/tool-file-editor.php @@ -26,7 +26,7 @@ $die_msg = sprintf( /* translators: %s expands to robots.txt. */ __( 'You cannot create a %s file.', 'wordpress-seo' ), - 'robots.txt' + 'robots.txt', ); exit( esc_html( $die_msg ) ); } @@ -47,7 +47,7 @@ $die_msg = sprintf( /* translators: %s expands to robots.txt. */ __( 'You cannot edit the %s file.', 'wordpress-seo' ), - 'robots.txt' + 'robots.txt', ); exit( esc_html( $die_msg ) ); } @@ -63,7 +63,7 @@ $msg = sprintf( /* translators: %s expands to robots.txt. */ __( 'Updated %s', 'wordpress-seo' ), - 'robots.txt' + 'robots.txt', ); } } @@ -74,7 +74,7 @@ $die_msg = sprintf( /* translators: %s expands to ".htaccess". */ __( 'You cannot edit the %s file.', 'wordpress-seo' ), - '.htaccess' + '.htaccess', ); exit( esc_html( $die_msg ) ); } @@ -114,7 +114,7 @@ printf( /* translators: %s expands to robots.txt. */ esc_html__( 'You don\'t have a %s file, create one here:', 'wordpress-seo' ), - 'robots.txt' + 'robots.txt', ); echo '

    '; @@ -123,8 +123,8 @@ sprintf( /* translators: %s expands to robots.txt. */ esc_attr__( 'Create %s file', 'wordpress-seo' ), - 'robots.txt' - ) + 'robots.txt', + ), ); echo ''; } @@ -133,7 +133,7 @@ printf( /* translators: %s expands to robots.txt. */ esc_html__( 'If you had a %s file and it was editable, you could edit it from here.', 'wordpress-seo' ), - 'robots.txt' + 'robots.txt', ); echo '

    '; } @@ -151,7 +151,7 @@ printf( /* translators: %s expands to robots.txt. */ esc_html__( 'If your %s were writable, you could edit it from here.', 'wordpress-seo' ), - 'robots.txt' + 'robots.txt', ); echo '

    '; echo '
    '; @@ -163,7 +163,7 @@ printf( /* translators: %s expands to robots.txt. */ esc_html__( 'Edit the content of your %s:', 'wordpress-seo' ), - 'robots.txt' + 'robots.txt', ); echo ''; echo '
    '; @@ -172,8 +172,8 @@ sprintf( /* translators: %s expands to robots.txt. */ esc_attr__( 'Save changes to %s', 'wordpress-seo' ), - 'robots.txt' - ) + 'robots.txt', + ), ); echo ''; } @@ -184,7 +184,7 @@ printf( /* translators: %s expands to ".htaccess". */ esc_html__( '%s file', 'wordpress-seo' ), - '.htaccess' + '.htaccess', ); echo ''; @@ -201,7 +201,7 @@ printf( /* translators: %s expands to ".htaccess". */ esc_html__( 'If your %s were writable, you could edit it from here.', 'wordpress-seo' ), - '.htaccess' + '.htaccess', ); echo '

    '; echo '
    '; @@ -213,7 +213,7 @@ printf( /* translators: %s expands to ".htaccess". */ esc_html__( 'Edit the content of your %s:', 'wordpress-seo' ), - '.htaccess' + '.htaccess', ); echo ''; echo '
    '; @@ -222,8 +222,8 @@ sprintf( /* translators: %s expands to ".htaccess". */ esc_attr__( 'Save changes to %s', 'wordpress-seo' ), - '.htaccess' - ) + '.htaccess', + ), ); echo ''; } @@ -233,7 +233,7 @@ printf( /* translators: %s expands to ".htaccess". */ esc_html__( 'If you had a %s file and it was editable, you could edit it from here.', 'wordpress-seo' ), - '.htaccess' + '.htaccess', ); echo '

    '; } diff --git a/admin/watchers/class-slug-change-watcher.php b/admin/watchers/class-slug-change-watcher.php index 68d186168d2..1c4718eed6e 100644 --- a/admin/watchers/class-slug-change-watcher.php +++ b/admin/watchers/class-slug-change-watcher.php @@ -184,9 +184,7 @@ protected function get_post_type_label( $post_type ) { $post_type_object = get_post_type_object( $post_type ); // If the post type of this post wasn't registered default back to post. - if ( $post_type_object === null ) { - $post_type_object = get_post_type_object( 'post' ); - } + $post_type_object ??= get_post_type_object( 'post' ); return $post_type_object->labels->singular_name; } @@ -247,7 +245,7 @@ protected function add_notification( $message ) { [ 'type' => 'notice-warning is-dismissible', 'yoast_branding' => true, - ] + ], ); $notification_center = Yoast_Notification_Center::get(); diff --git a/composer.json b/composer.json index 0a0994414d8..9604a60591f 100644 --- a/composer.json +++ b/composer.json @@ -38,8 +38,8 @@ "wpackagist-plugin/easy-digital-downloads": "dev-trunk", "wpackagist-plugin/google-site-kit": "dev-trunk", "wpackagist-plugin/woocommerce": "dev-trunk", - "yoast/wp-test-utils": "^1.2", - "yoast/yoastcs": "^3.2.0" + "yoast/wp-test-utils": "^1.2.1", + "yoast/yoastcs": "^3.3.0" }, "suggest": { "ext-bcmath": "For more accurate calculations", @@ -111,8 +111,8 @@ "Yoast\\WP\\SEO\\Composer\\Actions::check_coding_standards" ], "check-cs-thresholds": [ - "@putenv YOASTCS_THRESHOLD_ERRORS=2379", - "@putenv YOASTCS_THRESHOLD_WARNINGS=251", + "@putenv YOASTCS_THRESHOLD_ERRORS=2384", + "@putenv YOASTCS_THRESHOLD_WARNINGS=256", "Yoast\\WP\\SEO\\Composer\\Actions::check_cs_thresholds" ], "check-cs": [ diff --git a/composer.lock b/composer.lock index 2f5599b3ca1..c19445d7929 100644 --- a/composer.lock +++ b/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": "9a54667eb432cd5eb3bd9e7d7760d0c5", + "content-hash": "39a23b5c2ed5051c90d7939162f27c90", "packages": [ { "name": "composer/installers", @@ -258,27 +258,27 @@ }, { "name": "brain/monkey", - "version": "2.6.2", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/Brain-WP/BrainMonkey.git", - "reference": "d95a9d895352c30f47604ad1b825ab8fa9d1a373" + "reference": "ea3aeb3d559ba3c0930b3f4d210b665a4c044d83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Brain-WP/BrainMonkey/zipball/d95a9d895352c30f47604ad1b825ab8fa9d1a373", - "reference": "d95a9d895352c30f47604ad1b825ab8fa9d1a373", + "url": "https://api.github.com/repos/Brain-WP/BrainMonkey/zipball/ea3aeb3d559ba3c0930b3f4d210b665a4c044d83", + "reference": "ea3aeb3d559ba3c0930b3f4d210b665a4c044d83", "shasum": "" }, "require": { "antecedent/patchwork": "^2.1.17", - "mockery/mockery": "^1.3.5 || ^1.4.4", + "mockery/mockery": "~1.3.6 || ~1.4.4 || ~1.5.1 || ^1.6.10", "php": ">=5.6.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0", "phpcompatibility/php-compatibility": "^9.3.0", - "phpunit/phpunit": "^5.7.26 || ^6.0 || ^7.0 || >=8.0 <8.5.12 || ^8.5.14 || ^9.0" + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.49 || ^9.6.30" }, "type": "library", "extra": { @@ -324,7 +324,7 @@ "issues": "https://github.com/Brain-WP/BrainMonkey/issues", "source": "https://github.com/Brain-WP/BrainMonkey" }, - "time": "2024-08-29T20:15:04+00:00" + "time": "2026-02-05T09:22:14+00:00" }, { "name": "composer/package-versions-deprecated", @@ -401,29 +401,29 @@ }, { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1", + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", + "composer-plugin-api": "^2.2", "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { - "composer/composer": "*", + "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", @@ -442,9 +442,9 @@ "authors": [ { "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" }, { "name": "Contributors", @@ -452,7 +452,6 @@ } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", @@ -473,9 +472,28 @@ ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", "source": "https://github.com/PHPCSStandards/composer-installer" }, - "time": "2023-01-05T11:28:13+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-11T04:32:07+00:00" }, { "name": "doctrine/instantiator", @@ -1654,16 +1672,16 @@ }, { "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", "shasum": "" }, "require": { @@ -1720,27 +1738,32 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2024-04-24T21:30:46+00:00" + "time": "2025-09-19T17:43:28+00:00" }, { "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.6", + "version": "2.1.8", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "80ccb1a7640995edf1b87a4409fa584cd5869469" + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/80ccb1a7640995edf1b87a4409fa584cd5869469", - "reference": "80ccb1a7640995edf1b87a4409fa584cd5869469", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa", + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa", "shasum": "" }, "require": { "phpcompatibility/php-compatibility": "^9.0", - "phpcompatibility/phpcompatibility-paragonie": "^1.0" + "phpcompatibility/phpcompatibility-paragonie": "^1.0", + "squizlabs/php_codesniffer": "^3.3" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0" @@ -1790,35 +1813,39 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2025-01-16T22:34:19+00:00" + "time": "2025-10-18T00:05:59+00:00" }, { "name": "phpcsstandards/phpcsextra", - "version": "1.2.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", - "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489" + "reference": "b598aa890815b8df16363271b659d73280129101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", - "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101", + "reference": "b598aa890815b8df16363271b659d73280129101", "shasum": "" }, "require": { "php": ">=5.4", - "phpcsstandards/phpcsutils": "^1.0.9", - "squizlabs/php_codesniffer": "^3.8.0" + "phpcsstandards/phpcsutils": "^1.2.0", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" }, "require-dev": { "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", - "phpcsstandards/phpcsdevcs": "^1.1.6", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", "phpcsstandards/phpcsdevtools": "^1.2.1", - "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "type": "phpcodesniffer-standard", "extra": { @@ -1868,35 +1895,39 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2023-12-08T16:49:07+00:00" + "time": "2025-11-12T23:06:57+00:00" }, { "name": "phpcsstandards/phpcsutils", - "version": "1.0.12", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", - "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c" + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/87b233b00daf83fb70f40c9a28692be017ea7c6c", - "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.10.0 || 4.0.x-dev@dev" + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" }, "require-dev": { "ext-filter": "*", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", - "phpcsstandards/phpcsdevcs": "^1.1.6", - "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0" + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" }, "type": "phpcodesniffer-standard", "extra": { @@ -1933,6 +1964,7 @@ "phpcodesniffer-standard", "phpcs", "phpcs3", + "phpcs4", "standards", "static analysis", "tokens", @@ -1956,36 +1988,40 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-05-20T13:34:27+00:00" + "time": "2025-12-08T14:27:58+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.33.0", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", + "nikic/php-parser": "^5.3.0", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", "symfony/process": "^5.2" }, "type": "library", @@ -2003,9 +2039,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" }, - "time": "2024-10-13T11:25:22+00:00" + "time": "2026-01-25T14:56:51+00:00" }, { "name": "phpunit/php-code-coverage", @@ -3752,28 +3788,27 @@ }, { "name": "sirbrillig/phpcs-variable-analysis", - "version": "v2.12.0", + "version": "v2.13.0", "source": { "type": "git", "url": "https://github.com/sirbrillig/phpcs-variable-analysis.git", - "reference": "4debf5383d9ade705e0a25121f16c3fecaf433a7" + "reference": "a15e970b8a0bf64cfa5e86d941f5e6b08855f369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/4debf5383d9ade705e0a25121f16c3fecaf433a7", - "reference": "4debf5383d9ade705e0a25121f16c3fecaf433a7", + "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/a15e970b8a0bf64cfa5e86d941f5e6b08855f369", + "reference": "a15e970b8a0bf64cfa5e86d941f5e6b08855f369", "shasum": "" }, "require": { "php": ">=5.4.0", - "squizlabs/php_codesniffer": "^3.5.6" + "squizlabs/php_codesniffer": "^3.5.7 || ^4.0.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", - "phpcsstandards/phpcsdevcs": "^1.1", - "phpstan/phpstan": "^1.7", + "phpstan/phpstan": "^1.7 || ^2.0", "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0 || ^10.5.32 || ^11.3.3", - "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0" + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0 || ^6.0 || ^7.0" }, "type": "phpcodesniffer-standard", "autoload": { @@ -3805,36 +3840,36 @@ "source": "https://github.com/sirbrillig/phpcs-variable-analysis", "wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki" }, - "time": "2025-03-17T16:17:38+00:00" + "time": "2025-09-30T22:22:48+00:00" }, { "name": "slevomat/coding-standard", - "version": "8.15.0", + "version": "8.22.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "7d1d957421618a3803b593ec31ace470177d7817" + "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817", - "reference": "7d1d957421618a3803b593ec31ace470177d7817", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/1dd80bf3b93692bedb21a6623c496887fad05fec", + "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", - "php": "^7.2 || ^8.0", - "phpstan/phpdoc-parser": "^1.23.1", - "squizlabs/php_codesniffer": "^3.9.0" + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.1.2", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^2.3.0", + "squizlabs/php_codesniffer": "^3.13.4" }, "require-dev": { - "phing/phing": "2.17.4", - "php-parallel-lint/php-parallel-lint": "1.3.2", - "phpstan/phpstan": "1.10.60", - "phpstan/phpstan-deprecation-rules": "1.1.4", - "phpstan/phpstan-phpunit": "1.3.16", - "phpstan/phpstan-strict-rules": "1.5.2", - "phpunit/phpunit": "8.5.21|9.6.8|10.5.11" + "phing/phing": "3.0.1|3.1.0", + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/phpstan": "2.1.24", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpstan/phpstan-phpunit": "2.0.7", + "phpstan/phpstan-strict-rules": "2.0.6", + "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.3.10" }, "type": "phpcodesniffer-standard", "extra": { @@ -3858,7 +3893,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.15.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.22.1" }, "funding": [ { @@ -3870,20 +3905,20 @@ "type": "tidelift" } ], - "time": "2024-03-09T15:20:58+00:00" + "time": "2025-09-13T08:53:30+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.12.0", + "version": "3.13.5", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630" + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/2d1b63db139c3c6ea0c927698e5160f8b3b8d630", - "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { @@ -3900,11 +3935,6 @@ "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -3954,7 +3984,7 @@ "type": "thanks_dev" } ], - "time": "2025-03-18T05:04:51+00:00" + "time": "2025-11-04T16:30:35+00:00" }, { "name": "symfony/config", @@ -4950,16 +4980,16 @@ }, { "name": "wp-coding-standards/wpcs", - "version": "3.1.0", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", - "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7" + "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/9333efcbff231f10dfd9c56bb7b65818b4733ca7", - "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7795ec6fa05663d716a549d0b44e47ffc8b0d4a6", + "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6", "shasum": "" }, "require": { @@ -4967,17 +4997,17 @@ "ext-libxml": "*", "ext-tokenizer": "*", "ext-xmlreader": "*", - "php": ">=5.4", - "phpcsstandards/phpcsextra": "^1.2.1", - "phpcsstandards/phpcsutils": "^1.0.10", - "squizlabs/php_codesniffer": "^3.9.0" + "php": ">=7.2", + "phpcsstandards/phpcsextra": "^1.5.0", + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.4" }, "require-dev": { "php-parallel-lint/php-console-highlighter": "^1.0.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", - "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^10.0.0@dev", "phpcsstandards/phpcsdevtools": "^1.2.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^8.0 || ^9.0" }, "suggest": { "ext-iconv": "For improved results", @@ -5012,7 +5042,7 @@ "type": "custom" } ], - "time": "2024-03-25T16:39:00+00:00" + "time": "2025-11-25T12:08:04+00:00" }, { "name": "wpackagist-plugin/easy-digital-downloads", @@ -5136,25 +5166,27 @@ }, { "name": "yoast/wp-test-utils", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/Yoast/wp-test-utils.git", - "reference": "2e0f62e0281e4859707c5f13b7da1422aa1c8f7b" + "reference": "e1c316f10ff892fff36116349b59ee5a00174ca3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/wp-test-utils/zipball/2e0f62e0281e4859707c5f13b7da1422aa1c8f7b", - "reference": "2e0f62e0281e4859707c5f13b7da1422aa1c8f7b", + "url": "https://api.github.com/repos/Yoast/wp-test-utils/zipball/e1c316f10ff892fff36116349b59ee5a00174ca3", + "reference": "e1c316f10ff892fff36116349b59ee5a00174ca3", "shasum": "" }, "require": { - "brain/monkey": "^2.6.1", + "brain/monkey": "^2.7.0", "php": ">=5.6", - "yoast/phpunit-polyfills": "^1.1.0" + "yoast/phpunit-polyfills": "^1.1.5" }, "require-dev": { - "yoast/yoastcs": "^2.3.1" + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "yoast/yoastcs": "^3.3.0" }, "type": "library", "extra": { @@ -5199,22 +5231,23 @@ ], "support": { "issues": "https://github.com/Yoast/wp-test-utils/issues", + "security": "https://github.com/Yoast/wp-test-utils/security/policy", "source": "https://github.com/Yoast/wp-test-utils" }, - "time": "2023-09-27T10:25:08+00:00" + "time": "2026-02-05T18:06:16+00:00" }, { "name": "yoast/yoastcs", - "version": "3.2.0", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/Yoast/yoastcs.git", - "reference": "2594255b7d1503bae9584eb89708b0b23fac5391" + "reference": "54fdadbd4145dc5f08110c0f9b38fd2fc28a1394" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/yoastcs/zipball/2594255b7d1503bae9584eb89708b0b23fac5391", - "reference": "2594255b7d1503bae9584eb89708b0b23fac5391", + "url": "https://api.github.com/repos/Yoast/yoastcs/zipball/54fdadbd4145dc5f08110c0f9b38fd2fc28a1394", + "reference": "54fdadbd4145dc5f08110c0f9b38fd2fc28a1394", "shasum": "" }, "require": { @@ -5224,18 +5257,17 @@ "php-parallel-lint/php-console-highlighter": "^1.0.0", "php-parallel-lint/php-parallel-lint": "^1.4.0", "phpcompatibility/phpcompatibility-wp": "^2.1.6", - "phpcsstandards/phpcsextra": "^1.2.1", + "phpcsstandards/phpcsextra": "^1.5.0", "phpcsstandards/phpcsutils": "^1.0.12", - "sirbrillig/phpcs-variable-analysis": "^2.12.0", + "sirbrillig/phpcs-variable-analysis": "^2.13.0", "slevomat/coding-standard": "^8.15.0", "squizlabs/php_codesniffer": "^3.12.0", - "wp-coding-standards/wpcs": "^3.1.0" + "wp-coding-standards/wpcs": "^3.3.0" }, "require-dev": { "phpcompatibility/php-compatibility": "^9.3.5", - "phpcsstandards/phpcsdevtools": "^1.2.2", - "phpunit/phpunit": "^8.0 || ^9.0", - "roave/security-advisories": "dev-master" + "phpcsstandards/phpcsdevtools": "^1.2.3", + "phpunit/phpunit": "^8.5.50 || ^9.6.31" }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -5263,7 +5295,7 @@ "security": "https://github.com/Yoast/yoastcs/security/policy", "source": "https://github.com/Yoast/yoastcs" }, - "time": "2025-03-19T11:49:48+00:00" + "time": "2026-02-04T12:33:54+00:00" } ], "aliases": [], diff --git a/config/composer/actions.php b/config/composer/actions.php index e111da26dc1..4c0f50e4516 100644 --- a/config/composer/actions.php +++ b/config/composer/actions.php @@ -131,7 +131,7 @@ public static function compile_dependency_injection_container( Event $event ) { __DIR__ . '/../../src/generated/container.php', __DIR__ . '/../dependency-injection/services.php', __DIR__ . '/../../vendor/composer/autoload_classmap.php', - 'Yoast\WP\SEO\Generated' + 'Yoast\WP\SEO\Generated', ); $io->write( 'The dependency injection container has been compiled.' ); @@ -150,7 +150,7 @@ public static function lint_branch( Event $event ) { $branch = 'trunk'; $args = $event->getArguments(); - if ( ! empty( $args ) ) { + if ( ! empty( $args[0] ) ) { $branch = $args[0]; } @@ -240,7 +240,7 @@ private static function check_cs_for_changed_files( $compare ) { $command = \sprintf( 'composer check-cs-warnings -- %s %s', \implode( ' ', \array_map( 'escapeshellarg', $php_files ) ), - $extra_args + $extra_args, ); \system( $command, $exit_code ); @@ -260,7 +260,7 @@ private static function filter_files( array $files, string $extension ): array { $files, static function ( $file ) use ( $extension ) { return \substr( $file, ( 0 - \strlen( $extension ) ) ) === $extension; - } + }, ); } @@ -420,7 +420,7 @@ public static function generate_unit_test( Event $event ) { if ( empty( $args[0] ) ) { throw new RuntimeException( 'You must provide an argument with the fully qualified class name' - . 'for which you want a unit test to be generated.' + . 'for which you want a unit test to be generated.', ); } diff --git a/config/composer/unit-test-generator.php b/config/composer/unit-test-generator.php index c8dc849337a..f3728c96bfb 100644 --- a/config/composer/unit-test-generator.php +++ b/config/composer/unit-test-generator.php @@ -79,7 +79,7 @@ public function generate( $fully_qualified_class_name ) { $groups, $property_statements, $create_mock_statements, - $instance_argument_statements + $instance_argument_statements, ); \file_put_contents( __DIR__ . '/../../' . $unit_test_path, $filled_in_template ); @@ -148,7 +148,7 @@ protected function generate_groups( $path ) { static function ( $group ) { return ' * @group ' . $group; }, - $groups + $groups, ); return \implode( \PHP_EOL, $groups ); @@ -244,7 +244,7 @@ static function ( $argument ) { return 'use ' . $argument->getClass()->getShortName() . ';'; } }, - $constructor_arguments + $constructor_arguments, ); return \implode( \PHP_EOL, $statements ); @@ -262,7 +262,7 @@ protected function generate_property_statements( array $constructor_arguments ) static function ( $argument ) { return self::generate_mocked_property_statement( $argument->getClass()->getShortName(), $argument->getName() ); }, - $constructor_arguments + $constructor_arguments, ); return \implode( \PHP_EOL . \PHP_EOL, $statements ); @@ -300,7 +300,7 @@ protected function generate_create_mock_statements( array $constructor_arguments static function ( $argument ) { return '$this->' . $argument->getName() . ' = Mockery::mock( ' . $argument->getClass()->getShortName() . '::class );'; }, - $constructor_arguments + $constructor_arguments, ); return \implode( \PHP_EOL . "\t\t", $statements ); @@ -318,7 +318,7 @@ protected function generate_instance_argument_statements( array $constructor_arg static function ( $argument ) { return '$this->' . $argument->getName(); }, - $constructor_arguments + $constructor_arguments, ); return \implode( ',' . \PHP_EOL . "\t\t\t", $statements ); diff --git a/config/dependency-injection/container-compiler.php b/config/dependency-injection/container-compiler.php index a7572ffd03f..4cb79b5121e 100644 --- a/config/dependency-injection/container-compiler.php +++ b/config/dependency-injection/container-compiler.php @@ -55,7 +55,7 @@ public static function compile( [ 'class' => 'Cached_Container', 'namespace' => $target_namespace, - ] + ], ); $code = \str_replace( 'Symfony\\Component\\DependencyInjection', 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection', $code ); $code = \str_replace( 'Symfony\\\\Component\\\\DependencyInjection', 'YoastSEO_Vendor\\\\Symfony\\\\Component\\\\DependencyInjection', $code ); diff --git a/config/dependency-injection/custom-loader.php b/config/dependency-injection/custom-loader.php index e995857c6f0..0fedb5024dc 100644 --- a/config/dependency-injection/custom-loader.php +++ b/config/dependency-injection/custom-loader.php @@ -135,9 +135,7 @@ private function findClasses( $namespace, $pattern, $excludePattern ) { if ( $excludePattern ) { $excludePattern = $parameter_bag->unescapeValue( $parameter_bag->resolveValue( $excludePattern ) ); foreach ( $this->glob( $excludePattern, true, $resource ) as $path => $info ) { - if ( $exclude_prefix === null ) { - $exclude_prefix = $resource->getPrefix(); - } + $exclude_prefix ??= $resource->getPrefix(); // Normalize Windows slashes. $path = $this->normalize_slashes( $path ); @@ -181,7 +179,7 @@ private function findClasses( $namespace, $pattern, $excludePattern ) { 'While discovering services from namespace "%s", an error was thrown when processing the class "%s": "%s".', $namespace, $class, - $e->getMessage() + $e->getMessage(), ); continue; } diff --git a/config/dependency-injection/interface-injection-pass.php b/config/dependency-injection/interface-injection-pass.php index 801e9ca3123..d13f75620aa 100644 --- a/config/dependency-injection/interface-injection-pass.php +++ b/config/dependency-injection/interface-injection-pass.php @@ -149,7 +149,7 @@ static function ( $other_definition ) use ( $definition_class ) { } return \is_subclass_of( $other_class, $definition_class->splat_argument_type ); - } + }, ); } } diff --git a/inc/class-addon-manager.php b/inc/class-addon-manager.php index f6e1bc9954c..a9c687e5efc 100644 --- a/inc/class-addon-manager.php +++ b/inc/class-addon-manager.php @@ -276,9 +276,7 @@ public function get_plugin_information( $data, $action, $args ) { * @return stdClass The list of addons activated for this site. */ public function get_myyoast_site_information() { - if ( $this->site_information === null ) { - $this->site_information = $this->get_site_information_transient(); - } + $this->site_information ??= $this->get_site_information_transient(); if ( $this->site_information ) { return $this->site_information; @@ -412,7 +410,7 @@ public function expired_subscription_warning( $plugin_data ) { /* translators: %1$s and %2$s are a opening and closing tag. */ esc_html__( '%1$s30%% OFF - Black Friday %2$s', 'wordpress-seo' ), '', - '' + '', ); } echo '

    '; @@ -422,7 +420,7 @@ public function expired_subscription_warning( $plugin_data ) { esc_html__( 'Your %1$s plugin cannot be updated as your subscription has expired. %2$sRenew your product subscription%3$s to restore updates and full feature access.', 'wordpress-seo' ), esc_html( $plugin_data['name'] ), '', - '' + '', ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output is escaped above. . $sale_copy @@ -538,9 +536,9 @@ protected function create_notification( $product_name, $short_link ) { '', 'MyYoast', '', - $product_name + $product_name, ), - $notification_options + $notification_options, ); } diff --git a/inc/class-my-yoast-api-request.php b/inc/class-my-yoast-api-request.php index 752c22be57b..17a993fbe34 100644 --- a/inc/class-my-yoast-api-request.php +++ b/inc/class-my-yoast-api-request.php @@ -137,7 +137,7 @@ protected function decode_response( $response ) { if ( ! is_object( $response ) ) { throw new WPSEO_MyYoast_Invalid_JSON_Exception( - esc_html__( 'No JSON object was returned.', 'wordpress-seo' ) + esc_html__( 'No JSON object was returned.', 'wordpress-seo' ), ); } @@ -158,7 +158,7 @@ private function validate_response( $response ) { } throw new WPSEO_MyYoast_Invalid_JSON_Exception( - esc_html__( 'Not all needed fields are present.', 'wordpress-seo' ) + esc_html__( 'Not all needed fields are present.', 'wordpress-seo' ), ); } diff --git a/inc/class-rewrite.php b/inc/class-rewrite.php index 9622ada0aad..89827ceb38b 100644 --- a/inc/class-rewrite.php +++ b/inc/class-rewrite.php @@ -251,6 +251,6 @@ protected function redirect( $category_redirect ) { $catlink = trailingslashit( get_option( 'home' ) ) . user_trailingslashit( $category_redirect, 'category' ); wp_safe_redirect( $catlink, 301, 'Yoast SEO' ); - exit; + exit(); } } diff --git a/inc/class-upgrade-history.php b/inc/class-upgrade-history.php index 227cb672b19..da4b1e0a6d7 100644 --- a/inc/class-upgrade-history.php +++ b/inc/class-upgrade-history.php @@ -89,9 +89,9 @@ protected function get_options_data( array $option_names ) { SELECT %i, %i FROM ' . $wpdb->options . ' WHERE %i IN ( ' . implode( ',', array_fill( 0, count( $option_names ), '%s' ) ) . ' ) ', - array_merge( [ 'option_value', 'option_name', 'option_name' ], $option_names ) + array_merge( [ 'option_value', 'option_name', 'option_name' ], $option_names ), ), - ARRAY_A + ARRAY_A, ); $data = []; diff --git a/inc/class-upgrade.php b/inc/class-upgrade.php index 3ea7da39622..45f1ee2fffc 100644 --- a/inc/class-upgrade.php +++ b/inc/class-upgrade.php @@ -314,8 +314,8 @@ protected function upgrade_36() { $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE %i LIKE %s AND autoload IN ("on", "yes")', - [ $wpdb->options, 'option_name', 'wpseo_sitemap_%' ] - ) + [ $wpdb->options, 'option_name', 'wpseo_sitemap_%' ], + ), ); } @@ -358,8 +358,8 @@ private function upgrade_47() { $wpdb->query( $wpdb->prepare( 'UPDATE ' . $wpdb->postmeta . ' SET meta_key = %s WHERE meta_key = "yst_is_cornerstone"', - WPSEO_Cornerstone_Filter::META_NAME - ) + WPSEO_Cornerstone_Filter::META_NAME, + ), ); } @@ -398,9 +398,9 @@ protected function upgrade_49() { $meta_key, 'meta_value', '%wpseo-dismiss-about%', - ] + ], ), - ARRAY_A + ARRAY_A, ); if ( empty( $usermetas ) ) { @@ -452,8 +452,8 @@ protected function upgrade_50() { $wpdb->prepare( "DELETE FROM %i WHERE %i = '_yst_content_links_processed'", - [ $wpdb->postmeta, 'meta_key' ] - ) + [ $wpdb->postmeta, 'meta_key' ], + ), ); } @@ -658,8 +658,8 @@ protected function upgrade_90() { $wpdb->prepare( 'DELETE FROM %i WHERE %i LIKE %s', - [ $wpdb->options, 'option_name', 'wpseo_sitemap_%' ] - ) + [ $wpdb->options, 'option_name', 'wpseo_sitemap_%' ], + ), ); } @@ -743,8 +743,8 @@ public function upgrade_125() { $wpdb->prepare( 'DELETE FROM %i WHERE %i = %s', - [ $wpdb->usermeta, 'meta_key', 'wp_yoast_promo_hide_premium_upsell_admin_block' ] - ) + [ $wpdb->usermeta, 'meta_key', 'wp_yoast_promo_hide_premium_upsell_admin_block' ], + ), ); // Removes the WordPress update notification, because it is no longer necessary when WordPress 5.3 is released. @@ -1012,7 +1012,7 @@ private function upgrade_189() { WPSEO_Options::set( 'should_redirect_after_install_free', false ); // We're adding a hardcoded time here, so that in the future we can be able to identify whether the user did see the Installation Success page or not. // If they did, they wouldn't have this hardcoded value in that option, but rather (roughly) the timestamp of the moment they saw it. - WPSEO_Options::set( 'activation_redirect_timestamp_free', 1652258756 ); + WPSEO_Options::set( 'activation_redirect_timestamp_free', 1_652_258_756 ); // Transfer the Social URLs. $other = []; @@ -1218,7 +1218,7 @@ public function clean_up_private_taxonomies_for_141() { 'object_type', 'object_sub_type', ], - $private_taxonomies + $private_taxonomies, ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches. @@ -1230,8 +1230,8 @@ public function clean_up_private_taxonomies_for_141() { AND %i IN (" . implode( ', ', array_fill( 0, count( $private_taxonomies ), '%s' ) ) . ')', - $replacements - ) + $replacements, + ), ); $wpdb->show_errors = $show_errors; @@ -1255,8 +1255,8 @@ private function reset_permalinks_of_attachments_for_141() { $wpdb->query( $wpdb->prepare( "UPDATE %i SET %i = NULL WHERE %i = 'post' AND %i = 'attachment'", - [ Model::get_table_name( 'Indexable' ), 'permalink', 'object_type', 'object_sub_type' ] - ) + [ Model::get_table_name( 'Indexable' ), 'permalink', 'object_type', 'object_sub_type' ], + ), ); $wpdb->show_errors = $show_errors; @@ -1335,8 +1335,8 @@ private function remove_sitemap_validators() { $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE %i LIKE %s', - [ $wpdb->options, 'option_name', 'wpseo_sitemap%validator%' ] - ) + [ $wpdb->options, 'option_name', 'wpseo_sitemap%validator%' ], + ), ); } @@ -1357,9 +1357,9 @@ protected function get_option_from_database( $option_name ) { $results = $wpdb->get_results( $wpdb->prepare( 'SELECT %i FROM %i WHERE %i = %s', - [ 'option_value', $wpdb->options, 'option_name', $option_name ] + [ 'option_value', $wpdb->options, 'option_name', $option_name ], ), - ARRAY_A + ARRAY_A, ); if ( ! empty( $results ) ) { @@ -1402,9 +1402,7 @@ protected function cleanup_option_data( $option_name ) { * @return void */ protected function save_option_setting( $source_data, $source_setting, $target_setting = null ) { - if ( $target_setting === null ) { - $target_setting = $source_setting; - } + $target_setting ??= $source_setting; if ( isset( $source_data[ $source_setting ] ) ) { WPSEO_Options::set( $target_setting, $source_data[ $source_setting ] ); @@ -1433,7 +1431,7 @@ private function migrate_woocommerce_archive_setting_to_shop_page() { WPSEO_Meta::set_value( 'title', $option_title, - $shop_page_id + $shop_page_id, ); WPSEO_Options::set( 'title-ptarchive-product', '' ); @@ -1447,7 +1445,7 @@ private function migrate_woocommerce_archive_setting_to_shop_page() { WPSEO_Meta::set_value( 'metadesc', $option_metadesc, - $shop_page_id + $shop_page_id, ); WPSEO_Options::set( 'metadesc-ptarchive-product', '' ); @@ -1461,7 +1459,7 @@ private function migrate_woocommerce_archive_setting_to_shop_page() { WPSEO_Meta::set_value( 'bctitle', $option_bctitle, - $shop_page_id + $shop_page_id, ); WPSEO_Options::set( 'bctitle-ptarchive-product', '' ); @@ -1475,7 +1473,7 @@ private function migrate_woocommerce_archive_setting_to_shop_page() { WPSEO_Meta::set_value( 'meta-robots-noindex', $option_noindex, - $shop_page_id + $shop_page_id, ); WPSEO_Options::set( 'noindex-ptarchive-product', false ); @@ -1614,8 +1612,8 @@ public function remove_indexable_rows_for_non_public_post_types() { "DELETE FROM %i WHERE %i = 'post' AND %i IS NOT NULL", - [ $indexable_table, 'object_type', 'object_sub_type' ] - ) + [ $indexable_table, 'object_type', 'object_sub_type' ], + ), ); } else { @@ -1634,9 +1632,9 @@ public function remove_indexable_rows_for_non_public_post_types() { 'object_sub_type', 'object_sub_type', ], - $included_post_types - ) - ) + $included_post_types, + ), + ), ); } @@ -1668,8 +1666,8 @@ public function remove_indexable_rows_for_non_public_taxonomies() { "DELETE FROM %i WHERE %i = 'term' AND %i IS NOT NULL", - [ $indexable_table, 'object_type', 'object_sub_type' ] - ) + [ $indexable_table, 'object_type', 'object_sub_type' ], + ), ); } else { @@ -1688,9 +1686,9 @@ public function remove_indexable_rows_for_non_public_taxonomies() { 'object_sub_type', 'object_sub_type', ], - $included_taxonomies - ) - ) + $included_taxonomies, + ), + ), ); } @@ -1729,9 +1727,9 @@ protected function deduplicate_unindexed_indexable_rows() { object_type HAVING count(*) > 1", - [ Model::get_table_name( 'Indexable' ) ] + [ Model::get_table_name( 'Indexable' ) ], ), - ARRAY_A + ARRAY_A, ); if ( empty( $duplicates ) ) { @@ -1780,8 +1778,8 @@ protected function clean_unindexed_indexable_rows_with_no_object_id() { WHERE %i = 'unindexed' AND %i NOT IN ( 'home-page', 'date-archive', 'post-type-archive', 'system-page' ) AND %i IS NULL", - [ Model::get_table_name( 'Indexable' ), 'post_status', 'object_type', 'object_id' ] - ) + [ Model::get_table_name( 'Indexable' ), 'post_status', 'object_type', 'object_id' ], + ), ); $wpdb->show_errors = $show_errors; @@ -1808,8 +1806,8 @@ protected function remove_indexable_rows_for_disabled_authors_archive() { $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE %i = 'user'", - [ Model::get_table_name( 'Indexable' ), 'object_type' ] - ) + [ Model::get_table_name( 'Indexable' ), 'object_type' ], + ), ); $wpdb->show_errors = $show_errors; @@ -1829,7 +1827,7 @@ protected function get_indexable_deduplication_query_for_type( $object_type, $du $duplicates, static function ( $duplicate ) use ( $object_type ) { return $duplicate['object_type'] === $object_type; - } + }, ); if ( empty( $filtered_duplicates ) ) { @@ -1845,7 +1843,7 @@ static function ( $duplicate ) use ( $object_type ) { 'object_id', ], array_values( $object_ids ), - array_values( $newest_indexable_ids ) + array_values( $newest_indexable_ids ), ); $replacements[] = $object_type; @@ -1858,7 +1856,7 @@ static function ( $duplicate ) use ( $object_type ) { %i IN ( ' . implode( ', ', array_fill( 0, count( $filtered_duplicates ), '%d' ) ) . ' ) AND id NOT IN ( ' . implode( ', ', array_fill( 0, count( $filtered_duplicates ), '%d' ) ) . ' ) AND object_type = %s', - $replacements + $replacements, ); } diff --git a/inc/class-wpseo-admin-bar-menu.php b/inc/class-wpseo-admin-bar-menu.php index 8d3dc24a8ae..c96068d9d90 100644 --- a/inc/class-wpseo-admin-bar-menu.php +++ b/inc/class-wpseo-admin-bar-menu.php @@ -156,9 +156,7 @@ public function __construct( * @return bool True if SEO score is enabled, false otherwise. */ protected function get_is_seo_enabled() { - if ( $this->is_seo_enabled === null ) { - $this->is_seo_enabled = ( new WPSEO_Metabox_Analysis_SEO() )->is_enabled(); - } + $this->is_seo_enabled ??= ( new WPSEO_Metabox_Analysis_SEO() )->is_enabled(); return $this->is_seo_enabled; } @@ -169,9 +167,7 @@ protected function get_is_seo_enabled() { * @return bool True if readability is enabled, false otherwise. */ protected function get_is_readability_enabled() { - if ( $this->is_readability_enabled === null ) { - $this->is_readability_enabled = ( new WPSEO_Metabox_Analysis_Readability() )->is_enabled(); - } + $this->is_readability_enabled ??= ( new WPSEO_Metabox_Analysis_Readability() )->is_enabled(); return $this->is_readability_enabled; } @@ -182,9 +178,7 @@ protected function get_is_readability_enabled() { * @return bool|Indexable The indexable, false if none could be found. */ protected function get_current_indexable() { - if ( $this->current_indexable === null ) { - $this->current_indexable = $this->indexable_repository->for_current_page(); - } + $this->current_indexable ??= $this->indexable_repository->for_current_page(); return $this->current_indexable; } @@ -237,7 +231,7 @@ public function add_menu( WP_Admin_Bar $wp_admin_bar ) { 'id' => 'wpseo-seo-focus-keyword', 'title' => __( 'Focus keyphrase: ', 'wordpress-seo' ) . '' . $focus_keyword . '', 'meta' => [ 'tabindex' => '0' ], - ] + ], ); $wp_admin_bar->add_menu( [ @@ -246,7 +240,7 @@ public function add_menu( WP_Admin_Bar $wp_admin_bar ) { 'title' => __( 'SEO score', 'wordpress-seo' ) . ': ' . $this->score_icon_helper->for_seo( $indexable, 'adminbar-sub-menu-score' ) ->present(), 'meta' => [ 'tabindex' => '0' ], - ] + ], ); } @@ -258,7 +252,7 @@ public function add_menu( WP_Admin_Bar $wp_admin_bar ) { 'title' => __( 'Readability', 'wordpress-seo' ) . ': ' . $this->score_icon_helper->for_readability( $indexable->readability_score, 'adminbar-sub-menu-score' ) ->present(), 'meta' => [ 'tabindex' => '0' ], - ] + ], ); } @@ -273,7 +267,7 @@ public function add_menu( WP_Admin_Bar $wp_admin_bar ) { 'tabindex' => '0', 'target' => '_blank', ], - ] + ], ); } } @@ -623,12 +617,12 @@ protected function add_premium_link( WP_Admin_Bar $wp_admin_bar ) { 'title' => sprintf( '%2$s', esc_url( $link ), - $button_label + $button_label, ), 'meta' => [ 'tabindex' => '0', ], - ] + ], ); } @@ -660,7 +654,7 @@ protected function add_brand_insights_link( WP_Admin_Bar $wp_admin_bar ) { 'tabindex' => '0', 'target' => '_blank', ], - ] + ], ); } @@ -919,7 +913,7 @@ protected function get_notification_counter( $notification_count ) { '
    %s
    ', ( $notification_count ) ? '' : ' wpseo-no-adminbar-notifications', $notification_count, - $counter_screen_reader_text + $counter_screen_reader_text, ); } @@ -942,9 +936,9 @@ protected function get_notification_popup() { 'There is a new notification.', 'There are new notifications.', $new_notifications_count, - 'wordpress-seo' + 'wordpress-seo', ), - $new_notifications_count + $new_notifications_count, ); return '
    ' . $notification . '
    '; diff --git a/inc/class-wpseo-content-images.php b/inc/class-wpseo-content-images.php index bae91bc6360..9e23a91f625 100644 --- a/inc/class-wpseo-content-images.php +++ b/inc/class-wpseo-content-images.php @@ -87,9 +87,7 @@ private function get_img_tag_source( $image ) { * @return string The content of the supplied post. */ private function get_post_content( $post_id, $post ) { - if ( $post === null ) { - $post = get_post( $post_id ); - } + $post ??= get_post( $post_id ); if ( $post === null ) { return ''; diff --git a/inc/class-wpseo-custom-taxonomies.php b/inc/class-wpseo-custom-taxonomies.php index e1fb1816b2a..3d2f1bae719 100644 --- a/inc/class-wpseo-custom-taxonomies.php +++ b/inc/class-wpseo-custom-taxonomies.php @@ -40,7 +40,7 @@ public static function get_custom_taxonomies() { array_push( self::$custom_taxonomies, self::add_custom_taxonomies_prefix( $custom_taxonomy ), - self::add_custom_taxonomies_description_prefix( $custom_taxonomy ) + self::add_custom_taxonomies_description_prefix( $custom_taxonomy ), ); } } diff --git a/inc/class-wpseo-image-utils.php b/inc/class-wpseo-image-utils.php index 6875aab7a08..dbb0b7d0bf2 100644 --- a/inc/class-wpseo-image-utils.php +++ b/inc/class-wpseo-image-utils.php @@ -26,9 +26,7 @@ public static function get_attachment_by_url( $url ) { static $uploads; - if ( $uploads === null ) { - $uploads = wp_get_upload_dir(); - } + $uploads ??= wp_get_upload_dir(); // Don't try to do this for external URLs. if ( strpos( $url, $uploads['baseurl'] ) !== 0 ) { @@ -188,7 +186,7 @@ public static function has_usable_file_size( $image ) { * * @param int $max_bytes The maximum weight (in bytes) of an image. */ - $max_size = apply_filters( 'wpseo_image_image_weight_limit', 2097152 ); + $max_size = apply_filters( 'wpseo_image_image_weight_limit', 2_097_152 ); // We cannot check without a path, so assume it's fine. if ( ! isset( $image['path'] ) ) { @@ -268,9 +266,7 @@ protected static function get_full_size_image_data( $attachment_id ) { public static function get_absolute_path( $path ) { static $uploads; - if ( $uploads === null ) { - $uploads = wp_get_upload_dir(); - } + $uploads ??= wp_get_upload_dir(); // Add the uploads basedir if the path does not start with it. if ( empty( $uploads['error'] ) && strpos( $path, $uploads['basedir'] ) !== 0 ) { diff --git a/inc/class-wpseo-meta.php b/inc/class-wpseo-meta.php index 5a4a136cbbd..61691cd4e87 100644 --- a/inc/class-wpseo-meta.php +++ b/inc/class-wpseo-meta.php @@ -267,7 +267,7 @@ public static function init() { register_meta( 'post', self::$meta_prefix . $key, - [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ] ] + [ 'sanitize_callback' => [ self::class, 'sanitize_post_meta' ] ], ); // Set the $fields_index property for efficiency. @@ -398,7 +398,7 @@ public static function sanitize_post_meta( $meta_value, $meta_key ) { case ( $meta_key === self::$meta_prefix . 'linkdex' ): $int = WPSEO_Utils::validate_int( $meta_value ); if ( $int !== false && $int >= 0 ) { - $clean = strval( $int ); // Convert to string to make sure default check works. + $clean = (string) $int; // Convert to string to make sure default check works. } break; @@ -721,7 +721,7 @@ public static function replace_meta( $old_metakey, $new_metakey, $delete_old = f ;", $old_metakey, $wpdb->esc_like( self::$meta_prefix . '%' ), - self::$meta_prefix . 'linkdex' + self::$meta_prefix . 'linkdex', ); $oldies = $wpdb->get_results( $query ); @@ -773,7 +773,7 @@ public static function clean_up() { ;", self::$meta_prefix . 'meta-robots', self::$meta_prefix . 'meta-robots-noindex', - self::$meta_prefix . 'meta-robots-nofollow' + self::$meta_prefix . 'meta-robots-nofollow', ); $oldies = $wpdb->get_results( $query ); @@ -825,7 +825,7 @@ public static function clean_up() { $query[] = $wpdb->prepare( "( meta_key = %s AND meta_value NOT IN ( '" . implode( "','", esc_sql( $valid ) ) . "' ) )", - self::$meta_prefix . $key + self::$meta_prefix . $key, ); unset( $valid ); } @@ -833,13 +833,13 @@ public static function clean_up() { $query[] = $wpdb->prepare( '( meta_key = %s AND meta_value = %s )', self::$meta_prefix . $key, - $field_def['default_value'] + $field_def['default_value'], ); } else { $query[] = $wpdb->prepare( "( meta_key = %s AND meta_value = '' )", - self::$meta_prefix . $key + self::$meta_prefix . $key, ); } } @@ -877,7 +877,7 @@ public static function clean_up() { */ $query = $wpdb->prepare( "SELECT meta_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s", - self::$meta_prefix . 'meta-robots-adv' + self::$meta_prefix . 'meta-robots-adv', ); $oldies = $wpdb->get_results( $query ); diff --git a/inc/class-wpseo-rank.php b/inc/class-wpseo-rank.php index a8b9c101519..8f0e514045f 100644 --- a/inc/class-wpseo-rank.php +++ b/inc/class-wpseo-rank.php @@ -168,27 +168,27 @@ public function get_drop_down_label() { self::NO_FOCUS => sprintf( /* translators: %s expands to the SEO score */ __( 'SEO: %s', 'wordpress-seo' ), - __( 'No Focus Keyphrase', 'wordpress-seo' ) + __( 'No Focus Keyphrase', 'wordpress-seo' ), ), self::BAD => sprintf( /* translators: %s expands to the SEO score */ __( 'SEO: %s', 'wordpress-seo' ), - __( 'Needs improvement', 'wordpress-seo' ) + __( 'Needs improvement', 'wordpress-seo' ), ), self::OK => sprintf( /* translators: %s expands to the SEO score */ __( 'SEO: %s', 'wordpress-seo' ), - __( 'OK', 'wordpress-seo' ) + __( 'OK', 'wordpress-seo' ), ), self::GOOD => sprintf( /* translators: %s expands to the SEO score */ __( 'SEO: %s', 'wordpress-seo' ), - __( 'Good', 'wordpress-seo' ) + __( 'Good', 'wordpress-seo' ), ), self::NO_INDEX => sprintf( /* translators: %s expands to the SEO score */ __( 'SEO: %s', 'wordpress-seo' ), - __( 'Post Noindexed', 'wordpress-seo' ) + __( 'Post Noindexed', 'wordpress-seo' ), ), ]; @@ -205,22 +205,22 @@ public function get_drop_down_readability_labels() { self::BAD => sprintf( /* translators: %s expands to the readability score */ __( 'Readability: %s', 'wordpress-seo' ), - __( 'Needs improvement', 'wordpress-seo' ) + __( 'Needs improvement', 'wordpress-seo' ), ), self::OK => sprintf( /* translators: %s expands to the readability score */ __( 'Readability: %s', 'wordpress-seo' ), - __( 'OK', 'wordpress-seo' ) + __( 'OK', 'wordpress-seo' ), ), self::GOOD => sprintf( /* translators: %s expands to the readability score */ __( 'Readability: %s', 'wordpress-seo' ), - __( 'Good', 'wordpress-seo' ) + __( 'Good', 'wordpress-seo' ), ), self::NO_FOCUS => sprintf( /* translators: %s expands to the readability score */ __( 'Readability: %s', 'wordpress-seo' ), - __( 'Not analyzed', 'wordpress-seo' ) + __( 'Not analyzed', 'wordpress-seo' ), ), ]; @@ -237,17 +237,17 @@ public function get_drop_down_inclusive_language_labels() { self::BAD => sprintf( /* translators: %s expands to the inclusive language score */ __( 'Inclusive language: %s', 'wordpress-seo' ), - __( 'Needs improvement', 'wordpress-seo' ) + __( 'Needs improvement', 'wordpress-seo' ), ), self::OK => sprintf( /* translators: %s expands to the inclusive language score */ __( 'Inclusive language: %s', 'wordpress-seo' ), - __( 'Potentially non-inclusive', 'wordpress-seo' ) + __( 'Potentially non-inclusive', 'wordpress-seo' ), ), self::GOOD => sprintf( /* translators: %s expands to the inclusive language score */ __( 'Inclusive language: %s', 'wordpress-seo' ), - __( 'Good', 'wordpress-seo' ) + __( 'Good', 'wordpress-seo' ), ), ]; diff --git a/inc/class-wpseo-replace-vars.php b/inc/class-wpseo-replace-vars.php index b4ebbd76306..8f0f679b488 100644 --- a/inc/class-wpseo-replace-vars.php +++ b/inc/class-wpseo-replace-vars.php @@ -181,7 +181,7 @@ public function replace( $text, $args, $omit = [] ) { array_keys( $replacements ), // Make sure to exclude replacement values that are arrays e.g. coming from a custom field serialized value. array_filter( array_values( $replacements ), 'is_scalar' ), - $text + $text, ); } @@ -1306,7 +1306,7 @@ public function get_replacement_variables_with_labels() { $replacement_variables = array_filter( array_merge( self::$help_texts['basic'], self::$help_texts['advanced'] ), [ $this, 'is_not_prefixed' ], - ARRAY_FILTER_USE_KEY + ARRAY_FILTER_USE_KEY, ); $hidden = $this->get_hidden_replace_vars(); @@ -1323,8 +1323,8 @@ static function ( WPSEO_Replacement_Variable $replacement_variable ) use ( $hidd 'hidden' => in_array( $name, $hidden, true ), ]; }, - array_merge( $replacement_variables, $custom_variables ) - ) + array_merge( $replacement_variables, $custom_variables ), + ), ); } @@ -1339,7 +1339,7 @@ public function get_replacement_variables_list() { $replacement_variables = array_merge( $this->get_replacement_variables(), WPSEO_Custom_Fields::get_custom_fields(), - WPSEO_Custom_Taxonomies::get_custom_taxonomies() + WPSEO_Custom_Taxonomies::get_custom_taxonomies(), ); return array_map( [ $this, 'format_replacement_variable' ], $replacement_variables ); @@ -1463,7 +1463,7 @@ private static function set_basic_help_texts() { $separator_description = sprintf( $separator_description, // 'wp_title()' - 'wp_title()' + 'wp_title()', ); $replacement_variables = [ @@ -1621,7 +1621,7 @@ private function get_term_hierarchy() { return rtrim( get_term_parents_list( $this->args->term_id, $this->args->taxonomy, $args ), - $separator + $separator, ); } diff --git a/inc/class-wpseo-utils.php b/inc/class-wpseo-utils.php index 17541e60e17..914320d702d 100644 --- a/inc/class-wpseo-utils.php +++ b/inc/class-wpseo-utils.php @@ -198,10 +198,10 @@ public static function sanitize_url( $value, $allowed_protocols = [ 'http', 'htt $parts['host'] = preg_replace( '`[^a-z0-9-.:\[\]\\x80-\\xff]`', '', - strtolower( $parts['host'] ) + strtolower( $parts['host'] ), ); - $url .= $parts['host'] . ( isset( $parts['port'] ) ? ':' . intval( $parts['port'] ) : '' ); + $url .= $parts['host'] . ( isset( $parts['port'] ) ? ':' . (int) $parts['port'] : '' ); } if ( isset( $parts['path'] ) && strpos( $parts['path'], '/' ) === 0 ) { @@ -219,7 +219,7 @@ public static function sanitize_url( $value, $allowed_protocols = [ 'http', 'htt $parsed_query = array_combine( self::sanitize_encoded_text_field( array_keys( $parsed_query ) ), - self::sanitize_encoded_text_field( array_values( $parsed_query ) ) + self::sanitize_encoded_text_field( array_values( $parsed_query ) ), ); $url = add_query_arg( $parsed_query, $url ); @@ -235,7 +235,7 @@ public static function sanitize_url( $value, $allowed_protocols = [ 'http', 'htt static function ( $octects ) { return strtolower( $octects[0] ); }, - $url + $url, ); } @@ -551,14 +551,14 @@ public static function calc( $number1, $action, $number2, $round = false, $decim if ( isset( $result ) ) { if ( $compare === false ) { if ( $round === true ) { - $result = round( floatval( $result ), $decimals ); + $result = round( (float) $result, $decimals ); if ( $decimals === 0 ) { $result = (int) $result; } } else { // phpcs:ignore Universal.Operators.StrictComparisons -- Purposeful loose comparison. - $result = ( intval( $result ) == $result ) ? intval( $result ) : floatval( $result ); + $result = ( intval( $result ) == $result ) ? (int) $result : (float) $result; } } diff --git a/inc/options/class-wpseo-option-ms.php b/inc/options/class-wpseo-option-ms.php index c47b179d017..b0b38e15f22 100644 --- a/inc/options/class-wpseo-option-ms.php +++ b/inc/options/class-wpseo-option-ms.php @@ -206,7 +206,7 @@ protected function validate_option( $dirty, $clean, $old ) { $key, // Suffix-ID for the error message box. /* translators: %1$s expands to the option name and %2$sexpands to Yoast SEO */ sprintf( __( '%1$s is not a valid choice for who should be allowed access to the %2$s settings. Value reset to the default.', 'wordpress-seo' ), esc_html( sanitize_text_field( $dirty[ $key ] ) ), 'Yoast SEO' ), // The error message. - 'error' // Message type. + 'error', // Message type. ); } break; @@ -229,9 +229,9 @@ protected function validate_option( $dirty, $clean, $old ) { . sprintf( /* translators: %s is the ID number of a blog. */ esc_html__( 'This must be an existing blog. Blog %s does not exist or has been marked as deleted.', 'wordpress-seo' ), - '' . esc_html( sanitize_text_field( $dirty[ $key ] ) ) . '' + '' . esc_html( sanitize_text_field( $dirty[ $key ] ) ) . '', ), // The error message. - 'error' // Message type. + 'error', // Message type. ); } unset( $exists ); @@ -241,7 +241,7 @@ protected function validate_option( $dirty, $clean, $old ) { $this->group_name, // Slug title of the setting. $key, // Suffix-ID for the error message box. esc_html__( 'The default blog setting must be the numeric blog id of the blog you want to use as default.', 'wordpress-seo' ) . '
    ' . esc_html__( 'No numeric value was received.', 'wordpress-seo' ), // The error message. - 'error' // Message type. + 'error', // Message type. ); } unset( $int ); diff --git a/inc/options/class-wpseo-option-titles.php b/inc/options/class-wpseo-option-titles.php index e3a9bb5fab4..4b127c97c8b 100644 --- a/inc/options/class-wpseo-option-titles.php +++ b/inc/options/class-wpseo-option-titles.php @@ -543,7 +543,7 @@ protected function validate_option( $dirty, $clean, $old ) { $key, // Suffix-id for the error message box. /* translators: %s expands to a post type. */ sprintf( __( 'Please select a valid taxonomy for post type "%s"', 'wordpress-seo' ), $post_type ), // The error message. - 'error' // Message type. + 'error', // Message type. ); } } @@ -581,7 +581,7 @@ protected function validate_option( $dirty, $clean, $old ) { '_' . $tax, // Suffix-ID for the error message box. /* translators: %s expands to a taxonomy slug. */ sprintf( __( 'Please select a valid post type for taxonomy "%s"', 'wordpress-seo' ), $tax ), // The error message. - 'error' // Message type. + 'error', // Message type. ); unset( $tax ); } diff --git a/inc/options/class-wpseo-options.php b/inc/options/class-wpseo-options.php index 225d3601051..790a4261ab9 100644 --- a/inc/options/class-wpseo-options.php +++ b/inc/options/class-wpseo-options.php @@ -561,9 +561,7 @@ protected static function add_ms_option( $option ) { protected static function is_multisite() { static $is_multisite; - if ( $is_multisite === null ) { - $is_multisite = is_multisite(); - } + $is_multisite ??= is_multisite(); return $is_multisite; } diff --git a/inc/sitemaps/class-post-type-sitemap-provider.php b/inc/sitemaps/class-post-type-sitemap-provider.php index d018ad0b3ce..a621464e18d 100644 --- a/inc/sitemaps/class-post-type-sitemap-provider.php +++ b/inc/sitemaps/class-post-type-sitemap-provider.php @@ -365,7 +365,7 @@ protected function get_first_links( $post_type ) { $page_on_front_id = (int) get_option( 'page_on_front' ); if ( $page_on_front_id > 0 ) { $front_page = $this->get_url( - get_post( $page_on_front_id ) + get_post( $page_on_front_id ), ); } @@ -404,7 +404,7 @@ protected function get_first_links( $post_type ) { $archive_url = apply_filters( 'wpseo_sitemap_post_type_archive_link', $this->get_post_type_archive_link( $post_type ), - $post_type + $post_type, ); } @@ -626,7 +626,7 @@ protected function get_url( $post ) { $url['loc'] = apply_filters( 'wpseo_xml_sitemap_post_url', get_permalink( $post ), $post ); $link_type = YoastSEO()->helpers->url->get_link_type( wp_parse_url( $url['loc'] ), - $this->get_parsed_home_url() + $this->get_parsed_home_url(), ); /* @@ -696,7 +696,7 @@ private function get_all_dates_using_with_clause( $post_type, $max_entries ) { 'post_modified_gmt', 'ordering', $max_entries, - ] + ], ); //phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here. @@ -714,8 +714,8 @@ private function get_all_dates_using_with_clause( $post_type, $max_entries ) { FROM %i WHERE MOD(n, %d) = 0; ', - $replacements - ) + $replacements, + ), ); } @@ -744,7 +744,7 @@ private function get_all_dates( $post_type, $max_entries ) { $post_type, $max_entries, 'post_modified_gmt', - ] + ], ); return $wpdb->get_col( @@ -759,8 +759,8 @@ private function get_all_dates( $post_type, $max_entries ) { AND ( @rownum:=@rownum+1 ) %% %d = 0 ORDER BY %i ASC ', - $replacements - ) + $replacements, + ), ); } } diff --git a/inc/sitemaps/class-sitemap-image-parser.php b/inc/sitemaps/class-sitemap-image-parser.php index 58d8ec5a952..1a883999708 100644 --- a/inc/sitemaps/class-sitemap-image-parser.php +++ b/inc/sitemaps/class-sitemap-image-parser.php @@ -257,7 +257,7 @@ protected function parse_galleries( $content, $post_id = 0 ) { $id = $post_id; if ( ! empty( $gallery['id'] ) ) { - $id = intval( $gallery['id'] ); + $id = (int) $gallery['id']; } // Forked from core gallery_shortcode() to have exact same logic. R. @@ -467,7 +467,7 @@ protected function get_gallery_attachments_for_included( $included_ids ) { [ 'posts_per_page' => count( $ids_to_include ), 'post__in' => $ids_to_include, - ] + ], ); $gallery_attachments = []; diff --git a/inc/sitemaps/class-sitemaps-cache-validator.php b/inc/sitemaps/class-sitemaps-cache-validator.php index 166d181fc3f..49c2463e330 100644 --- a/inc/sitemaps/class-sitemaps-cache-validator.php +++ b/inc/sitemaps/class-sitemaps-cache-validator.php @@ -110,8 +110,8 @@ public static function truncate_type( $type, $prefix = '', $postfix = '' ) { throw new OutOfRangeException( __( 'Trying to build the sitemap cache key, but the postfix and prefix combination leaves too little room to do this. You are probably requesting a page that is way out of the expected range.', - 'wordpress-seo' - ) + 'wordpress-seo', + ), ); } @@ -195,8 +195,8 @@ public static function cleanup_database( $type = null, $validator = null ) { $wpdb->prepare( //phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized. 'DELETE FROM %i WHERE ' . implode( ' OR ', array_fill( 0, count( $where ), '%s' ) ), - array_merge( [ $wpdb->options ], $where ) - ) + array_merge( [ $wpdb->options ], $where ), + ), ); wp_cache_delete( 'alloptions', 'options' ); diff --git a/inc/sitemaps/class-sitemaps.php b/inc/sitemaps/class-sitemaps.php index dd8f350343a..c7653259387 100644 --- a/inc/sitemaps/class-sitemaps.php +++ b/inc/sitemaps/class-sitemaps.php @@ -194,8 +194,8 @@ public function register_xsl( $name, $building_function, $rewrite = '' ) { * @return void */ public function set_n( $current_page ) { - if ( is_scalar( $current_page ) && intval( $current_page ) > 0 ) { - $this->current_page = intval( $current_page ); + if ( is_scalar( $current_page ) && (int) $current_page > 0 ) { + $this->current_page = (int) $current_page; } } @@ -270,7 +270,7 @@ public function redirect( $query ) { if ( get_query_var( 'sitemap_n' ) === '1' || get_query_var( 'sitemap_n' ) === '0' ) { wp_safe_redirect( home_url( "/$type-sitemap.xml" ), 301, 'Yoast SEO' ); - exit; + exit(); } $this->set_n( get_query_var( 'sitemap_n' ) ); @@ -539,7 +539,7 @@ public static function get_last_modified_gmt( $post_types, $return_all = false ) [ 'post_type', 'date', - ] + ], ); //phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here. @@ -555,8 +555,8 @@ public static function get_last_modified_gmt( $post_types, $return_all = false ) GROUP BY %i ORDER BY %i DESC ', - $replacements - ) + $replacements, + ), ); foreach ( $dates as $obj ) { diff --git a/inc/sitemaps/class-taxonomy-sitemap-provider.php b/inc/sitemaps/class-taxonomy-sitemap-provider.php index e69f0e79182..064c808572e 100644 --- a/inc/sitemaps/class-taxonomy-sitemap-provider.php +++ b/inc/sitemaps/class-taxonomy-sitemap-provider.php @@ -202,7 +202,7 @@ public function get_sitemap_links( $type, $max_entries, $current_page ) { 'update_term_meta_cache' => false, 'offset' => $offset, 'number' => $steps, - ] + ], ); // If there are no terms fetched for this range, we are on an invalid page. @@ -227,7 +227,7 @@ public function get_sitemap_links( $type, $max_entries, $current_page ) { 'post_status', ], $post_statuses, - [ 'post_password' ] + [ 'post_password' ], ); /** @@ -279,8 +279,8 @@ public function get_sitemap_links( $type, $max_entries, $current_page ) { WHERE p.%i IN (' . implode( ', ', array_fill( 0, count( $post_statuses ), '%s' ) ) . ") AND p.%i = '' ", - $current_replacements - ) + $current_replacements, + ), ); if ( $this->include_images ) { diff --git a/lib/migrations/adapter.php b/lib/migrations/adapter.php index 561f5e53ad2..ff70d587e46 100644 --- a/lib/migrations/adapter.php +++ b/lib/migrations/adapter.php @@ -604,7 +604,7 @@ public function add_index( $table_name, $column_name, $options = [] ) { ( $unique === true ) ? 'UNIQUE ' : '', $this->identifier( $index_name ), $this->identifier( $table_name ), - \implode( ', ', $cols ) + \implode( ', ', $cols ), ); return $this->execute_ddl( $sql ); @@ -658,7 +658,7 @@ public function add_timestamps( $table_name, $created_column_name, $updated_colu 'null' => false, 'default' => 'CURRENT_TIMESTAMP', 'extra' => 'ON UPDATE CURRENT_TIMESTAMP', - ] + ], ); return $created_at && $updated_at; @@ -813,7 +813,7 @@ public function type_to_sql( $type, $options = [] ) { else { $column_type_sql .= \sprintf( "('%s')", - \implode( "','", \array_map( [ $this, 'quote_string' ], $values ) ) + \implode( "','", \array_map( [ $this, 'quote_string' ], $values ) ), ); } } diff --git a/lib/migrations/table.php b/lib/migrations/table.php index 8ad2228cb42..5ca7adf27aa 100644 --- a/lib/migrations/table.php +++ b/lib/migrations/table.php @@ -150,7 +150,7 @@ public function timestamps( $created_column_name = 'created_at', $updated_column 'null' => false, 'default' => 'CURRENT_TIMESTAMP', 'extra' => 'ON UPDATE CURRENT_TIMESTAMP', - ] + ], ); } @@ -208,7 +208,7 @@ public function finish( $wants_sql = false ) { 'unsigned' => true, 'null' => false, 'auto_increment' => true, - ] + ], ); $create_table_sql .= $primary_id->to_sql() . ",\n"; } diff --git a/lib/model.php b/lib/model.php index eb767b1d1d5..2b8b6c693ee 100644 --- a/lib/model.php +++ b/lib/model.php @@ -484,7 +484,7 @@ protected function has_many_through( $associated_class_name, $join_class_name = "{$associated_table_name}.{$associated_table_id_column}", '=', "{$join_table_name}.{$key_to_associated_table}", - ] + ], ) ->where( "{$join_table_name}.{$key_to_base_table}", $this->{$base_table_id_column} ); } diff --git a/lib/orm.php b/lib/orm.php index 8681f22dc20..afaff54c56a 100644 --- a/lib/orm.php +++ b/lib/orm.php @@ -281,7 +281,7 @@ protected static function execute( $query, $parameters = [] ) { $parameters, static function ( $parameter ) { return $parameter !== null; - } + }, ); if ( ! empty( $parameters ) ) { $query = $wpdb->prepare( $query, $parameters ); @@ -1080,7 +1080,7 @@ protected function add_condition( $type, $fragment, $values = [] ) { [ self::CONDITION_FRAGMENT => $fragment, self::CONDITION_VALUES => $values, - ] + ], ); return $this; @@ -1742,7 +1742,7 @@ protected function build_select() { $this->build_order_by(), $this->build_limit(), $this->build_offset(), - ] + ], ); } @@ -2439,7 +2439,7 @@ public function delete_many() { 'DELETE FROM', $this->quote_identifier( $this->table_name ), $this->build_where(), - ] + ], ); return self::execute( $query, $this->values ); diff --git a/readme.txt b/readme.txt index ba48f80a4a1..4254ed6cd4e 100644 --- a/readme.txt +++ b/readme.txt @@ -309,17 +309,17 @@ Release date: 2026-02-17 #### Enhancements -* Adds `html-react-parser` dependency for improved HTML string handling in React components. -* Adds `images` array to FAQ and How-to blocks attributes for explicit image handling. -* Migrates FAQ block's question/answer fields from array-based formats to HTML strings for better compatibility with WordPress components. -* Migrates How-to block's step name/text fields from array-based formats to HTML strings for better compatibility with WordPress components. -* Updates the design for the search appearance mode switcher. +* Introduces an `images` array attribute to FAQ and How-to blocks to allow for explicit image handling. +* Integrates `html-react-parser` to improve HTML string handling within React components. +* Migrates FAQ block question and answer fields from arrays to HTML strings to improve compatibility with WordPress components. +* Migrates How-to block step name and text fields from arrays to HTML strings to improve compatibility with WordPress components. +* Refines the design of the search appearance mode switcher. #### Bugfixes -* Fixes a bug where inline link icon was missing when editing a sync pattern in the block editor with WordPress 6.9. +* Fixes a bug where the inline link icon was missing when editing a synced pattern in the Block Editor on WordPress 6.9. * Fixes a bug where the AI Optimize buttons remained active even when another button had been pressed. -* Fixes a bug where the _subheading distribution assessment_ threw an error when there was some text with no subheadings plus a block containing a subheading (like the Yoast Table of contents block). +* Fixes a bug where the subheading distribution assessment threw an error when the content contained text without subheadings followed by a block that included a subheading (such as a Table of Contents block). #### Other diff --git a/src/actions/configuration/first-time-configuration-action.php b/src/actions/configuration/first-time-configuration-action.php index 6b518540d68..6fb3595b47f 100644 --- a/src/actions/configuration/first-time-configuration-action.php +++ b/src/actions/configuration/first-time-configuration-action.php @@ -151,7 +151,7 @@ public function set_person_social_profiles( $params ) { static function ( $key ) { return $key !== 'user_id'; }, - \ARRAY_FILTER_USE_KEY + \ARRAY_FILTER_USE_KEY, ); $failures = $this->social_profiles_helper->set_person_social_profiles( $params['user_id'], $social_profiles ); diff --git a/src/actions/importing/aioseo/aioseo-cleanup-action.php b/src/actions/importing/aioseo/aioseo-cleanup-action.php index 13195bfba72..c2f90288223 100644 --- a/src/actions/importing/aioseo/aioseo-cleanup-action.php +++ b/src/actions/importing/aioseo/aioseo-cleanup-action.php @@ -130,7 +130,7 @@ public function cleanup_postmeta_query() { // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. return $this->wpdb->prepare( "DELETE FROM {$table} WHERE meta_key IN (" . \implode( ', ', \array_fill( 0, \count( $meta_keys_to_delete ), '%s' ) ) . ')', - $meta_keys_to_delete + $meta_keys_to_delete, ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared } diff --git a/src/actions/importing/aioseo/aioseo-posts-importing-action.php b/src/actions/importing/aioseo/aioseo-posts-importing-action.php index 71bdbdbc1ec..eff92311c25 100644 --- a/src/actions/importing/aioseo/aioseo-posts-importing-action.php +++ b/src/actions/importing/aioseo/aioseo-posts-importing-action.php @@ -461,7 +461,7 @@ public function query( $limit = false, $just_detect = false ) { // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. return $this->wpdb->prepare( "SELECT {$select_statement} FROM {$table} WHERE id > %d ORDER BY id{$limit_statement}", - $replacements + $replacements, ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared } diff --git a/src/actions/importing/aioseo/aioseo-validate-data-action.php b/src/actions/importing/aioseo/aioseo-validate-data-action.php index 17817f1d1f2..72a3f03aa2e 100644 --- a/src/actions/importing/aioseo/aioseo-validate-data-action.php +++ b/src/actions/importing/aioseo/aioseo-validate-data-action.php @@ -142,7 +142,7 @@ public function validate_aioseo_table() { $aioseo_columns = $this->wpdb->get_col( "SHOW COLUMNS FROM {$table}", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. - 0 + 0, ); return $needed_data === \array_intersect( $needed_data, $aioseo_columns ); diff --git a/src/actions/indexing/indexable-post-indexation-action.php b/src/actions/indexing/indexable-post-indexation-action.php index d549a2b9842..88854226147 100644 --- a/src/actions/indexing/indexable-post-indexation-action.php +++ b/src/actions/indexing/indexable-post-indexation-action.php @@ -143,7 +143,7 @@ protected function get_count_query() { $excluded_post_statuses = $this->post_helper->get_excluded_post_statuses(); $replacements = \array_merge( $post_types, - $excluded_post_statuses + $excluded_post_statuses, ); $replacements[] = $this->version; @@ -160,7 +160,7 @@ protected function get_count_query() { SELECT I.object_id from $indexable_table as I WHERE I.object_type = 'post' AND I.version = %d )", - $replacements + $replacements, ); } @@ -178,7 +178,7 @@ protected function get_select_query( $limit = false ) { $excluded_post_statuses = $this->post_helper->get_excluded_post_statuses(); $replacements = \array_merge( $post_types, - $excluded_post_statuses + $excluded_post_statuses, ); $replacements[] = $this->version; @@ -201,7 +201,7 @@ protected function get_select_query( $limit = false ) { WHERE I.object_type = 'post' AND I.version = %d ) $limit_query", - $replacements + $replacements, ); } } diff --git a/src/actions/indexing/indexable-term-indexation-action.php b/src/actions/indexing/indexable-term-indexation-action.php index b1dbfd356a8..0d0b54d24ea 100644 --- a/src/actions/indexing/indexable-term-indexation-action.php +++ b/src/actions/indexing/indexable-term-indexation-action.php @@ -148,7 +148,7 @@ protected function get_count_query() { AND I.version = %d WHERE I.object_id IS NULL AND taxonomy IN ($taxonomies_placeholders)", - $replacements + $replacements, ); } @@ -191,7 +191,7 @@ protected function get_select_query( $limit = false ) { WHERE I.object_id IS NULL AND taxonomy IN ($placeholders) $limit_query", - $replacements + $replacements, ); } } diff --git a/src/actions/indexing/post-link-indexing-action.php b/src/actions/indexing/post-link-indexing-action.php index 3f96a5ec9a8..0d13a0741be 100644 --- a/src/actions/indexing/post-link-indexing-action.php +++ b/src/actions/indexing/post-link-indexing-action.php @@ -63,7 +63,7 @@ static function ( $post ) { 'content' => $post->post_content, ]; }, - $posts + $posts, ); } @@ -94,7 +94,7 @@ protected function get_count_query() { WHERE ( I.object_id IS NULL OR L.post_id IS NOT NULL ) AND P.post_status = 'publish' AND P.post_type IN (" . \implode( ', ', \array_fill( 0, \count( $public_post_types ), '%s' ) ) . ')', - $public_post_types + $public_post_types, ); } @@ -136,7 +136,7 @@ protected function get_select_query( $limit = false ) { AND P.post_status = 'publish' AND P.post_type IN (" . \implode( ', ', \array_fill( 0, \count( $public_post_types ), '%s' ) ) . ") $limit_query", - $replacements + $replacements, ); } } diff --git a/src/actions/indexing/term-link-indexing-action.php b/src/actions/indexing/term-link-indexing-action.php index 3e6a4bc3a31..68a3432f5aa 100644 --- a/src/actions/indexing/term-link-indexing-action.php +++ b/src/actions/indexing/term-link-indexing-action.php @@ -67,7 +67,7 @@ static function ( $term ) { 'content' => $term->description, ]; }, - $terms + $terms, ); } @@ -97,7 +97,7 @@ protected function get_count_query() { AND I.link_count IS NOT NULL WHERE I.object_id IS NULL AND T.taxonomy IN ($placeholders)", - $public_taxonomies + $public_taxonomies, ); } @@ -136,7 +136,7 @@ protected function get_select_query( $limit = false ) { WHERE I.object_id IS NULL AND T.taxonomy IN (" . \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) ) . ") $limit_query", - $replacements + $replacements, ); } } diff --git a/src/actions/wincher/wincher-keyphrases-action.php b/src/actions/wincher/wincher-keyphrases-action.php index dd51f5b6658..5b469682ba2 100644 --- a/src/actions/wincher/wincher-keyphrases-action.php +++ b/src/actions/wincher/wincher-keyphrases-action.php @@ -85,7 +85,7 @@ public function track_keyphrases( $keyphrases, $limits ) { try { $endpoint = \sprintf( self::KEYPHRASES_ADD_URL, - $this->options_helper->get( 'wincher_website_id' ) + $this->options_helper->get( 'wincher_website_id' ), ); // Enforce arrrays to ensure a consistent way of preparing the request. @@ -113,8 +113,8 @@ static function ( $keyphrase ) { 'groups' => [], ]; }, - $keyphrases - ) + $keyphrases, + ), ); $results = $this->client->post( $endpoint, WPSEO_Utils::format_json_encode( $formatted_keyphrases ) ); @@ -131,12 +131,12 @@ static function ( $keyphrase ) { 'keyword' => $keyphrase['keyword'], ]; }, - $results['data'] + $results['data'], ); $results['data'] = \array_combine( \array_column( $results['data'], 'keyword' ), - \array_values( $results['data'] ) + \array_values( $results['data'] ), ); return $this->to_result_object( $results ); @@ -160,7 +160,7 @@ public function untrack_keyphrase( $keyphrase_id ) { $endpoint = \sprintf( self::KEYPHRASE_DELETE_URL, $this->options_helper->get( 'wincher_website_id' ), - $keyphrase_id + $keyphrase_id, ); $this->client->delete( $endpoint ); @@ -188,9 +188,7 @@ public function untrack_keyphrase( $keyphrase_id ) { */ public function get_tracked_keyphrases( $used_keyphrases = null, $permalink = null, $start_at = null ) { try { - if ( $used_keyphrases === null ) { - $used_keyphrases = $this->collect_all_keyphrases(); - } + $used_keyphrases ??= $this->collect_all_keyphrases(); // If we still have no keyphrases the API will return an error, so // don't even bother sending a request. @@ -199,13 +197,13 @@ public function get_tracked_keyphrases( $used_keyphrases = null, $permalink = nu [ 'data' => [], 'status' => 200, - ] + ], ); } $endpoint = \sprintf( self::KEYPHRASES_URL, - $this->options_helper->get( 'wincher_website_id' ) + $this->options_helper->get( 'wincher_website_id' ), ); $results = $this->client->post( @@ -215,11 +213,11 @@ public function get_tracked_keyphrases( $used_keyphrases = null, $permalink = nu 'keywords' => $used_keyphrases, 'url' => $permalink, 'start_at' => $start_at, - ] + ], ), [ 'timeout' => 60, - ] + ], ); if ( ! \array_key_exists( 'data', $results ) ) { @@ -231,7 +229,7 @@ public function get_tracked_keyphrases( $used_keyphrases = null, $permalink = nu // Extract the positional data and assign it to the keyphrase. $results['data'] = \array_combine( \array_column( $results['data'], 'keyword' ), - \array_values( $results['data'] ) + \array_values( $results['data'] ), ); return $this->to_result_object( $results ); @@ -287,7 +285,7 @@ protected function collect_all_keyphrases() { ->where_not_equal( 'post_status', 'trash' ) ->distinct() ->find_array(), - 'primary_focus_keyword' + 'primary_focus_keyword', ); /** @@ -314,7 +312,7 @@ protected function filter_results_by_used_keyphrases( $results, $used_keyphrases $results, static function ( $result ) use ( $used_keyphrases ) { return \in_array( $result['keyword'], \array_map( 'strtolower', $used_keyphrases ), true ); - } + }, ); } diff --git a/src/ai-authorization/application/token-manager.php b/src/ai-authorization/application/token-manager.php index 42b6eadddc9..8b62c724360 100644 --- a/src/ai-authorization/application/token-manager.php +++ b/src/ai-authorization/application/token-manager.php @@ -156,8 +156,8 @@ public function token_invalidate( string $user_id ): void { new Request( '/token/invalidate', $request_body, - $request_headers - ) + $request_headers, + ), ); } catch ( Unauthorized_Exception | Forbidden_Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch -- Reason: Ignored on purpose. // If the credentials in our request were already invalid, our job is done and we continue to remove the tokens client-side. diff --git a/src/ai-authorization/infrastructure/access-token-user-meta-repository.php b/src/ai-authorization/infrastructure/access-token-user-meta-repository.php index 2dc0a3f02b5..41315edc16a 100644 --- a/src/ai-authorization/infrastructure/access-token-user-meta-repository.php +++ b/src/ai-authorization/infrastructure/access-token-user-meta-repository.php @@ -57,7 +57,7 @@ public function store_token( int $user_id, string $value ): void { $this->user_helper->update_meta( $user_id, self::META_KEY, - $value + $value, ); } /** diff --git a/src/ai-authorization/infrastructure/code-verifier-user-meta-repository.php b/src/ai-authorization/infrastructure/code-verifier-user-meta-repository.php index f281da8381d..be5a1dad6d5 100644 --- a/src/ai-authorization/infrastructure/code-verifier-user-meta-repository.php +++ b/src/ai-authorization/infrastructure/code-verifier-user-meta-repository.php @@ -55,7 +55,7 @@ public function store_code_verifier( int $user_id, string $code, int $created_at [ 'code' => $code, 'created_at' => $created_at, - ] + ], ); } diff --git a/src/ai-authorization/infrastructure/refresh-token-user-meta-repository.php b/src/ai-authorization/infrastructure/refresh-token-user-meta-repository.php index ae7da309465..948940c1931 100644 --- a/src/ai-authorization/infrastructure/refresh-token-user-meta-repository.php +++ b/src/ai-authorization/infrastructure/refresh-token-user-meta-repository.php @@ -57,7 +57,7 @@ public function store_token( int $user_id, string $value ): void { $this->user_helper->update_meta( $user_id, self::META_KEY, - $value + $value, ); } /** diff --git a/src/ai-authorization/user-interface/abstract-callback-route.php b/src/ai-authorization/user-interface/abstract-callback-route.php index 5129b19db2e..e104c1b17cd 100644 --- a/src/ai-authorization/user-interface/abstract-callback-route.php +++ b/src/ai-authorization/user-interface/abstract-callback-route.php @@ -101,7 +101,7 @@ public function callback( WP_REST_Request $request ): WP_REST_Response { [ 'message' => 'Tokens successfully stored.', 'code_verifier' => $code_verifier->get_code(), - ] + ], ); } diff --git a/src/ai-authorization/user-interface/callback-route.php b/src/ai-authorization/user-interface/callback-route.php index ac22f0005b4..a653b93ef1a 100644 --- a/src/ai-authorization/user-interface/callback-route.php +++ b/src/ai-authorization/user-interface/callback-route.php @@ -54,7 +54,7 @@ public function register_routes() { ], 'callback' => [ $this, 'callback' ], 'permission_callback' => '__return_true', - ] + ], ); } } diff --git a/src/ai-authorization/user-interface/refresh-callback-route.php b/src/ai-authorization/user-interface/refresh-callback-route.php index b9d81cee557..ccb58b55843 100644 --- a/src/ai-authorization/user-interface/refresh-callback-route.php +++ b/src/ai-authorization/user-interface/refresh-callback-route.php @@ -54,7 +54,7 @@ public function register_routes() { ], 'callback' => [ $this, 'callback' ], 'permission_callback' => '__return_true', - ] + ], ); } } diff --git a/src/ai-consent/user-interface/consent-route.php b/src/ai-consent/user-interface/consent-route.php index e5dca97430f..922896a6d2b 100644 --- a/src/ai-consent/user-interface/consent-route.php +++ b/src/ai-consent/user-interface/consent-route.php @@ -97,7 +97,7 @@ public function register_routes() { ], 'callback' => [ $this, 'consent' ], 'permission_callback' => [ $this, 'check_permissions' ], - ] + ], ); } @@ -110,7 +110,7 @@ public function register_routes() { */ public function consent( WP_REST_Request $request ): WP_REST_Response { $user_id = \get_current_user_id(); - $consent = \boolval( $request->get_param( 'consent' ) ); + $consent = (bool) $request->get_param( 'consent' ); try { if ( $consent ) { diff --git a/src/ai-free-sparks/user-interface/free-sparks-route.php b/src/ai-free-sparks/user-interface/free-sparks-route.php index 8e2c6a27320..664d6922d97 100644 --- a/src/ai-free-sparks/user-interface/free-sparks-route.php +++ b/src/ai-free-sparks/user-interface/free-sparks-route.php @@ -66,7 +66,7 @@ public function register_routes() { 'methods' => 'POST', 'callback' => [ $this, 'start' ], 'permission_callback' => [ $this, 'can_edit_posts' ], - ] + ], ); } diff --git a/src/ai-generator/domain/suggestions-bucket.php b/src/ai-generator/domain/suggestions-bucket.php index 71399b567ed..478c07e2d9c 100644 --- a/src/ai-generator/domain/suggestions-bucket.php +++ b/src/ai-generator/domain/suggestions-bucket.php @@ -43,7 +43,7 @@ public function to_array() { static function ( $item ) { return $item->get_value(); }, - $this->suggestions + $this->suggestions, ); } } diff --git a/src/ai-generator/user-interface/bust-subscription-cache-route.php b/src/ai-generator/user-interface/bust-subscription-cache-route.php index 2a9a87ce7a2..33f830a286e 100644 --- a/src/ai-generator/user-interface/bust-subscription-cache-route.php +++ b/src/ai-generator/user-interface/bust-subscription-cache-route.php @@ -73,7 +73,7 @@ public function register_routes() { 'args' => [], 'callback' => [ $this, 'bust_subscription_cache' ], 'permission_callback' => [ $this, 'check_permissions' ], - ] + ], ); } diff --git a/src/ai-generator/user-interface/get-suggestions-route.php b/src/ai-generator/user-interface/get-suggestions-route.php index 5135ddcb85e..03e4b657dad 100644 --- a/src/ai-generator/user-interface/get-suggestions-route.php +++ b/src/ai-generator/user-interface/get-suggestions-route.php @@ -131,7 +131,7 @@ public function register_routes() { ], 'callback' => [ $this, 'get_suggestions' ], 'permission_callback' => [ $this, 'check_permissions' ], - ] + ], ); } @@ -152,7 +152,7 @@ public function get_suggestions( WP_REST_Request $request ): WP_REST_Response { $request->get_param( 'focus_keyphrase' ), $request->get_param( 'language' ), $request->get_param( 'platform' ), - $request->get_param( 'editor' ) + $request->get_param( 'editor' ), ); } catch ( Remote_Request_Exception $e ) { $message = [ @@ -164,7 +164,7 @@ public function get_suggestions( WP_REST_Request $request ): WP_REST_Response { } return new WP_REST_Response( $message, - $e->getCode() + $e->getCode(), ); } catch ( RuntimeException $e ) { return new WP_REST_Response( 'Failed to get suggestions.', 500 ); diff --git a/src/ai-generator/user-interface/get-usage-route.php b/src/ai-generator/user-interface/get-usage-route.php index 32f5acfa27a..adf1e640a29 100644 --- a/src/ai-generator/user-interface/get-usage-route.php +++ b/src/ai-generator/user-interface/get-usage-route.php @@ -102,7 +102,7 @@ public function register_routes() { ], 'callback' => [ $this, 'get_usage' ], 'permission_callback' => [ $this, 'check_permissions' ], - ] + ], ); } @@ -135,7 +135,7 @@ public function get_usage( $request ): WP_REST_Response { } return new WP_REST_Response( $message, - $e->getCode() + $e->getCode(), ); } diff --git a/src/ai-http-request/application/request-handler.php b/src/ai-http-request/application/request-handler.php index efd51bfc23a..757298d1a12 100644 --- a/src/ai-http-request/application/request-handler.php +++ b/src/ai-http-request/application/request-handler.php @@ -76,7 +76,7 @@ public function handle( Request $request ): Response { $request->get_action_path(), $request->get_body(), $request->get_headers(), - $request->is_post() + $request->is_post(), ); $response = $this->response_parser->parse( $api_response ); diff --git a/src/alerts/application/default-seo-data/default-seo-data-alert.php b/src/alerts/application/default-seo-data/default-seo-data-alert.php index 60af7692a26..915e7eaf7cd 100644 --- a/src/alerts/application/default-seo-data/default-seo-data-alert.php +++ b/src/alerts/application/default-seo-data/default-seo-data-alert.php @@ -160,7 +160,7 @@ private function get_default_seo_data_notification( $has_enough_posts_with_defau 'id' => self::NOTIFICATION_ID, 'type' => Yoast_Notification::WARNING, 'capabilities' => [ 'wpseo_manage_options' ], - ] + ], ); } @@ -197,7 +197,7 @@ private function get_default_seo_data_message( $has_enough_posts_with_default_ti '', '', '', - '' + '', ); } } diff --git a/src/alerts/application/ping-other-admins/ping-other-admins-alert.php b/src/alerts/application/ping-other-admins/ping-other-admins-alert.php index 25b0866fd08..b2cab981aee 100644 --- a/src/alerts/application/ping-other-admins/ping-other-admins-alert.php +++ b/src/alerts/application/ping-other-admins/ping-other-admins-alert.php @@ -160,7 +160,7 @@ private function get_ping_other_admins_notification(): Yoast_Notification { 'capabilities' => [ 'wpseo_manage_options' ], 'priority' => 20, 'resolve_nonce' => \wp_create_nonce( 'wpseo-resolve-alert-nonce' ), - ] + ], ); } @@ -173,7 +173,7 @@ private function get_message() { $message = \sprintf( /* translators: %1$s expands to "Yoast SEO". */ \esc_html__( 'Looks like you’re new here. %1$s makes it easy to optimize your website for search engines. Want to keep your site healthy and easier to find? Sign up below to receive practical emails to get you started!', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); $notification_text = '

    ' . $message . '

    '; diff --git a/src/alerts/user-interface/default-seo-data/default-seo-data-cron-callback-integration.php b/src/alerts/user-interface/default-seo-data/default-seo-data-cron-callback-integration.php index d30dd12bac0..1117fbcc3f3 100644 --- a/src/alerts/user-interface/default-seo-data/default-seo-data-cron-callback-integration.php +++ b/src/alerts/user-interface/default-seo-data/default-seo-data-cron-callback-integration.php @@ -67,7 +67,7 @@ public function register_hooks() { [ $this, 'detect_default_seo_data_in_recent', - ] + ], ); } diff --git a/src/alerts/user-interface/resolve-alert-route.php b/src/alerts/user-interface/resolve-alert-route.php index 5b2a49cdd2a..0e24582890b 100644 --- a/src/alerts/user-interface/resolve-alert-route.php +++ b/src/alerts/user-interface/resolve-alert-route.php @@ -64,7 +64,7 @@ public function resolve_alert() { \wp_send_json_error( [ 'message' => 'Security check failed.', - ] + ], ); return; } @@ -73,7 +73,7 @@ public function resolve_alert() { \wp_send_json_error( [ 'message' => 'Alert ID is missing.', - ] + ], ); return; } @@ -86,7 +86,7 @@ public function resolve_alert() { \wp_send_json_success( [ 'message' => 'Alert resolved successfully.', - ] + ], ); } } diff --git a/src/analytics/application/missing-indexables-collector.php b/src/analytics/application/missing-indexables-collector.php index 957d4127367..28d71b53093 100644 --- a/src/analytics/application/missing-indexables-collector.php +++ b/src/analytics/application/missing-indexables-collector.php @@ -66,7 +66,7 @@ private function add_additional_indexing_actions() { $indexing_actions, static function ( $indexing_action ) { return \is_a( $indexing_action, Indexation_Action_Interface::class ); - } + }, ); } } diff --git a/src/analytics/domain/missing-indexable-bucket.php b/src/analytics/domain/missing-indexable-bucket.php index f384c5a1c65..391da0059d7 100644 --- a/src/analytics/domain/missing-indexable-bucket.php +++ b/src/analytics/domain/missing-indexable-bucket.php @@ -42,7 +42,7 @@ public function to_array() { static function ( $item ) { return $item->to_array(); }, - $this->missing_indexable_counts + $this->missing_indexable_counts, ); } } diff --git a/src/analytics/domain/to-be-cleaned-indexable-bucket.php b/src/analytics/domain/to-be-cleaned-indexable-bucket.php index abaf1f886c9..5aa5cf3cafb 100644 --- a/src/analytics/domain/to-be-cleaned-indexable-bucket.php +++ b/src/analytics/domain/to-be-cleaned-indexable-bucket.php @@ -42,7 +42,7 @@ public function to_array() { static function ( $item ) { return $item->to_array(); }, - $this->to_be_cleaned_indexable_counts + $this->to_be_cleaned_indexable_counts, ); } } diff --git a/src/analytics/user-interface/last-completed-indexation-integration.php b/src/analytics/user-interface/last-completed-indexation-integration.php index 6360b70f86c..ec7eef1b395 100644 --- a/src/analytics/user-interface/last-completed-indexation-integration.php +++ b/src/analytics/user-interface/last-completed-indexation-integration.php @@ -42,7 +42,7 @@ public function register_hooks(): void { 'maybe_set_indexables_unindexed_calculated', ], 10, - 2 + 2, ); } diff --git a/src/builders/indexable-author-builder.php b/src/builders/indexable-author-builder.php index 6977ed9e6f0..ba1d3ed6289 100644 --- a/src/builders/indexable-author-builder.php +++ b/src/builders/indexable-author-builder.php @@ -163,7 +163,7 @@ protected function find_alternative_image( Indexable $indexable ) { [ 'size' => 500, 'scheme' => 'https', - ] + ], ); if ( $gravatar_image ) { return [ @@ -208,8 +208,8 @@ protected function get_object_timestamps( $author_id ) { AND p.%i = '' AND p.%i = %d ", - $replacements - ) + $replacements, + ), ); //phpcs:enable } diff --git a/src/builders/indexable-builder.php b/src/builders/indexable-builder.php index ac556a05f5a..719b90a2f9b 100644 --- a/src/builders/indexable-builder.php +++ b/src/builders/indexable-builder.php @@ -278,7 +278,7 @@ protected function maybe_build_author_indexable( $author_id ) { $author_indexable = $this->indexable_repository->find_by_id_and_type( $author_id, 'user', - false + false, ); if ( ! $author_indexable || $this->version_manager->indexable_needs_upgrade( $author_indexable ) ) { // Try to build the author. @@ -398,7 +398,7 @@ public function build( $indexable, $defaults = null ) { 'object_type' => $indexable->object_type, 'post_status' => 'unindexed', 'version' => 0, - ] + ], ); // If we already had an existing indexable, mark it as unindexed. We cannot rely on its validity anymore. $indexable->post_status = 'unindexed'; diff --git a/src/builders/indexable-home-page-builder.php b/src/builders/indexable-home-page-builder.php index bb803fa3e05..86bf4edf0d1 100644 --- a/src/builders/indexable-home-page-builder.php +++ b/src/builders/indexable-home-page-builder.php @@ -140,8 +140,8 @@ protected function get_object_timestamps() { AND p.%i = '' AND p.%i = 'post' ", - $replacements - ) + $replacements, + ), ); //phpcs:enable } diff --git a/src/builders/indexable-link-builder.php b/src/builders/indexable-link-builder.php index 48520c7485d..3e04055b91a 100644 --- a/src/builders/indexable-link-builder.php +++ b/src/builders/indexable-link-builder.php @@ -254,14 +254,14 @@ protected function create_links( $indexable, $links, $images ) { function ( $link ) use ( $home_url, $indexable ) { return $this->create_internal_link( $link, $home_url, $indexable ); }, - $links + $links, ); // Filter out links to the same page with a fragment or query. $links = \array_filter( $links, function ( $link ) use ( $current_url ) { return $this->filter_link( $link, $current_url ); - } + }, ); $image_links = []; @@ -314,7 +314,7 @@ protected function create_internal_link( $url, $home_url, $indexable, $is_image 'type' => $link_type, 'indexable_id' => $indexable->id, 'post_id' => $indexable->object_id, - ] + ], ); $model->parsed_url = $parsed_url; @@ -503,7 +503,7 @@ protected function links_diff( $links_a, $links_b ) { $links_b, static function ( SEO_Links $link_a, SEO_Links $link_b ) { return \strcmp( $link_a->url, $link_b->url ); - } + }, ); } diff --git a/src/builders/indexable-post-builder.php b/src/builders/indexable-post-builder.php index e5d9c3efab5..2784f552169 100644 --- a/src/builders/indexable-post-builder.php +++ b/src/builders/indexable-post-builder.php @@ -133,7 +133,7 @@ public function build( $post_id, $indexable ) { $indexable->primary_focus_keyword_score = $this->get_keyword_score( $this->meta->get_value( 'focuskw', $post_id ), - (int) $this->meta->get_value( 'linkdex', $post_id ) + (int) $this->meta->get_value( 'linkdex', $post_id ), ); $indexable->readability_score = (int) $this->meta->get_value( 'content_score', $post_id ); @@ -142,7 +142,7 @@ public function build( $post_id, $indexable ) { $indexable->is_cornerstone = ( $this->meta->get_value( 'is_cornerstone', $post_id ) === '1' ); $indexable->is_robots_noindex = $this->get_robots_noindex( - (int) $this->meta->get_value( 'meta-robots-noindex', $post_id ) + (int) $this->meta->get_value( 'meta-robots-noindex', $post_id ), ); // Set additional meta-robots values. diff --git a/src/builders/indexable-post-type-archive-builder.php b/src/builders/indexable-post-type-archive-builder.php index 3d04aa5d5cc..1b4de3fde97 100644 --- a/src/builders/indexable-post-type-archive-builder.php +++ b/src/builders/indexable-post-type-archive-builder.php @@ -160,8 +160,8 @@ protected function get_object_timestamps( $post_type ) { AND p.%i = '' AND p.%i = %s ", - $replacements - ) + $replacements, + ), ); //phpcs:enable } diff --git a/src/builders/indexable-term-builder.php b/src/builders/indexable-term-builder.php index 3484a37dda5..78eb342161c 100644 --- a/src/builders/indexable-term-builder.php +++ b/src/builders/indexable-term-builder.php @@ -101,7 +101,7 @@ public function build( $term_id, $indexable ) { $indexable->primary_focus_keyword_score = $this->get_keyword_score( $this->get_meta_value( 'wpseo_focuskw', $term_meta ), - $this->get_meta_value( 'wpseo_linkdex', $term_meta ) + $this->get_meta_value( 'wpseo_linkdex', $term_meta ), ); $indexable->is_robots_noindex = $this->get_noindex_value( $this->get_meta_value( 'wpseo_noindex', $term_meta ) ); @@ -283,8 +283,8 @@ protected function get_object_timestamps( $term_id, $taxonomy ) { WHERE p.%i IN (' . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ") AND p.%i = '' ", - $replacements - ) + $replacements, + ), ); //phpcs:enable } diff --git a/src/commands/cleanup-command.php b/src/commands/cleanup-command.php index 7bbba3dedfa..dbc565c2bf0 100644 --- a/src/commands/cleanup-command.php +++ b/src/commands/cleanup-command.php @@ -98,10 +98,10 @@ public function cleanup( $args = null, $assoc_args = null ) { 'Cleaned up %1$d record.', 'Cleaned up %1$d records.', $total_removed, - 'wordpress-seo' + 'wordpress-seo', ), - $total_removed - ) + $total_removed, + ), ); } @@ -184,11 +184,11 @@ private function cleanup_current_site( $assoc_args ) { 'Cleaned up %1$d record from %2$s.', 'Cleaned up %1$d records from %2$s.', $total_removed, - 'wordpress-seo' + 'wordpress-seo', ), $total_removed, - $site_url - ) + $site_url, + ), ); return $total_removed; diff --git a/src/commands/index-command.php b/src/commands/index-command.php index ac612cd101f..4b860e16154 100644 --- a/src/commands/index-command.php +++ b/src/commands/index-command.php @@ -171,7 +171,7 @@ public static function get_namespace() { public function index( $args = null, $assoc_args = null ) { if ( ! $this->indexable_helper->should_index_indexables() ) { WP_CLI::log( - \__( 'Your WordPress environment is running on a non-production site. Indexables can only be created on production environments. Please check your `WP_ENVIRONMENT_TYPE` settings.', 'wordpress-seo' ) + \__( 'Your WordPress environment is running on a non-production site. Indexables can only be created on production environments. Please check your `WP_ENVIRONMENT_TYPE` settings.', 'wordpress-seo' ), ); return; @@ -282,14 +282,14 @@ protected function clear() { $wpdb->query( $wpdb->prepare( 'TRUNCATE TABLE %1$s', - Model::get_table_name( 'Indexable' ) - ) + Model::get_table_name( 'Indexable' ), + ), ); $wpdb->query( $wpdb->prepare( 'TRUNCATE TABLE %1$s', - Model::get_table_name( 'Indexable_Hierarchy' ) - ) + Model::get_table_name( 'Indexable_Hierarchy' ), + ), ); // phpcs:enable } diff --git a/src/config/badge-group-names.php b/src/config/badge-group-names.php index 59ae793cf76..e8ba39e87f6 100644 --- a/src/config/badge-group-names.php +++ b/src/config/badge-group-names.php @@ -53,9 +53,7 @@ public function is_still_eligible_for_new_badge( $group, $current_version = null $group_version = $this::GROUP_NAMES[ $group ]; - if ( $current_version === null ) { - $current_version = $this->version; - } + $current_version ??= $this->version; return (bool) \version_compare( $group_version, $current_version, '>' ); } diff --git a/src/config/conflicting-plugins.php b/src/config/conflicting-plugins.php index b6e2b67c6cd..769df5d65a0 100644 --- a/src/config/conflicting-plugins.php +++ b/src/config/conflicting-plugins.php @@ -105,7 +105,7 @@ public static function all_plugins() { self::OPEN_GRAPH_PLUGINS, self::XML_SITEMAPS_PLUGINS, self::CLOAKING_PLUGINS, - self::SEO_PLUGINS + self::SEO_PLUGINS, ); } } diff --git a/src/config/migrations/20171228151840_WpYoastIndexable.php b/src/config/migrations/20171228151840_WpYoastIndexable.php index 5ed29a66554..0b8d2020259 100644 --- a/src/config/migrations/20171228151840_WpYoastIndexable.php +++ b/src/config/migrations/20171228151840_WpYoastIndexable.php @@ -53,7 +53,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); // Object information. @@ -64,7 +64,7 @@ private function add_table() { 'unsigned' => true, 'null' => true, 'limit' => 11, - ] + ], ); $indexable_table->column( 'object_type', @@ -72,7 +72,7 @@ private function add_table() { [ 'null' => false, 'limit' => 32, - ] + ], ); $indexable_table->column( 'object_sub_type', @@ -80,7 +80,7 @@ private function add_table() { [ 'null' => true, 'limit' => 32, - ] + ], ); // Ownership. @@ -91,7 +91,7 @@ private function add_table() { 'unsigned' => true, 'null' => true, 'limit' => 11, - ] + ], ); $indexable_table->column( 'post_parent', @@ -100,7 +100,7 @@ private function add_table() { 'unsigned' => true, 'null' => true, 'limit' => 11, - ] + ], ); // Title and description. @@ -110,7 +110,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'description', 'text', [ 'null' => true ] ); $indexable_table->column( @@ -119,7 +119,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); // Post metadata: status, public, protected. @@ -129,7 +129,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'is_public', @@ -137,7 +137,7 @@ private function add_table() { [ 'null' => true, 'default' => null, - ] + ], ); $indexable_table->column( 'is_protected', 'boolean', [ 'default' => false ] ); $indexable_table->column( @@ -146,7 +146,7 @@ private function add_table() { [ 'null' => true, 'default' => null, - ] + ], ); $indexable_table->column( @@ -157,7 +157,7 @@ private function add_table() { 'null' => true, 'default' => null, 'limit' => 11, - ] + ], ); $indexable_table->column( 'canonical', 'mediumtext', [ 'null' => true ] ); @@ -169,7 +169,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'primary_focus_keyword_score', @@ -177,7 +177,7 @@ private function add_table() { [ 'null' => true, 'limit' => 3, - ] + ], ); $indexable_table->column( 'readability_score', @@ -185,7 +185,7 @@ private function add_table() { [ 'null' => true, 'limit' => 3, - ] + ], ); $indexable_table->column( 'is_cornerstone', 'boolean', [ 'default' => false ] ); @@ -196,7 +196,7 @@ private function add_table() { [ 'null' => true, 'default' => false, - ] + ], ); $indexable_table->column( 'is_robots_nofollow', @@ -204,7 +204,7 @@ private function add_table() { [ 'null' => true, 'default' => false, - ] + ], ); $indexable_table->column( 'is_robots_noarchive', @@ -212,7 +212,7 @@ private function add_table() { [ 'null' => true, 'default' => false, - ] + ], ); $indexable_table->column( 'is_robots_noimageindex', @@ -220,7 +220,7 @@ private function add_table() { [ 'null' => true, 'default' => false, - ] + ], ); $indexable_table->column( 'is_robots_nosnippet', @@ -228,7 +228,7 @@ private function add_table() { [ 'null' => true, 'default' => false, - ] + ], ); // Twitter. @@ -238,7 +238,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'twitter_image', 'mediumtext', [ 'null' => true ] ); $indexable_table->column( 'twitter_description', 'mediumtext', [ 'null' => true ] ); @@ -248,7 +248,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'twitter_image_source', @@ -256,7 +256,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); // Open-Graph. @@ -266,7 +266,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'open_graph_description', 'mediumtext', [ 'null' => true ] ); $indexable_table->column( 'open_graph_image', 'mediumtext', [ 'null' => true ] ); @@ -276,7 +276,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'open_graph_image_source', @@ -284,7 +284,7 @@ private function add_table() { [ 'null' => true, 'limit' => 191, - ] + ], ); $indexable_table->column( 'open_graph_image_meta', 'text', [ 'null' => true ] ); @@ -295,7 +295,7 @@ private function add_table() { [ 'null' => true, 'limit' => 11, - ] + ], ); $indexable_table->column( 'incoming_link_count', @@ -303,7 +303,7 @@ private function add_table() { [ 'null' => true, 'limit' => 11, - ] + ], ); // Prominent words. @@ -315,7 +315,7 @@ private function add_table() { 'limit' => 11, 'unsigned' => true, 'default' => null, - ] + ], ); $indexable_table->finish(); @@ -341,7 +341,7 @@ private function add_indexes( $indexable_table_name ) { ], [ 'name' => 'object_type_and_sub_type', - ] + ], ); $this->add_index( @@ -349,7 +349,7 @@ private function add_indexes( $indexable_table_name ) { 'permalink_hash', [ 'name' => 'permalink_hash', - ] + ], ); } diff --git a/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php b/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php index e68f316b5a6..c65f83c7936 100644 --- a/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php +++ b/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php @@ -34,7 +34,7 @@ public function up() { 'unsigned' => true, 'null' => false, 'limit' => 11, - ] + ], ); $indexable_table->column( 'term_id', @@ -43,7 +43,7 @@ public function up() { 'unsigned' => true, 'null' => false, 'limit' => 11, - ] + ], ); $indexable_table->column( 'taxonomy', @@ -51,7 +51,7 @@ public function up() { [ 'null' => false, 'limit' => 32, - ] + ], ); // Executes the SQL to create the table. @@ -65,7 +65,7 @@ public function up() { ], [ 'name' => 'post_taxonomy', - ] + ], ); $this->add_index( @@ -76,7 +76,7 @@ public function up() { ], [ 'name' => 'post_term', - ] + ], ); $this->add_timestamps( $table_name ); diff --git a/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php b/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php index 6d36d1a56af..cd5478a6cf3 100644 --- a/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php +++ b/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php @@ -35,7 +35,7 @@ public function up() { 'unsigned' => true, 'null' => true, 'limit' => 11, - ] + ], ); $indexable_table->column( 'ancestor_id', @@ -45,7 +45,7 @@ public function up() { 'unsigned' => true, 'null' => true, 'limit' => 11, - ] + ], ); $indexable_table->column( 'depth', @@ -54,7 +54,7 @@ public function up() { 'unsigned' => true, 'null' => true, 'limit' => 11, - ] + ], ); $indexable_table->finish(); diff --git a/src/config/migrations/20200420073606_AddColumnsToIndexables.php b/src/config/migrations/20200420073606_AddColumnsToIndexables.php index 6b77bc10780..d39ac705b2c 100644 --- a/src/config/migrations/20200420073606_AddColumnsToIndexables.php +++ b/src/config/migrations/20200420073606_AddColumnsToIndexables.php @@ -34,7 +34,7 @@ public function up() { 'null' => false, 'limit' => 20, 'default' => $blog_id, - ] + ], ); } diff --git a/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php b/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php index 83fcb74c6b3..21a96dac33a 100644 --- a/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php +++ b/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php @@ -40,7 +40,7 @@ public function down() { [ 'null' => true, 'limit' => 191, - ] + ], ); } diff --git a/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php b/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php index 2633ae61549..aaac655fa81 100644 --- a/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php +++ b/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php @@ -45,31 +45,31 @@ public function down() { $this->get_table_name(), 'title', 'string', - $attr_limit_191 + $attr_limit_191, ); $this->change_column( $this->get_table_name(), 'opengraph_title', 'string', - $attr_limit_191 + $attr_limit_191, ); $this->change_column( $this->get_table_name(), 'twitter_title', 'string', - $attr_limit_191 + $attr_limit_191, ); $this->change_column( $this->get_table_name(), 'open_graph_image_source', 'string', - $attr_limit_191 + $attr_limit_191, ); $this->change_column( $this->get_table_name(), 'twitter_image_source', 'string', - $attr_limit_191 + $attr_limit_191, ); } diff --git a/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php b/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php index f4a702705f7..5884496c833 100644 --- a/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php +++ b/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php @@ -31,7 +31,7 @@ public function up() { ], [ 'name' => 'object_id_and_type', - ] + ], ); } @@ -49,7 +49,7 @@ public function down() { ], [ 'name' => 'object_id_and_type', - ] + ], ); } diff --git a/src/config/migrations/20200609154515_AddHasAncestorsColumn.php b/src/config/migrations/20200609154515_AddHasAncestorsColumn.php index 34adf8b2604..f2c1e55ba43 100644 --- a/src/config/migrations/20200609154515_AddHasAncestorsColumn.php +++ b/src/config/migrations/20200609154515_AddHasAncestorsColumn.php @@ -30,7 +30,7 @@ public function up() { 'boolean', [ 'default' => false, - ] + ], ); Wrapper::get_wpdb()->query( @@ -38,7 +38,7 @@ public function up() { UPDATE ' . Model::get_table_name( 'Indexable' ) . ' SET has_ancestors = 1 WHERE id IN ( SELECT indexable_id FROM ' . Model::get_table_name( 'Indexable_Hierarchy' ) . ' ) - ' + ', ); } diff --git a/src/config/migrations/20200616130143_ReplacePermalinkHashIndex.php b/src/config/migrations/20200616130143_ReplacePermalinkHashIndex.php index bfb4c359e25..4961fc22a90 100644 --- a/src/config/migrations/20200616130143_ReplacePermalinkHashIndex.php +++ b/src/config/migrations/20200616130143_ReplacePermalinkHashIndex.php @@ -37,7 +37,7 @@ public function up() { [ 'null' => true, 'limit' => 40, - ] + ], ); if ( $adapter->has_index( $table_name, [ 'permalink_hash' ], [ 'name' => 'permalink_hash' ] ) ) { @@ -48,7 +48,7 @@ public function up() { ], [ 'name' => 'permalink_hash', - ] + ], ); } @@ -61,7 +61,7 @@ public function up() { ], [ 'name' => 'permalink_hash_and_object_type', - ] + ], ); } } @@ -88,7 +88,7 @@ public function down() { ], [ 'name' => 'permalink_hash_and_object_type', - ] + ], ); } @@ -99,7 +99,7 @@ public function down() { [ 'null' => true, 'limit' => 191, - ] + ], ); if ( ! $adapter->has_index( $table_name, [ 'permalink_hash' ], [ 'name' => 'permalink_hash' ] ) ) { @@ -110,7 +110,7 @@ public function down() { ], [ 'name' => 'permalink_hash', - ] + ], ); } } diff --git a/src/config/migrations/20200617122511_CreateSEOLinksTable.php b/src/config/migrations/20200617122511_CreateSEOLinksTable.php index c9b2fb6bcb4..067b42641b9 100644 --- a/src/config/migrations/20200617122511_CreateSEOLinksTable.php +++ b/src/config/migrations/20200617122511_CreateSEOLinksTable.php @@ -38,7 +38,7 @@ public function up() { 'limit' => 20, 'unsigned' => true, 'auto_increment' => true, - ] + ], ); $table->column( 'url', 'string', [ 'limit' => 255 ] ); $table->column( @@ -47,7 +47,7 @@ public function up() { [ 'limit' => 20, 'unsigned' => true, - ] + ], ); $table->column( 'target_post_id', @@ -55,7 +55,7 @@ public function up() { [ 'limit' => 20, 'unsigned' => true, - ] + ], ); $table->column( 'type', 'string', [ 'limit' => 8 ] ); $table->finish(); diff --git a/src/config/migrations/20200702141921_CreateIndexableSubpagesIndex.php b/src/config/migrations/20200702141921_CreateIndexableSubpagesIndex.php index ba1d13c8361..0c4084f63ba 100644 --- a/src/config/migrations/20200702141921_CreateIndexableSubpagesIndex.php +++ b/src/config/migrations/20200702141921_CreateIndexableSubpagesIndex.php @@ -30,12 +30,12 @@ public function up() { [ 'null' => true, 'limit' => 20, - ] + ], ); $this->add_index( $this->get_table_name(), [ 'post_parent', 'object_type', 'post_status', 'object_id' ], - [ 'name' => 'subpages' ] + [ 'name' => 'subpages' ], ); } @@ -52,12 +52,12 @@ public function down() { [ 'null' => true, 'limit' => 191, - ] + ], ); $this->remove_index( $this->get_table_name(), [ 'post_parent', 'object_type', 'post_status', 'object_id' ], - [ 'name' => 'subpages' ] + [ 'name' => 'subpages' ], ); } diff --git a/src/config/migrations/20200728095334_AddIndexesForProminentWordsOnIndexables.php b/src/config/migrations/20200728095334_AddIndexesForProminentWordsOnIndexables.php index 51566ca5a3b..093259d9841 100644 --- a/src/config/migrations/20200728095334_AddIndexesForProminentWordsOnIndexables.php +++ b/src/config/migrations/20200728095334_AddIndexesForProminentWordsOnIndexables.php @@ -44,7 +44,7 @@ public function up() { $this->columns_with_index, [ 'name' => 'prominent_words', - ] + ], ); } } diff --git a/src/config/migrations/20201202144329_AddEstimatedReadingTime.php b/src/config/migrations/20201202144329_AddEstimatedReadingTime.php index f0d94cf3b78..8cdea8e0c05 100644 --- a/src/config/migrations/20201202144329_AddEstimatedReadingTime.php +++ b/src/config/migrations/20201202144329_AddEstimatedReadingTime.php @@ -32,7 +32,7 @@ public function up() { [ 'null' => true, 'default' => null, - ] + ], ); } diff --git a/src/config/migrations/20201216124002_ExpandIndexableIDColumnLengths.php b/src/config/migrations/20201216124002_ExpandIndexableIDColumnLengths.php index 5d46c997c4c..361ea495543 100644 --- a/src/config/migrations/20201216124002_ExpandIndexableIDColumnLengths.php +++ b/src/config/migrations/20201216124002_ExpandIndexableIDColumnLengths.php @@ -39,7 +39,7 @@ public function up() { $this->get_table_name(), $column, 'biginteger', - [ 'limit' => 20 ] + [ 'limit' => 20 ], ); } } diff --git a/src/config/migrations/20201216141134_ExpandPrimaryTermIDColumnLengths.php b/src/config/migrations/20201216141134_ExpandPrimaryTermIDColumnLengths.php index 9105bae72f0..f3a6137928a 100644 --- a/src/config/migrations/20201216141134_ExpandPrimaryTermIDColumnLengths.php +++ b/src/config/migrations/20201216141134_ExpandPrimaryTermIDColumnLengths.php @@ -38,7 +38,7 @@ public function up() { $this->get_table_name(), $column, 'biginteger', - [ 'limit' => 20 ] + [ 'limit' => 20 ], ); } } diff --git a/src/config/migrations/20210817092415_AddVersionColumnToIndexables.php b/src/config/migrations/20210817092415_AddVersionColumnToIndexables.php index 2d179abcd12..ddd6562e846 100644 --- a/src/config/migrations/20210817092415_AddVersionColumnToIndexables.php +++ b/src/config/migrations/20210817092415_AddVersionColumnToIndexables.php @@ -29,7 +29,7 @@ public function up() { 'integer', [ 'default' => 1, - ] + ], ); } @@ -41,7 +41,7 @@ public function up() { public function down() { $this->remove_column( $this->get_table_name(), - 'version' + 'version', ); } diff --git a/src/config/migrations/20211020091404_AddObjectTimestamps.php b/src/config/migrations/20211020091404_AddObjectTimestamps.php index eece2639781..271d53c9118 100644 --- a/src/config/migrations/20211020091404_AddObjectTimestamps.php +++ b/src/config/migrations/20211020091404_AddObjectTimestamps.php @@ -30,7 +30,7 @@ public function up() { [ 'null' => true, 'default' => null, - ] + ], ); $this->add_column( $this->get_table_name(), @@ -39,7 +39,7 @@ public function up() { [ 'null' => true, 'default' => null, - ] + ], ); $this->add_index( $this->get_table_name(), @@ -51,7 +51,7 @@ public function up() { ], [ 'name' => 'published_sitemap_index', - ] + ], ); } @@ -73,7 +73,7 @@ public function down() { ], [ 'name' => 'published_sitemap_index', - ] + ], ); } diff --git a/src/config/migrations/20230417083836_AddInclusiveLanguageScore.php b/src/config/migrations/20230417083836_AddInclusiveLanguageScore.php index ab2fdc7c30e..6792220eb43 100644 --- a/src/config/migrations/20230417083836_AddInclusiveLanguageScore.php +++ b/src/config/migrations/20230417083836_AddInclusiveLanguageScore.php @@ -32,7 +32,7 @@ public function up() { [ 'null' => true, 'limit' => 3, - ] + ], ); } diff --git a/src/config/migrations/20260105111111_AddSeoLinksIndex.php b/src/config/migrations/20260105111111_AddSeoLinksIndex.php index 3a4d7ea8209..94ac2b69b56 100644 --- a/src/config/migrations/20260105111111_AddSeoLinksIndex.php +++ b/src/config/migrations/20260105111111_AddSeoLinksIndex.php @@ -30,7 +30,7 @@ public function up() { 'url', [ 'name' => 'url_index', - ] + ], ); $this->add_index( @@ -38,7 +38,7 @@ public function up() { 'target_indexable_id', [ 'name' => 'target_indexable_id_index', - ] + ], ); } @@ -55,14 +55,14 @@ public function down() { 'url', [ 'name' => 'url_index', - ] + ], ); $this->remove_index( $table_name, 'target_indexable_id', [ 'name' => 'target_indexable_id_index', - ] + ], ); } diff --git a/src/config/oauth-client.php b/src/config/oauth-client.php index 5ba1ec22d87..09a653306f8 100644 --- a/src/config/oauth-client.php +++ b/src/config/oauth-client.php @@ -72,7 +72,7 @@ public function __construct( $tokens['expires'], $tokens['has_expired'], $tokens['created_at'], - ( $tokens['error_count'] ?? 0 ) + ( $tokens['error_count'] ?? 0 ), ); } } @@ -93,7 +93,7 @@ public function request_tokens( $code ) { 'authorization_code', [ 'code' => $code, - ] + ], ); $token = OAuth_Token::from_response( $response ); @@ -274,7 +274,7 @@ protected function refresh_tokens( OAuth_Token $tokens ) { 'refresh_token', [ 'refresh_token' => $tokens->refresh_token, - ] + ], ); $token_obj = OAuth_Token::from_response( $new_tokens ); diff --git a/src/config/schema-types.php b/src/config/schema-types.php index e0f76202631..25d5dcf3871 100644 --- a/src/config/schema-types.php +++ b/src/config/schema-types.php @@ -163,7 +163,7 @@ public function get_article_type_options() { 'name' => \__( 'None', 'wordpress-seo' ), 'value' => 'None', ], - ] + ], ); } } diff --git a/src/config/semrush-client.php b/src/config/semrush-client.php index da45140bf17..41f2a1cd895 100644 --- a/src/config/semrush-client.php +++ b/src/config/semrush-client.php @@ -41,13 +41,13 @@ public function __construct( Options_Helper $options_helper, WP_Remote_Handler $ ], [ 'httpClient' => new Client( [ 'handler' => $wp_remote_handler ] ), - ] + ], ); parent::__construct( self::TOKEN_OPTION, $provider, - $options_helper + $options_helper, ); } @@ -75,7 +75,7 @@ public function do_request( $method, $url, array $options ) { 'params' => [ 'access_token' => $this->get_tokens()->access_token, ], - ] + ], ); return parent::do_request( $method, $url, $options ); diff --git a/src/config/wincher-client.php b/src/config/wincher-client.php index 7f9b58302f2..4c4ade7b5d3 100644 --- a/src/config/wincher-client.php +++ b/src/config/wincher-client.php @@ -56,13 +56,13 @@ public function __construct( Options_Helper $options_helper, WP_Remote_Handler $ ], [ 'httpClient' => new Client( [ 'handler' => $wp_remote_handler ] ), - ] + ], ); parent::__construct( self::TOKEN_OPTION, $provider, - $options_helper + $options_helper, ); } @@ -77,7 +77,7 @@ public function get_authorization_url() { $url = $this->provider->getAuthorizationUrl( [ 'state' => WPSEO_Utils::format_json_encode( [ 'domain' => $parsed_site_url['host'] ] ), - ] + ], ); $pkce_code = $this->provider->getPkceCode(); diff --git a/src/config/wincher-pkce-provider.php b/src/config/wincher-pkce-provider.php index 58c67bed32c..ce59c755306 100644 --- a/src/config/wincher-pkce-provider.php +++ b/src/config/wincher-pkce-provider.php @@ -80,10 +80,10 @@ protected function getRandomPkceCode( $length = 64 ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode \base64_encode( \random_bytes( $length ) ), '+/', - '-_' + '-_', ), 0, - $length + $length, ); } @@ -136,9 +136,9 @@ protected function getAuthorizationParameters( array $options ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode \base64_encode( \hash( 'sha256', $this->pkceCode, true ) ), '+/', - '-_' + '-_', ), - '=' + '=', ); } elseif ( $pkce_method === 'plain' ) { @@ -190,7 +190,7 @@ public function getAccessToken( $grant, array $options = [] ) { if ( \is_array( $response ) === false ) { throw new UnexpectedValueException( - 'Invalid response received from Authorization Server. Expected JSON.' + 'Invalid response received from Authorization Server. Expected JSON.', ); } @@ -217,7 +217,7 @@ protected function getConfigurableOptions() { 'responseResourceOwnerId', 'scopes', 'pkceMethod', - ] + ], ); } diff --git a/src/content-type-visibility/application/content-type-visibility-watcher-actions.php b/src/content-type-visibility/application/content-type-visibility-watcher-actions.php index e9b60b2b7d0..06103973d4a 100644 --- a/src/content-type-visibility/application/content-type-visibility-watcher-actions.php +++ b/src/content-type-visibility/application/content-type-visibility-watcher-actions.php @@ -156,7 +156,7 @@ private function add_notification() { /* translators: 1: Opening tag of the link to the Search appearance settings page, 2: Link closing tag. */ \esc_html__( 'You\'ve added a new type of content. We recommend that you review the corresponding %1$sSearch appearance settings%2$s.', 'wordpress-seo' ), '', - '' + '', ); $notification = new Yoast_Notification( @@ -166,7 +166,7 @@ private function add_notification() { 'id' => 'content-types-made-public', 'capabilities' => 'wpseo_manage_options', 'priority' => 0.8, - ] + ], ); $this->notification_center->add_notification( $notification ); diff --git a/src/content-type-visibility/user-interface/content-type-visibility-dismiss-new-route.php b/src/content-type-visibility/user-interface/content-type-visibility-dismiss-new-route.php index df999e16528..292742196b9 100644 --- a/src/content-type-visibility/user-interface/content-type-visibility-dismiss-new-route.php +++ b/src/content-type-visibility/user-interface/content-type-visibility-dismiss-new-route.php @@ -120,7 +120,7 @@ public function post_type_dismiss_callback( $request ) { return new WP_REST_Response( (object) $response, - $response['status'] + $response['status'], ); } @@ -149,7 +149,7 @@ public function taxonomy_dismiss_callback( WP_REST_Request $request ) { return new WP_REST_Response( (object) $response, - $response['status'] + $response['status'], ); } } diff --git a/src/context/meta-tags-context.php b/src/context/meta-tags-context.php index 55452c72ab8..0676ac7a2a0 100644 --- a/src/context/meta-tags-context.php +++ b/src/context/meta-tags-context.php @@ -522,10 +522,8 @@ public function generate_schema_page_type() { $type = 'CollectionPage'; break; default: - $additional_type = $this->indexable->schema_page_type; - if ( $additional_type === null ) { - $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); - } + $additional_type = $this->indexable->schema_page_type; + $additional_type ??= $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); $type = [ 'WebPage', $additional_type ]; @@ -552,10 +550,8 @@ public function generate_schema_page_type() { * @return string|array The schema article type. */ public function generate_schema_article_type() { - $additional_type = $this->indexable->schema_article_type; - if ( $additional_type === null ) { - $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); - } + $additional_type = $this->indexable->schema_article_type; + $additional_type ??= $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); diff --git a/src/dashboard/application/configuration/dashboard-configuration.php b/src/dashboard/application/configuration/dashboard-configuration.php index 60c0e00397b..1baa57295d4 100644 --- a/src/dashboard/application/configuration/dashboard-configuration.php +++ b/src/dashboard/application/configuration/dashboard-configuration.php @@ -134,7 +134,7 @@ public function get_configuration(): array { [ Readability_Analysis::NAME, Keyphrase_Analysis::NAME, - ] + ], )->to_array(), 'endpoints' => $this->endpoints_repository->get_all_endpoints()->to_array(), 'nonce' => $this->nonce_repository->get_rest_nonce(), diff --git a/src/dashboard/infrastructure/browser-cache/browser-cache-configuration.php b/src/dashboard/infrastructure/browser-cache/browser-cache-configuration.php index ed9261201aa..d55dc19bf1b 100644 --- a/src/dashboard/infrastructure/browser-cache/browser-cache-configuration.php +++ b/src/dashboard/infrastructure/browser-cache/browser-cache-configuration.php @@ -42,7 +42,7 @@ private function get_storage_prefix() { $current_user = \wp_get_current_user(); $auth_cookie = \wp_parse_auth_cookie(); $blog_id = \get_current_blog_id(); - $session_token = isset( $auth_cookie['token'] ) ? $auth_cookie['token'] : ''; + $session_token = ( $auth_cookie['token'] ?? '' ); return \wp_hash( $current_user->user_login . '|' . $session_token . '|' . $blog_id ); } diff --git a/src/dashboard/infrastructure/integrations/site-kit.php b/src/dashboard/infrastructure/integrations/site-kit.php index 56ef67bc9c4..fe06032308f 100644 --- a/src/dashboard/infrastructure/integrations/site-kit.php +++ b/src/dashboard/infrastructure/integrations/site-kit.php @@ -154,7 +154,7 @@ public function is_onboarded(): bool { * @return bool If the user can read the data. */ private function can_read_data( array $module ): bool { - return ( ! \is_null( $module['can_view'] ) ? $module['can_view'] : false ); + return ( $module['can_view'] ?? false ); } /** @@ -269,7 +269,7 @@ public function get_preloaded_data( array $paths ): array { return \array_reduce( \array_unique( $actual_paths ), 'rest_preload_api_request', - [] + [], ); } @@ -282,8 +282,8 @@ public function get_activate_url(): string { return \html_entity_decode( \wp_nonce_url( \self_admin_url( 'plugins.php?action=activate&plugin=' . self::SITE_KIT_FILE ), - 'activate-plugin_' . self::SITE_KIT_FILE - ) + 'activate-plugin_' . self::SITE_KIT_FILE, + ), ); } @@ -296,8 +296,8 @@ public function get_install_url(): string { return \html_entity_decode( \wp_nonce_url( \self_admin_url( 'update.php?action=install-plugin&plugin=google-site-kit' ), - 'install-plugin_google-site-kit' - ) + 'install-plugin_google-site-kit', + ), ); } @@ -310,8 +310,8 @@ public function get_update_url(): string { return \html_entity_decode( \wp_nonce_url( \self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . self::SITE_KIT_FILE ), - 'upgrade-plugin_' . self::SITE_KIT_FILE - ) + 'upgrade-plugin_' . self::SITE_KIT_FILE, + ), ); } diff --git a/src/dashboard/infrastructure/score-results/readability-score-results/readability-score-results-collector.php b/src/dashboard/infrastructure/score-results/readability-score-results/readability-score-results-collector.php index f41a55f924e..5abf6f8cb1d 100644 --- a/src/dashboard/infrastructure/score-results/readability-score-results/readability-score-results-collector.php +++ b/src/dashboard/infrastructure/score-results/readability-score-results/readability-score-results-collector.php @@ -39,7 +39,7 @@ public function get_score_results( array $readability_score_groups, Content_Type [ Model::get_table_name( 'Indexable' ), $content_type_name, - ] + ], ); if ( $term_id === null ) { @@ -52,7 +52,7 @@ public function get_score_results( array $readability_score_groups, Content_Type WHERE ( I.post_status = 'publish' OR I.post_status IS NULL ) AND I.object_type = 'post' AND I.object_sub_type = %s", - $replacements + $replacements, ); //phpcs:enable } @@ -74,7 +74,7 @@ public function get_score_results( array $readability_score_groups, Content_Type FROM %i WHERE term_taxonomy_id = %d )", - $replacements + $replacements, ); //phpcs:enable } diff --git a/src/dashboard/infrastructure/score-results/seo-score-results/seo-score-results-collector.php b/src/dashboard/infrastructure/score-results/seo-score-results/seo-score-results-collector.php index d5e7043e57e..75efe486d7c 100644 --- a/src/dashboard/infrastructure/score-results/seo-score-results/seo-score-results-collector.php +++ b/src/dashboard/infrastructure/score-results/seo-score-results/seo-score-results-collector.php @@ -39,7 +39,7 @@ public function get_score_results( array $seo_score_groups, Content_Type $conten [ Model::get_table_name( 'Indexable' ), $content_type_name, - ] + ], ); if ( $term_id === null ) { @@ -53,7 +53,7 @@ public function get_score_results( array $seo_score_groups, Content_Type $conten AND I.object_type = 'post' AND I.object_sub_type = %s AND ( I.is_robots_noindex IS NULL OR I.is_robots_noindex <> 1 )", - $replacements + $replacements, ); //phpcs:enable } @@ -76,7 +76,7 @@ public function get_score_results( array $seo_score_groups, Content_Type $conten FROM %i WHERE term_taxonomy_id = %d )", - $replacements + $replacements, ); //phpcs:enable } diff --git a/src/dashboard/infrastructure/search-console/site-kit-search-console-adapter.php b/src/dashboard/infrastructure/search-console/site-kit-search-console-adapter.php index 5a802704840..f7b7c6de59d 100644 --- a/src/dashboard/infrastructure/search-console/site-kit-search-console-adapter.php +++ b/src/dashboard/infrastructure/search-console/site-kit-search-console-adapter.php @@ -179,9 +179,9 @@ private function validate_response( WP_REST_Response $response ): void { throw new Failed_Request_Exception( \wp_kses_post( $response->as_error() - ->get_error_message() + ->get_error_message(), ), - (int) $error_status_code + (int) $error_status_code, ); } diff --git a/src/dashboard/infrastructure/taxonomies/taxonomies-collector.php b/src/dashboard/infrastructure/taxonomies/taxonomies-collector.php index a0714f5ad67..00c05593674 100644 --- a/src/dashboard/infrastructure/taxonomies/taxonomies-collector.php +++ b/src/dashboard/infrastructure/taxonomies/taxonomies-collector.php @@ -53,7 +53,7 @@ public function get_custom_filtering_taxonomy( string $content_type ) { \_doing_it_wrong( 'Filter: \'wpseo_{$content_type}_filtering_taxonomy\'', 'The `wpseo_{$content_type}_filtering_taxonomy` filter should return a public taxonomy, available in REST API, that is associated with that content type.', - 'YoastSEO v24.1' + 'YoastSEO v24.1', ); } diff --git a/src/dashboard/user-interface/configuration/site-kit-configuration-dismissal-route.php b/src/dashboard/user-interface/configuration/site-kit-configuration-dismissal-route.php index ef922af786b..13c7041355d 100644 --- a/src/dashboard/user-interface/configuration/site-kit-configuration-dismissal-route.php +++ b/src/dashboard/user-interface/configuration/site-kit-configuration-dismissal-route.php @@ -88,7 +88,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -108,7 +108,7 @@ public function set_site_kit_configuration_permanent_dismissal( WP_REST_Request return new WP_Error( 'wpseo_set_site_kit_configuration_permanent_dismissal_error', $exception->getMessage(), - (object) [] + (object) [], ); } @@ -116,7 +116,7 @@ public function set_site_kit_configuration_permanent_dismissal( WP_REST_Request [ 'success' => $result, ], - ( $result ) ? 200 : 400 + ( $result ) ? 200 : 400, ); } diff --git a/src/dashboard/user-interface/configuration/site-kit-consent-management-route.php b/src/dashboard/user-interface/configuration/site-kit-consent-management-route.php index 3063981a586..096d4866cb4 100644 --- a/src/dashboard/user-interface/configuration/site-kit-consent-management-route.php +++ b/src/dashboard/user-interface/configuration/site-kit-consent-management-route.php @@ -96,7 +96,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -116,7 +116,7 @@ public function set_site_kit_consent( WP_REST_Request $request ) { return new WP_Error( 'wpseo_set_site_kit_consent_error', $exception->getMessage(), - (object) [] + (object) [], ); } @@ -124,7 +124,7 @@ public function set_site_kit_consent( WP_REST_Request $request ) { [ 'success' => $result, ], - ( $result ) ? 200 : 400 + ( $result ) ? 200 : 400, ); } diff --git a/src/dashboard/user-interface/scores/abstract-scores-route.php b/src/dashboard/user-interface/scores/abstract-scores-route.php index 11fa2e4d239..5da16f4eaae 100644 --- a/src/dashboard/user-interface/scores/abstract-scores-route.php +++ b/src/dashboard/user-interface/scores/abstract-scores-route.php @@ -146,7 +146,7 @@ public function register_routes() { 'type' => 'integer', 'default' => null, 'sanitize_callback' => static function ( $param ) { - return \intval( $param ); + return (int) $param; }, ], 'troubleshooting' => [ @@ -157,7 +157,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -180,13 +180,13 @@ public function get_scores( WP_REST_Request $request ) { [ 'error' => $exception->getMessage(), ], - $exception->getCode() + $exception->getCode(), ); } return new WP_REST_Response( $results, - 200 + 200, ); } diff --git a/src/dashboard/user-interface/setup/setup-url-interceptor.php b/src/dashboard/user-interface/setup/setup-url-interceptor.php index bb488bf2d7d..b0ca0b8a270 100644 --- a/src/dashboard/user-interface/setup/setup-url-interceptor.php +++ b/src/dashboard/user-interface/setup/setup-url-interceptor.php @@ -93,7 +93,7 @@ public function add_redirect_page( $pages ) { '', '', 'wpseo_manage_options', - self::PAGE + self::PAGE, ); return $pages; diff --git a/src/dashboard/user-interface/time-based-seo-metrics/time-based-seo-metrics-route.php b/src/dashboard/user-interface/time-based-seo-metrics/time-based-seo-metrics-route.php index c30fbf8032a..7684d711bb1 100644 --- a/src/dashboard/user-interface/time-based-seo-metrics/time-based-seo-metrics-route.php +++ b/src/dashboard/user-interface/time-based-seo-metrics/time-based-seo-metrics-route.php @@ -151,7 +151,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -225,13 +225,13 @@ public function get_time_based_seo_metrics( WP_REST_Request $request ): WP_REST_ [ 'error' => $exception->getMessage(), ], - $exception->getCode() + $exception->getCode(), ); } return new WP_REST_Response( $time_based_seo_metrics_container->to_array(), - 200 + 200, ); } diff --git a/src/dashboard/user-interface/tracking/setup-steps-tracking-route.php b/src/dashboard/user-interface/tracking/setup-steps-tracking-route.php index aa30f8bd306..a0a2445a158 100644 --- a/src/dashboard/user-interface/tracking/setup-steps-tracking-route.php +++ b/src/dashboard/user-interface/tracking/setup-steps-tracking-route.php @@ -108,7 +108,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -133,7 +133,7 @@ public function track_setup_steps( WP_REST_Request $request ) { $data, static function ( $value ) { return $value !== null; - } + }, ); // Check if all values are null then return an error that no valid params were passed. @@ -141,7 +141,7 @@ static function ( $value ) { return new WP_Error( 'wpseo_set_site_kit_usage_tracking', \__( 'No valid parameters were passed.', 'wordpress-seo' ), - [ 'status' => 400 ] + [ 'status' => 400 ], ); } @@ -153,7 +153,7 @@ static function ( $value ) { return new WP_Error( 'wpseo_set_site_kit_usage_tracking', $exception->getMessage(), - (object) [] + (object) [], ); } if ( ! $result ) { @@ -165,7 +165,7 @@ static function ( $value ) { [ 'success' => $result, ], - ( $result ) ? 200 : 400 + ( $result ) ? 200 : 400, ); } diff --git a/src/deprecated/frontend/breadcrumbs.php b/src/deprecated/frontend/breadcrumbs.php index 5c9337eed2e..5b450fc378a 100644 --- a/src/deprecated/frontend/breadcrumbs.php +++ b/src/deprecated/frontend/breadcrumbs.php @@ -106,9 +106,7 @@ public function __toString() { * @return static The instance. */ public static function get_instance() { - if ( self::$instance === null ) { - self::$instance = new self(); - } + self::$instance ??= new self(); return self::$instance; } diff --git a/src/deprecated/frontend/frontend.php b/src/deprecated/frontend/frontend.php index c301ca03d0f..afb9a962827 100644 --- a/src/deprecated/frontend/frontend.php +++ b/src/deprecated/frontend/frontend.php @@ -92,9 +92,7 @@ public function __call( $method, $arguments ) { * @return static The instance. */ public static function get_instance() { - if ( self::$instance === null ) { - self::$instance = new self(); - } + self::$instance ??= new self(); return self::$instance; } diff --git a/src/deprecated/src/promotions/domain/black-friday-checklist-promotion.php b/src/deprecated/src/promotions/domain/black-friday-checklist-promotion.php index e5d2cc8fdb9..0e96e232cdb 100644 --- a/src/deprecated/src/promotions/domain/black-friday-checklist-promotion.php +++ b/src/deprecated/src/promotions/domain/black-friday-checklist-promotion.php @@ -22,8 +22,8 @@ public function __construct() { 'black-friday-2023-checklist', new Time_Interval( \gmmktime( 11, 00, 00, 9, 19, 2023 ), - \gmmktime( 11, 00, 00, 10, 31, 2023 ) - ) + \gmmktime( 11, 00, 00, 10, 31, 2023 ), + ), ); } } diff --git a/src/exceptions/indexable/author-not-built-exception.php b/src/exceptions/indexable/author-not-built-exception.php index 9363d0e187d..c09537b5854 100644 --- a/src/exceptions/indexable/author-not-built-exception.php +++ b/src/exceptions/indexable/author-not-built-exception.php @@ -17,7 +17,7 @@ class Author_Not_Built_Exception extends Not_Built_Exception { */ public static function author_archives_are_not_indexed_for_users_without_posts( $user_id ) { return new self( - 'Indexable for author with id ' . $user_id . ' is not being built, since author archives are not indexed for users without posts.' + 'Indexable for author with id ' . $user_id . ' is not being built, since author archives are not indexed for users without posts.', ); } @@ -31,7 +31,7 @@ public static function author_archives_are_not_indexed_for_users_without_posts( */ public static function author_archives_are_disabled( $user_id ) { return new self( - 'Indexable for author with id ' . $user_id . ' is not being built, since author archives are disabled.' + 'Indexable for author with id ' . $user_id . ' is not being built, since author archives are disabled.', ); } @@ -45,7 +45,7 @@ public static function author_archives_are_disabled( $user_id ) { */ public static function author_not_built_because_of_filter( $user_id ) { return new self( - 'Indexable for author with id ' . $user_id . ' is not being built, since it is excluded because of the \'wpseo_should_build_and_save_user_indexable\' filter.' + 'Indexable for author with id ' . $user_id . ' is not being built, since it is excluded because of the \'wpseo_should_build_and_save_user_indexable\' filter.', ); } } diff --git a/src/exceptions/indexable/invalid-term-exception.php b/src/exceptions/indexable/invalid-term-exception.php index 1c6a3178e58..bd0f733a1d8 100644 --- a/src/exceptions/indexable/invalid-term-exception.php +++ b/src/exceptions/indexable/invalid-term-exception.php @@ -19,8 +19,8 @@ public function __construct( $reason ) { \sprintf( /* translators: %s is the reason given by WordPress. */ \esc_html__( 'The term is considered invalid. The following reason was given by WordPress: %s', 'wordpress-seo' ), - $reason - ) + $reason, + ), ); } } diff --git a/src/exceptions/indexable/not-built-exception.php b/src/exceptions/indexable/not-built-exception.php index decc356f0ee..fe70e839564 100644 --- a/src/exceptions/indexable/not-built-exception.php +++ b/src/exceptions/indexable/not-built-exception.php @@ -17,7 +17,7 @@ class Not_Built_Exception extends Indexable_Exception { */ public static function invalid_object_id( $object_id ) { return new self( - "Indexable was not built because it had an invalid object id of $object_id." + "Indexable was not built because it had an invalid object id of $object_id.", ); } } diff --git a/src/exceptions/missing-method.php b/src/exceptions/missing-method.php index 780cb6bc392..3dab2987ad9 100644 --- a/src/exceptions/missing-method.php +++ b/src/exceptions/missing-method.php @@ -23,8 +23,8 @@ public static function for_class( $method, $class_name ) { /* translators: %1$s expands to the method name. %2$s expands to the class name */ \__( 'Method %1$s() does not exist in class %2$s', 'wordpress-seo' ), $method, - $class_name - ) + $class_name, + ), ); } } diff --git a/src/general/user-interface/general-page-integration.php b/src/general/user-interface/general-page-integration.php index 96857018b59..d7893ba41fd 100644 --- a/src/general/user-interface/general-page-integration.php +++ b/src/general/user-interface/general-page-integration.php @@ -215,7 +215,7 @@ public function add_page( $pages ) { self::PAGE, [ $this, 'display_page' ], ], - ] + ], ); return $pages; diff --git a/src/general/user-interface/opt-in-route.php b/src/general/user-interface/opt-in-route.php index dc66860c8ed..a43e924de92 100644 --- a/src/general/user-interface/opt-in-route.php +++ b/src/general/user-interface/opt-in-route.php @@ -108,7 +108,7 @@ public function set_opt_in_seen( $request ) { 'success' => $success, 'status' => $status, ], - $status + $status, ); } diff --git a/src/generators/breadcrumbs-generator.php b/src/generators/breadcrumbs-generator.php index a38691bf594..6cb882f795e 100644 --- a/src/generators/breadcrumbs-generator.php +++ b/src/generators/breadcrumbs-generator.php @@ -153,7 +153,7 @@ public function generate( Meta_Tags_Context $context ) { $indexables, static function ( $indexable ) { return \is_a( $indexable, Indexable::class ); - } + }, ); $crumbs = \array_map( [ $this, 'get_post_type_crumb' ], $indexables ); @@ -176,7 +176,7 @@ static function ( $indexable ) { \_doing_it_wrong( 'Filter: \'wpseo_breadcrumb_links\'', 'The `wpseo_breadcrumb_links` filter should return a multi-dimensional array.', - 'YoastSEO v20.0' + 'YoastSEO v20.0', ); } else { @@ -422,7 +422,7 @@ protected function add_paged_crumb( array $crumbs, $current_indexable ) { 'text' => \sprintf( /* translators: %s expands to the current page number */ \__( 'Page %s', 'wordpress-seo' ), - $current_page_number + $current_page_number, ), ]; diff --git a/src/generators/open-graph-image-generator.php b/src/generators/open-graph-image-generator.php index aaf8ee7230a..de8f2cedd7b 100644 --- a/src/generators/open-graph-image-generator.php +++ b/src/generators/open-graph-image-generator.php @@ -162,8 +162,8 @@ protected function add_from_indexable( Indexable $indexable, Images $image_conta (array) $meta_data, [ 'url' => $indexable->open_graph_image, - ] - ) + ], + ), ); } } diff --git a/src/generators/schema-generator.php b/src/generators/schema-generator.php index 86e6bedab57..d640ffe53c8 100644 --- a/src/generators/schema-generator.php +++ b/src/generators/schema-generator.php @@ -272,7 +272,7 @@ public function protected_webpage_schema( $graph_piece ) { 'datePublished', 'dateModified', 'breadcrumb', - ] + ], ); $graph_piece = \array_intersect_key( $graph_piece, $properties_to_show ); diff --git a/src/helpers/crawl-cleanup-helper.php b/src/helpers/crawl-cleanup-helper.php index 73d0d96626d..65c168d36d3 100644 --- a/src/helpers/crawl-cleanup-helper.php +++ b/src/helpers/crawl-cleanup-helper.php @@ -270,7 +270,7 @@ public function do_clean_redirect( $proper_url ) { /* translators: %1$s: Yoast SEO */ \__( '%1$s: unregistered URL parameter removed. See %2$s', 'wordpress-seo' ), 'Yoast SEO', - 'https://yoa.st/advanced-crawl-settings' + 'https://yoa.st/advanced-crawl-settings', ); $this->redirect_helper->do_safe_redirect( $proper_url, 301, $message ); diff --git a/src/helpers/current-page-helper.php b/src/helpers/current-page-helper.php index 09aae3e4aa8..39e632fee47 100644 --- a/src/helpers/current-page-helper.php +++ b/src/helpers/current-page-helper.php @@ -441,7 +441,7 @@ public function current_post_is_privacy_policy() { return false; } - return \intval( $post->ID ) === \intval( \get_option( 'wp_page_for_privacy_policy', false ) ); + return (int) $post->ID === (int) \get_option( 'wp_page_for_privacy_policy', false ); } /** diff --git a/src/helpers/home-url-helper.php b/src/helpers/home-url-helper.php index 17197a7818c..6103fb0251c 100644 --- a/src/helpers/home-url-helper.php +++ b/src/helpers/home-url-helper.php @@ -27,9 +27,7 @@ class Home_Url_Helper { * @return string The home url. */ public function get() { - if ( static::$home_url === null ) { - static::$home_url = \home_url(); - } + static::$home_url ??= \home_url(); return static::$home_url; } @@ -40,9 +38,7 @@ public function get() { * @return array The parsed url. */ public function get_parsed() { - if ( static::$parsed_home_url === null ) { - static::$parsed_home_url = \wp_parse_url( $this->get() ); - } + static::$parsed_home_url ??= \wp_parse_url( $this->get() ); return static::$parsed_home_url; } diff --git a/src/helpers/indexing-helper.php b/src/helpers/indexing-helper.php index a6c8a4b68e0..ddf852d5959 100644 --- a/src/helpers/indexing-helper.php +++ b/src/helpers/indexing-helper.php @@ -178,7 +178,7 @@ public function set_reason( $reason ) { */ protected function remove_indexing_notification() { $this->notification_center->remove_notification_by_id( - Indexing_Notification_Integration::NOTIFICATION_ID + Indexing_Notification_Integration::NOTIFICATION_ID, ); } diff --git a/src/helpers/notification-helper.php b/src/helpers/notification-helper.php index 3989e14f1ec..cb127c4d3ee 100644 --- a/src/helpers/notification-helper.php +++ b/src/helpers/notification-helper.php @@ -69,7 +69,7 @@ function ( $notification ) { 'resolveNonce' => $notification->get_resolve_nonce(), ]; }, - $all_notifications + $all_notifications, ); } } diff --git a/src/helpers/post-type-helper.php b/src/helpers/post-type-helper.php index 92ee2cfcf42..7f45c006edc 100644 --- a/src/helpers/post-type-helper.php +++ b/src/helpers/post-type-helper.php @@ -225,7 +225,7 @@ public function is_post_type_archive_indexable( $post_type ) { static function ( $post_type_object ) { return $post_type_object->name; }, - $public_type_objects + $public_type_objects, ); return \in_array( $post_type, $public_types, true ); diff --git a/src/helpers/redirect-helper.php b/src/helpers/redirect-helper.php index b2fba707677..2c0f8802831 100644 --- a/src/helpers/redirect-helper.php +++ b/src/helpers/redirect-helper.php @@ -21,7 +21,7 @@ class Redirect_Helper { public function do_unsafe_redirect( $location, $status = 302, $reason = 'Yoast SEO' ) { // phpcs:ignore WordPress.Security.SafeRedirect -- intentional, function has been renamed to make unsafe more clear. \wp_redirect( $location, $status, $reason ); - exit; + exit(); } /** @@ -37,7 +37,7 @@ public function do_unsafe_redirect( $location, $status = 302, $reason = 'Yoast S */ public function do_safe_redirect( $location, $status = 302, $reason = 'Yoast SEO' ) { \wp_safe_redirect( $location, $status, $reason ); - exit; + exit(); } /** diff --git a/src/helpers/schema/article-helper.php b/src/helpers/schema/article-helper.php index d4661c25143..b31af3a5e2a 100644 --- a/src/helpers/schema/article-helper.php +++ b/src/helpers/schema/article-helper.php @@ -15,9 +15,7 @@ class Article_Helper { * @return bool True if it has Article schema, false if not. */ public function is_article_post_type( $post_type = null ) { - if ( $post_type === null ) { - $post_type = \get_post_type(); - } + $post_type ??= \get_post_type(); return $this->is_author_supported( $post_type ); } diff --git a/src/helpers/schema/replace-vars-helper.php b/src/helpers/schema/replace-vars-helper.php index 6d09410befb..4b205d6a01b 100644 --- a/src/helpers/schema/replace-vars-helper.php +++ b/src/helpers/schema/replace-vars-helper.php @@ -116,7 +116,7 @@ public function register_replace_vars( $context ) { protected function register_replacement( $variable, $value ) { $this->replace_vars->safe_register_replacement( $variable, - $this->get_identity_function( $value ) + $this->get_identity_function( $value ), ); } diff --git a/src/helpers/social-profiles-helper.php b/src/helpers/social-profiles-helper.php index 4c2098f5b1a..a82f801efac 100644 --- a/src/helpers/social-profiles-helper.php +++ b/src/helpers/social-profiles-helper.php @@ -226,7 +226,7 @@ public function set_organization_social_profiles( $social_profiles ) { $social_profiles[ $field_name ], static function ( $other_social_url ) { return $other_social_url !== ''; - } + }, ); $social_profiles[ $field_name ] = \array_values( $other_social_urls ); diff --git a/src/helpers/url-helper.php b/src/helpers/url-helper.php index e5f5d2b7b26..e638ed81f4a 100644 --- a/src/helpers/url-helper.php +++ b/src/helpers/url-helper.php @@ -213,9 +213,7 @@ public function get_link_type( $url, $home_url = null, $is_image = false ) { return ( $is_image ) ? SEO_Links::TYPE_EXTERNAL_IMAGE : SEO_Links::TYPE_EXTERNAL; } - if ( $home_url === null ) { - $home_url = \wp_parse_url( \home_url() ); - } + $home_url ??= \wp_parse_url( \home_url() ); // When the base host is equal to the host. if ( isset( $url['host'] ) && $url['host'] !== $home_url['host'] ) { diff --git a/src/helpers/woocommerce-helper.php b/src/helpers/woocommerce-helper.php index 05423808c47..edfe49a80e5 100644 --- a/src/helpers/woocommerce-helper.php +++ b/src/helpers/woocommerce-helper.php @@ -66,6 +66,6 @@ public function current_post_is_terms_and_conditions_page() { return false; } - return \intval( $post->ID ) === \intval( \wc_terms_and_conditions_page_id() ); + return (int) $post->ID === (int) \wc_terms_and_conditions_page_id(); } } diff --git a/src/initializers/crawl-cleanup-permalinks.php b/src/initializers/crawl-cleanup-permalinks.php index c76dcd10559..a30e12badd3 100644 --- a/src/initializers/crawl-cleanup-permalinks.php +++ b/src/initializers/crawl-cleanup-permalinks.php @@ -142,7 +142,7 @@ public function utm_redirect() { $message = \sprintf( /* translators: %1$s: Yoast SEO */ \__( '%1$s: redirect utm variables to #', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); $this->redirect_helper->do_safe_redirect( \trailingslashit( $this->url_helper->recreate_current_url( false ) ) . \ltrim( $new_path, '/' ), 301, $message ); diff --git a/src/integrations/academy-integration.php b/src/integrations/academy-integration.php index 4c8cd9be91e..b49a1f457e8 100644 --- a/src/integrations/academy-integration.php +++ b/src/integrations/academy-integration.php @@ -113,7 +113,7 @@ public function add_page( $pages ) { self::PAGE, [ $this, 'display_page' ], ], - ] + ], ); return $pages; diff --git a/src/integrations/admin/addon-installation/dialog-integration.php b/src/integrations/admin/addon-installation/dialog-integration.php index 6b0821492ae..fe360971bf7 100644 --- a/src/integrations/admin/addon-installation/dialog-integration.php +++ b/src/integrations/admin/addon-installation/dialog-integration.php @@ -93,9 +93,9 @@ public function throw_no_owned_addons_warning() { /* translators: %1$s expands to Yoast SEO */ \esc_html__( 'No %1$s plugins have been installed. You don\'t seem to own any active subscriptions.', - 'wordpress-seo' + 'wordpress-seo', ), - 'Yoast SEO' + 'Yoast SEO', ) . '

    '; } @@ -112,7 +112,7 @@ public function show_modal() { [ 'addons' => $this->owned_addons, 'nonce' => \wp_create_nonce( 'wpseo_addon_installation' ), - ] + ], ); $asset_manager = new WPSEO_Admin_Asset_Manager(); diff --git a/src/integrations/admin/addon-installation/installation-integration.php b/src/integrations/admin/addon-installation/installation-integration.php index 1a0b8ea83b1..bc7369c5e29 100644 --- a/src/integrations/admin/addon-installation/installation-integration.php +++ b/src/integrations/admin/addon-installation/installation-integration.php @@ -103,7 +103,7 @@ public function install_and_activate_addons() { \printf( '

    %s

    ', - \esc_html__( 'Installing and activating addons', 'wordpress-seo' ) + \esc_html__( 'Installing and activating addons', 'wordpress-seo' ), ); $licensed_addons = $this->addon_manager->get_myyoast_site_information()->subscriptions; @@ -129,12 +129,12 @@ public function install_and_activate_addons() { \esc_html__( '%1$s Continue to %2$s%3$s', 'wordpress-seo' ), '', 'Yoast SEO Premium', - '' + '', ); echo '
    '; - exit; + exit(); } /** @@ -158,7 +158,7 @@ public function activate_addon( $addon_slug ) { $output[] = \sprintf( /* Translators:%s expands to the error message. */ \__( 'Addon activation failed because of an error: %s.', 'wordpress-seo' ), - $exception->getMessage() + $exception->getMessage(), ); } @@ -190,7 +190,7 @@ public function install_addon( $addon_slug, $addon_download ) { $output[] = \sprintf( /* Translators: %s expands to the error message. */ \__( 'Addon installation failed because of an error: %s.', 'wordpress-seo' ), - $exception->getMessage() + $exception->getMessage(), ); } diff --git a/src/integrations/admin/check-required-version.php b/src/integrations/admin/check-required-version.php index a82e0d7d991..125593b24af 100644 --- a/src/integrations/admin/check-required-version.php +++ b/src/integrations/admin/check-required-version.php @@ -83,13 +83,13 @@ public function check_required_version( $source, $remote_source = null, $upgrade /* translators: 1: Current Yoast SEO version, 2: Version required by the uploaded plugin. */ \__( 'The Yoast SEO version on your site is %1$s, however the uploaded plugin requires %2$s.', 'wordpress-seo' ), \WPSEO_VERSION, - \esc_html( $requires_yoast_seo ) + \esc_html( $requires_yoast_seo ), ); return new WP_Error( 'incompatible_yoast_seo_required_version', \__( 'The package could not be installed because it\'s not supported by the currently installed Yoast SEO version.', 'wordpress-seo' ), - $error + $error, ); } @@ -114,7 +114,7 @@ public function update_comparison_table( $table, $current_plugin_data, $new_plug '%1$s%2$s%3$s', \__( 'Required Yoast SEO version', 'wordpress-seo' ), ( $requires_yoast_seo_current !== false ) ? \esc_html( $requires_yoast_seo_current ) : '-', - ( $requires_yoast_seo_new !== false ) ? \esc_html( $requires_yoast_seo_new ) : '-' + ( $requires_yoast_seo_new !== false ) ? \esc_html( $requires_yoast_seo_new ) : '-', ); $table = \str_replace( '', $new_row . '', $table ); diff --git a/src/integrations/admin/crawl-settings-integration.php b/src/integrations/admin/crawl-settings-integration.php index 57a8dc0ae0b..8a31040ec97 100644 --- a/src/integrations/admin/crawl-settings-integration.php +++ b/src/integrations/admin/crawl-settings-integration.php @@ -203,10 +203,10 @@ private function add_crawl_settings( $yform ) { /* Translators: %1$s expands to an opening anchor tag for a link leading to the Yoast SEO page of the Permalink Cleanup features, %2$s expands to a closing anchor tag. */ \esc_html__( 'These are expert features, so make sure you know what you\'re doing before removing the parameters. %1$sRead more about how your site can be affected%2$s.', - 'wordpress-seo' + 'wordpress-seo', ), '', - '' + '', ); $this->print_toggles( $this->permalink_cleanup_settings, $yform, \__( 'Permalink cleanup settings', 'wordpress-seo' ), [], $permalink_warning ); @@ -276,7 +276,7 @@ private function print_toggles( array $settings, Yoast_Form $yform, $title = '', $toggles, $label, '', - $attr + $attr, ); if ( $this->should_feature_be_disabled_permalink( $setting ) ) { echo '

    '; @@ -285,7 +285,7 @@ private function print_toggles( array $settings, Yoast_Form $yform, $title = '', /* translators: 1: Link start tag to the Permalinks settings page, 2: Link closing tag. */ \esc_html__( 'This feature is disabled when your site is not using %1$spretty permalinks%2$s.', 'wordpress-seo' ), '', - '' + '', ); } else { diff --git a/src/integrations/admin/cron-integration.php b/src/integrations/admin/cron-integration.php index 14c4699ac1f..c3f85a0dcf9 100644 --- a/src/integrations/admin/cron-integration.php +++ b/src/integrations/admin/cron-integration.php @@ -42,7 +42,7 @@ public function register_hooks() { \wp_schedule_event( $this->date_helper->current_time(), 'daily', - Indexing_Notification_Integration::NOTIFICATION_ID + Indexing_Notification_Integration::NOTIFICATION_ID, ); } } diff --git a/src/integrations/admin/deactivated-premium-integration.php b/src/integrations/admin/deactivated-premium-integration.php index 40516b137c6..faa7445274a 100644 --- a/src/integrations/admin/deactivated-premium-integration.php +++ b/src/integrations/admin/deactivated-premium-integration.php @@ -88,10 +88,10 @@ public function premium_deactivated_notice() { '', - '' + '', ); // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped above. echo new Notice_Presenter( @@ -101,7 +101,7 @@ public function premium_deactivated_notice() { 'support-team.svg', null, true, - 'yoast-premium-deactivated-notice' + 'yoast-premium-deactivated-notice', ); // phpcs:enable diff --git a/src/integrations/admin/first-time-configuration-integration.php b/src/integrations/admin/first-time-configuration-integration.php index 3b5b3804922..9845cecb778 100644 --- a/src/integrations/admin/first-time-configuration-integration.php +++ b/src/integrations/admin/first-time-configuration-integration.php @@ -137,8 +137,8 @@ public function add_first_time_configuration_tab( $dashboard_tabs ) { new WPSEO_Option_Tab( 'first-time-configuration', \__( 'First-time configuration', 'wordpress-seo' ), - [ 'save_button' => false ] - ) + [ 'save_button' => false ], + ), ); } @@ -192,7 +192,7 @@ public function enqueue_assets() { $options, function ( $item ) { return $item['value'] === $this->is_company_or_person(); - } + }, ); $selected_option = \reset( $filtered_options ); if ( \is_array( $selected_option ) ) { diff --git a/src/integrations/admin/first-time-configuration-notice-integration.php b/src/integrations/admin/first-time-configuration-notice-integration.php index d47d05935d3..837ab3f0200 100644 --- a/src/integrations/admin/first-time-configuration-notice-integration.php +++ b/src/integrations/admin/first-time-configuration-notice-integration.php @@ -110,7 +110,7 @@ public function first_time_configuration_notice() { \__( 'Get started quickly with the %1$s%2$s First-time configuration%3$s and configure Yoast SEO with the optimal SEO settings for your site!', 'wordpress-seo' ), '', 'Yoast SEO', - '' + '', ); } else { @@ -118,7 +118,7 @@ public function first_time_configuration_notice() { /* translators: 1: Link start tag to the first-time configuration, 2: Link closing tag. */ \__( 'We noticed that you haven\'t fully configured Yoast SEO yet. Optimize your SEO settings even further by using our improved %1$s First-time configuration%2$s.', 'wordpress-seo' ), '', - '' + '', ); } @@ -128,7 +128,7 @@ public function first_time_configuration_notice() { 'mirrored_fit_bubble_woman_1_optim.svg', null, true, - 'yoast-first-time-configuration-notice' + 'yoast-first-time-configuration-notice', ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output from present() is considered safe. diff --git a/src/integrations/admin/helpscout-beacon.php b/src/integrations/admin/helpscout-beacon.php index 3a6c2d0b4eb..4a9098cf0f4 100644 --- a/src/integrations/admin/helpscout-beacon.php +++ b/src/integrations/admin/helpscout-beacon.php @@ -190,7 +190,7 @@ public function output_beacon_js() { ( $this->ask_consent ) ? 'wpseoHelpScoutBeaconConsent' : 'wpseoHelpScoutBeacon', \esc_html( $this->pages_ids[ $this->page ] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaping done in format_json_encode. - WPSEO_Utils::format_json_encode( (array) $this->get_session_data() ) + WPSEO_Utils::format_json_encode( (array) $this->get_session_data() ), ); } @@ -242,7 +242,7 @@ protected function get_session_data() { 'Active plugins' => $this->get_active_plugins(), 'Must-use and dropins' => $this->get_mustuse_and_dropins(), 'Indexables status' => $this->get_indexables_status(), - ] + ], ); if ( ! empty( $this->products ) ) { @@ -319,7 +319,7 @@ private function get_product_info( $plugin ) { $product_info = \sprintf( 'Expiration date %1$s', - $plugin->expiry_date + $plugin->expiry_date, ); return $product_info; @@ -356,7 +356,7 @@ private function get_theme_info() { '%1$s (Version %2$s, %3$s)', \esc_html( $theme->display( 'Name' ) ), \esc_html( $theme->display( 'Version' ) ), - \esc_attr( $theme->display( 'ThemeURI' ) ) + \esc_attr( $theme->display( 'ThemeURI' ) ), ); if ( \is_child_theme() ) { @@ -389,7 +389,7 @@ private function get_active_plugins() { \esc_html( $plugin_data['Name'] ), \esc_html( $plugin_data['Version'] ), $plugin_update_available, - \esc_attr( $plugin_data['PluginURI'] ) + \esc_attr( $plugin_data['PluginURI'] ), ); } @@ -452,7 +452,7 @@ private function get_language_settings() { $language_settings = \sprintf( 'Site locale: %1$s, user locale: %2$s', ( \is_string( $site_locale ) ) ? \esc_html( $site_locale ) : 'unknown', - ( \is_string( $user_locale ) ) ? \esc_html( $user_locale ) : 'unknown' + ( \is_string( $user_locale ) ) ? \esc_html( $user_locale ) : 'unknown', ); return $language_settings; diff --git a/src/integrations/admin/indexing-notification-integration.php b/src/integrations/admin/indexing-notification-integration.php index 3ae6cbdfbd6..fd03721530f 100644 --- a/src/integrations/admin/indexing-notification-integration.php +++ b/src/integrations/admin/indexing-notification-integration.php @@ -227,7 +227,7 @@ protected function notification() { 'id' => self::NOTIFICATION_ID, 'capabilities' => 'wpseo_manage_options', 'priority' => 0.8, - ] + ], ); } diff --git a/src/integrations/admin/indexing-tool-integration.php b/src/integrations/admin/indexing-tool-integration.php index fa2e15e34e2..d4cd3d3e723 100644 --- a/src/integrations/admin/indexing-tool-integration.php +++ b/src/integrations/admin/indexing-tool-integration.php @@ -178,7 +178,7 @@ protected function render_indexing_error() { $presenter = new Indexing_Error_Presenter( $this->short_link_helper, $this->product_helper, - $this->addon_manager + $this->addon_manager, ); return $presenter->present(); diff --git a/src/integrations/admin/installation-success-integration.php b/src/integrations/admin/installation-success-integration.php index be7ad79be7b..d66bc77efaf 100644 --- a/src/integrations/admin/installation-success-integration.php +++ b/src/integrations/admin/installation-success-integration.php @@ -115,7 +115,7 @@ public function add_submenu_page( $submenu_pages ) { '', 'manage_options', 'wpseo_installation_successful_free', - [ $this, 'render_page' ] + [ $this, 'render_page' ], ); return $submenu_pages; @@ -147,7 +147,7 @@ public function enqueue_assets() { 'firstTimeConfigurationUrl' => $ftc_url, 'dashboardUrl' => \esc_url( \admin_url( 'admin.php?page=wpseo_dashboard' ) ), 'explorePremiumUrl' => $this->shortlinker->build( 'https://yoa.st/ftc-premium-link' ), - ] + ], ); } @@ -166,6 +166,6 @@ public function render_page() { * @return void */ public function terminate_execution() { - exit; + exit(); } } diff --git a/src/integrations/admin/integrations-page.php b/src/integrations/admin/integrations-page.php index c9f03a62a6e..34f073b236b 100644 --- a/src/integrations/admin/integrations-page.php +++ b/src/integrations/admin/integrations-page.php @@ -179,19 +179,19 @@ public function enqueue_assets() { if ( $acf_seo_installed ) { $acf_seo_activate_url = \wp_nonce_url( \self_admin_url( 'plugins.php?action=activate&plugin=' . $acf_seo_file ), - 'activate-plugin_' . $acf_seo_file + 'activate-plugin_' . $acf_seo_file, ); } else { $acf_seo_activate_url = \wp_nonce_url( \self_admin_url( 'plugins.php?action=activate&plugin=' . $acf_seo_file_github ), - 'activate-plugin_' . $acf_seo_file_github + 'activate-plugin_' . $acf_seo_file_github, ); } $acf_seo_install_url = \wp_nonce_url( \self_admin_url( 'update.php?action=install-plugin&plugin=acf-content-analysis-for-yoast-seo' ), - 'install-plugin_acf-content-analysis-for-yoast-seo' + 'install-plugin_acf-content-analysis-for-yoast-seo', ); $this->admin_asset_manager->localize_script( @@ -226,7 +226,7 @@ public function enqueue_assets() { 'site_kit_configuration' => $this->site_kit_integration_data->to_array(), 'site_kit_consent_management_url' => $this->site_kit_consent_management_endpoint->get_url(), 'schema_framework_enabled' => $this->options_helper->get( 'enable_schema', true ) === true && ! $this->schema_configuration->is_schema_disabled_programmatically(), - ] + ], ); } diff --git a/src/integrations/admin/link-count-columns-integration.php b/src/integrations/admin/link-count-columns-integration.php index c9f72bc7ab9..e87befbc22d 100644 --- a/src/integrations/admin/link-count-columns-integration.php +++ b/src/integrations/admin/link-count-columns-integration.php @@ -138,7 +138,7 @@ public function add_post_columns( $columns ) { '%2$s', \esc_attr__( 'Number of outgoing internal links in this post.', 'wordpress-seo' ), /* translators: Hidden accessibility text. */ - \esc_html__( 'Outgoing internal links', 'wordpress-seo' ) + \esc_html__( 'Outgoing internal links', 'wordpress-seo' ), ); if ( $this->post_link_indexing_action->get_total_unindexed() === 0 ) { @@ -146,7 +146,7 @@ public function add_post_columns( $columns ) { '%2$s', \esc_attr__( 'Number of internal links linking to this post.', 'wordpress-seo' ), /* translators: Hidden accessibility text. */ - \esc_html__( 'Received internal links', 'wordpress-seo' ) + \esc_html__( 'Received internal links', 'wordpress-seo' ), ); } diff --git a/src/integrations/admin/old-configuration-integration.php b/src/integrations/admin/old-configuration-integration.php index e3d3a50a277..406b5eef635 100644 --- a/src/integrations/admin/old-configuration-integration.php +++ b/src/integrations/admin/old-configuration-integration.php @@ -39,7 +39,7 @@ public function add_submenu_page( $submenu_pages ) { '', 'manage_options', 'wpseo_configurator', - [ $this, 'render_page' ] + [ $this, 'render_page' ], ); return $submenu_pages; @@ -66,6 +66,6 @@ public function redirect_to_new_configuration() { } $redirect_url = 'admin.php?page=wpseo_dashboard#/first-time-configuration'; \wp_safe_redirect( \admin_url( $redirect_url ), 302, 'Yoast SEO' ); - exit; + exit(); } } diff --git a/src/integrations/admin/redirections-tools-page.php b/src/integrations/admin/redirections-tools-page.php index da4bb5432ea..ccbad977e7d 100644 --- a/src/integrations/admin/redirections-tools-page.php +++ b/src/integrations/admin/redirections-tools-page.php @@ -58,7 +58,7 @@ public function register_admin_menu() { $page_title = \sprintf( /* translators: %s: expands to Yoast */ \esc_html__( '%s Redirects', 'wordpress-seo' ), - 'Yoast' + 'Yoast', ); \add_management_page( @@ -66,7 +66,7 @@ public function register_admin_menu() { $page_title, 'edit_others_posts', 'wpseo_redirects_tools', - [ $this, 'show_redirects_page' ] + [ $this, 'show_redirects_page' ], ); } diff --git a/src/integrations/admin/redirects-page-integration.php b/src/integrations/admin/redirects-page-integration.php index 528e937672a..cfdc61d3a96 100644 --- a/src/integrations/admin/redirects-page-integration.php +++ b/src/integrations/admin/redirects-page-integration.php @@ -127,7 +127,7 @@ public function enqueue_assets() { 'linkParams' => \YoastSEO()->helpers->short_link->get_query_params(), 'pluginUrl' => \plugins_url( '', \WPSEO_FILE ), 'wistiaEmbedPermission' => $this->wistia_embed_permission_repository->get_value_for_user( $user_id ), - ] + ], ); } diff --git a/src/integrations/admin/workouts-integration.php b/src/integrations/admin/workouts-integration.php index 5e8867bc244..25d9285b79d 100644 --- a/src/integrations/admin/workouts-integration.php +++ b/src/integrations/admin/workouts-integration.php @@ -160,7 +160,7 @@ public function enqueue_assets() { 'isPremium' => $this->product_helper->is_premium(), 'upsellText' => $this->get_upsell_text(), 'upsellLink' => $this->get_upsell_link(), - ] + ], ); } @@ -205,9 +205,9 @@ private function get_update_premium_notice() { /* translators: %s: expands to 'Yoast SEO Premium'. */ \esc_html__( 'Accessing the latest workouts requires an updated version of %s (at least 17.7), but it looks like your subscription has expired. Please renew your subscription to update and gain access to all the latest features.', - 'wordpress-seo' + 'wordpress-seo', ), - 'Yoast SEO Premium' + 'Yoast SEO Premium', ); $button = '' . \esc_html__( 'Renew your subscription', 'wordpress-seo' ) @@ -224,7 +224,7 @@ private function get_update_premium_notice() { \esc_html__( 'It looks like you\'re running an outdated version of %1$s, please %2$supdate to the latest version (at least 17.7)%3$s to gain access to our updated workouts section.', 'wordpress-seo' ), 'Yoast SEO Premium', '', - '' + '', ); $button = null; } @@ -237,7 +237,7 @@ private function get_update_premium_notice() { \esc_html__( 'It looks like you’re running an outdated and unactivated version of %1$s, please activate your subscription in %2$sMyYoast%3$s and update to the latest version (at least 17.7) to gain access to our updated workouts section.', 'wordpress-seo' ), 'Yoast SEO Premium', '', - '' + '', ); $button = '' . \esc_html__( 'Get help activating your subscription', 'wordpress-seo' ) @@ -250,7 +250,7 @@ private function get_update_premium_notice() { $title, $copy, null, - $button + $button, ); return $notice->present(); @@ -300,20 +300,20 @@ private function get_upsell_text() { return \sprintf( /* translators: %s: expands to 'Yoast SEO Premium'. */ \__( 'Renew %s', 'wordpress-seo' ), - 'Yoast SEO Premium' + 'Yoast SEO Premium', ); } if ( $this->has_premium_subscription_activated() ) { return \sprintf( /* translators: %s: expands to 'Yoast SEO Premium'. */ \__( 'Update %s', 'wordpress-seo' ), - 'Yoast SEO Premium' + 'Yoast SEO Premium', ); } return \sprintf( /* translators: %s: expands to 'Yoast SEO Premium'. */ \__( 'Activate %s', 'wordpress-seo' ), - 'Yoast SEO Premium' + 'Yoast SEO Premium', ); } diff --git a/src/integrations/blocks/abstract-dynamic-block-v3.php b/src/integrations/blocks/abstract-dynamic-block-v3.php index c905a44e96f..4715c935214 100644 --- a/src/integrations/blocks/abstract-dynamic-block-v3.php +++ b/src/integrations/blocks/abstract-dynamic-block-v3.php @@ -62,7 +62,7 @@ public function register_block() { [ 'editor_script' => $this->script, 'render_callback' => [ $this, 'present' ], - ] + ], ); } diff --git a/src/integrations/blocks/abstract-dynamic-block.php b/src/integrations/blocks/abstract-dynamic-block.php index 4352fb1f043..bed943c9262 100644 --- a/src/integrations/blocks/abstract-dynamic-block.php +++ b/src/integrations/blocks/abstract-dynamic-block.php @@ -54,7 +54,7 @@ public function register_block() { 'type' => 'string', ], ], - ] + ], ); } diff --git a/src/integrations/blocks/block-categories.php b/src/integrations/blocks/block-categories.php index 09fa960a075..3e31312fdf3 100644 --- a/src/integrations/blocks/block-categories.php +++ b/src/integrations/blocks/block-categories.php @@ -35,7 +35,7 @@ public function add_block_categories( $categories ) { 'title' => \sprintf( /* translators: %1$s expands to Yoast. */ \__( '%1$s Structured Data Blocks', 'wordpress-seo' ), - 'Yoast' + 'Yoast', ), ]; $categories[] = [ @@ -43,7 +43,7 @@ public function add_block_categories( $categories ) { 'title' => \sprintf( /* translators: %1$s expands to Yoast. */ \__( '%1$s Internal Linking Blocks', 'wordpress-seo' ), - 'Yoast' + 'Yoast', ), ]; diff --git a/src/integrations/blocks/breadcrumbs-block.php b/src/integrations/blocks/breadcrumbs-block.php index 867729209e1..9f248cf72c4 100644 --- a/src/integrations/blocks/breadcrumbs-block.php +++ b/src/integrations/blocks/breadcrumbs-block.php @@ -100,7 +100,7 @@ public function present( $attributes ) { 'object_id' => $post_id, 'object_type' => 'post', 'object_sub_type' => $post->post_type, - ] + ], ); } diff --git a/src/integrations/blocks/structured-data-blocks.php b/src/integrations/blocks/structured-data-blocks.php index 59a5cad17c3..2adfadb92a4 100644 --- a/src/integrations/blocks/structured-data-blocks.php +++ b/src/integrations/blocks/structured-data-blocks.php @@ -88,13 +88,13 @@ public function register_blocks() { \WPSEO_PATH . 'blocks/structured-data-blocks/faq/block.json', [ 'render_callback' => [ $this, 'optimize_faq_images' ], - ] + ], ); \register_block_type( \WPSEO_PATH . 'blocks/structured-data-blocks/how-to/block.json', [ 'render_callback' => [ $this, 'optimize_how_to_images' ], - ] + ], ); } @@ -130,21 +130,21 @@ private function transform_duration_to_string( $days, $hours, $minutes ) { $strings[] = \sprintf( /* translators: %d expands to the number of day/days. */ \_n( '%d day', '%d days', $days, 'wordpress-seo' ), - $days + $days, ); } if ( $hours ) { $strings[] = \sprintf( /* translators: %d expands to the number of hour/hours. */ \_n( '%d hour', '%d hours', $hours, 'wordpress-seo' ), - $hours + $hours, ); } if ( $minutes ) { $strings[] = \sprintf( /* translators: %d expands to the number of minute/minutes. */ \_n( '%d minute', '%d minutes', $minutes, 'wordpress-seo' ), - $minutes + $minutes, ); } return $strings; @@ -170,13 +170,13 @@ private function build_duration_string( $attributes ) { return \sprintf( /* translators: %s expands to a unit of time (e.g. 1 day). */ \__( '%1$s and %2$s', 'wordpress-seo' ), - ...$elements + ...$elements, ); case 3: return \sprintf( /* translators: %s expands to a unit of time (e.g. 1 day). */ \__( '%1$s, %2$s and %3$s', 'wordpress-seo' ), - ...$elements + ...$elements, ); default: return ''; @@ -204,7 +204,7 @@ public function present_duration_text( $attributes, $content ) { '/(

    )(.*<\/span>)(.[^\/p>]*)(<\/p>)/', '

    ' . $duration_text . ' ' . $duration . '

    ', $content, - 1 + 1, ); } @@ -282,13 +282,13 @@ function ( $matches ) { 'wpseo_structured_data_blocks_image_size', $image_size, $attachment_id, - $src_matches[1] + $src_matches[1], ); $image_html = \wp_get_attachment_image( $attachment_id, $image_size, false, - $image_style + $image_style, ); if ( empty( $image_html ) ) { @@ -297,7 +297,7 @@ function ( $matches ) { return $image_html; }, - $content + $content, ); if ( ! $this->registered_shutdown_function ) { diff --git a/src/integrations/cleanup-integration.php b/src/integrations/cleanup-integration.php index 892bc1124c5..48f262dc23f 100644 --- a/src/integrations/cleanup-integration.php +++ b/src/integrations/cleanup-integration.php @@ -165,7 +165,7 @@ public function get_cleanup_tasks() { return $this->cleanup_repository->cleanup_orphaned_from_table( 'SEO_Links', 'target_indexable_id', $limit ); }, ], - $this->get_additional_misc_cleanups() + $this->get_additional_misc_cleanups(), ); } @@ -270,7 +270,7 @@ public function start_cron_job( $task_name, $schedule_time = 3600 ) { \wp_schedule_event( ( \time() + $schedule_time ), 'hourly', - self::CRON_HOOK + self::CRON_HOOK, ); } diff --git a/src/integrations/front-end-integration.php b/src/integrations/front-end-integration.php index 7e1ecd8c521..0b26ac78ba8 100644 --- a/src/integrations/front-end-integration.php +++ b/src/integrations/front-end-integration.php @@ -262,7 +262,7 @@ public function register_hooks() { \add_filter( 'wpseo_frontend_presenter_classes', [ $this, 'filter_robots_presenter' ] ); \add_action( 'wpseo_head', [ $this, 'present_head' ], -9999 ); - \add_action( 'wpseo_head', [ $this, 'update_outdated_permalink' ], -10000 ); + \add_action( 'wpseo_head', [ $this, 'update_outdated_permalink' ], -10_000 ); \remove_action( 'wp_head', 'rel_canonical' ); \remove_action( 'wp_head', 'index_rel_link' ); @@ -329,7 +329,7 @@ public function update_outdated_permalink() { $this->indexable_repository->reset_permalink( $context->indexable->object_type, $context->indexable->object_sub_type, - $context->indexable->object_id + $context->indexable->object_id, ); // Clear the memoizer caches so present_head() sees the updated indexable. @@ -501,9 +501,7 @@ public function present_head() { * @return Abstract_Indexable_Presenter[] The presenters. */ public function get_presenters( $page_type, $context = null ) { - if ( $context === null ) { - $context = $this->context_memoizer->for_current_page(); - } + $context ??= $this->context_memoizer->for_current_page(); $needed_presenters = $this->get_needed_presenters( $page_type ); @@ -535,7 +533,7 @@ public function get_presenters( $page_type, $context = null ) { return \array_merge( [ new Marker_Open_Presenter() ], $presenter_instances, - [ new Marker_Close_Presenter() ] + [ new Marker_Close_Presenter() ], ); } diff --git a/src/integrations/front-end/crawl-cleanup-rss.php b/src/integrations/front-end/crawl-cleanup-rss.php index 6f26706c58a..b2dbaf06397 100644 --- a/src/integrations/front-end/crawl-cleanup-rss.php +++ b/src/integrations/front-end/crawl-cleanup-rss.php @@ -51,7 +51,7 @@ public function register_hooks() { } \add_action( 'wp', [ $this, 'maybe_disable_feeds' ] ); - \add_action( 'wp', [ $this, 'maybe_redirect_feeds' ], -10000 ); + \add_action( 'wp', [ $this, 'maybe_redirect_feeds' ], -10_000 ); } /** @@ -183,7 +183,7 @@ private function redirect_feed( $url, $reason ) { $this->cache_control_header( 7 * \DAY_IN_SECONDS ); \wp_safe_redirect( $url, 301, 'Yoast SEO: ' . $reason ); - exit; + exit(); } /** diff --git a/src/integrations/front-end/crawl-cleanup-searches.php b/src/integrations/front-end/crawl-cleanup-searches.php index 48acf627923..d66f9e9311a 100644 --- a/src/integrations/front-end/crawl-cleanup-searches.php +++ b/src/integrations/front-end/crawl-cleanup-searches.php @@ -118,7 +118,7 @@ public function maybe_redirect_searches() { $proper_url = \home_url( '/' ); - if ( \intval( \get_query_var( 'paged' ) ) > 1 ) { + if ( (int) \get_query_var( 'paged' ) > 1 ) { $proper_url .= \sprintf( 'page/%s/', \get_query_var( 'paged' ) ); unset( $args['paged'] ); } diff --git a/src/integrations/front-end/force-rewrite-title.php b/src/integrations/front-end/force-rewrite-title.php index 357e9b90f06..ec142556fb7 100644 --- a/src/integrations/front-end/force-rewrite-title.php +++ b/src/integrations/front-end/force-rewrite-title.php @@ -75,7 +75,7 @@ public function register_hooks() { return; } - \add_action( 'template_redirect', [ $this, 'force_rewrite_output_buffer' ], 99999 ); + \add_action( 'template_redirect', [ $this, 'force_rewrite_output_buffer' ], 99_999 ); \add_action( 'wp_footer', [ $this, 'flush_cache' ], -1 ); } diff --git a/src/integrations/front-end/redirects.php b/src/integrations/front-end/redirects.php index 9f61e54b0c1..7ffcb1c542e 100644 --- a/src/integrations/front-end/redirects.php +++ b/src/integrations/front-end/redirects.php @@ -224,7 +224,7 @@ protected function get_attachment_url() { return \apply_filters( 'wpseo_attachment_redirect_url', \wp_get_attachment_url( \get_queried_object_id() ), - \get_queried_object() + \get_queried_object(), ); } diff --git a/src/integrations/front-end/robots-txt-integration.php b/src/integrations/front-end/robots-txt-integration.php index adbda35281d..9e2b6462d22 100644 --- a/src/integrations/front-end/robots-txt-integration.php +++ b/src/integrations/front-end/robots-txt-integration.php @@ -65,7 +65,7 @@ public static function get_conditionals() { * @return void */ public function register_hooks() { - \add_filter( 'robots_txt', [ $this, 'filter_robots' ], 99999 ); + \add_filter( 'robots_txt', [ $this, 'filter_robots' ], 99_999 ); if ( $this->options_helper->get( 'deny_search_crawling' ) && ! \is_multisite() ) { \add_action( 'Yoast\WP\SEO\register_robots_rules', [ $this, 'add_disallow_search_to_robots' ], 10, 1 ); @@ -157,7 +157,7 @@ protected function remove_default_robots( $robots_txt ) { return \preg_replace( '`User-agent: \*[\r\n]+Disallow: /wp-admin/[\r\n]+Allow: /wp-admin/admin-ajax\.php[\r\n]+`', '', - $robots_txt + $robots_txt, ); } diff --git a/src/integrations/front-end/wp-robots-integration.php b/src/integrations/front-end/wp-robots-integration.php index 657083a62c4..f07ca0eaa49 100644 --- a/src/integrations/front-end/wp-robots-integration.php +++ b/src/integrations/front-end/wp-robots-integration.php @@ -195,7 +195,7 @@ static function ( $a, $b ) { $bi = ( $order[ $b ] ?? 4 ); return ( $ai - $bi ); - } + }, ); return $robots; diff --git a/src/integrations/settings-integration.php b/src/integrations/settings-integration.php index 9207bea3ed7..13fb4bdd6dd 100644 --- a/src/integrations/settings-integration.php +++ b/src/integrations/settings-integration.php @@ -382,7 +382,7 @@ public function add_page( $pages ) { self::PAGE, [ $this, 'display_page' ], ], - ] + ], ); return $pages; @@ -415,7 +415,7 @@ static function () use ( $runner ) { $failure_reason = $runner->get_generation_failure_reason(); echo \esc_html( "{{ yoast-llms-txt-generation-failure: $failure_reason }}" ); } - } + }, ); return $pages; @@ -862,7 +862,7 @@ protected function transform_settings( $settings ) { $settings['wpseo_titles']['breadcrumbs-sep'] = \html_entity_decode( $settings['wpseo_titles']['breadcrumbs-sep'], ( \ENT_NOQUOTES | \ENT_HTML5 ), - 'UTF-8' + 'UTF-8', ); } @@ -872,7 +872,7 @@ protected function transform_settings( $settings ) { $settings['blogdescription'] = \html_entity_decode( $settings['blogdescription'], ( \ENT_NOQUOTES | \ENT_HTML5 ), - 'UTF-8' + 'UTF-8', ); if ( isset( $settings['wpseo_llmstxt']['other_included_pages'] ) ) { @@ -1055,7 +1055,7 @@ protected function transform_taxonomies( $taxonomies, $post_type_names ) { $taxonomy->object_type, static function ( $object_type ) use ( $post_type_names ) { return \in_array( $object_type, $post_type_names, true ); - } + }, ), 'isNew' => \in_array( $taxonomy->name, $new_taxonomies, true ), ]; @@ -1065,7 +1065,7 @@ static function ( $object_type ) use ( $post_type_names ) { $transformed, static function ( $a, $b ) { return \strnatcmp( $a['label'], $b['label'] ); - } + }, ); return $transformed; diff --git a/src/integrations/third-party/elementor.php b/src/integrations/third-party/elementor.php index 330232e2e92..eae64489f3b 100644 --- a/src/integrations/third-party/elementor.php +++ b/src/integrations/third-party/elementor.php @@ -296,7 +296,7 @@ public function save_postdata() { WPSEO_Meta::get_meta_field_defs( 'general', $post->post_type ), WPSEO_Meta::get_meta_field_defs( 'advanced', $post->post_type ), $social_fields, - WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ) + WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ), ); foreach ( $meta_boxes as $key => $meta_box ) { @@ -513,7 +513,7 @@ protected function render_hidden_fields() { \printf( '
    ', \esc_url( \admin_url( 'admin-ajax.php' ) ), - \esc_attr( $this->get_metabox_post()->ID ) + \esc_attr( $this->get_metabox_post()->ID ), ); \wp_nonce_field( 'wpseo_elementor_save', '_wpseo_elementor_nonce' ); @@ -541,7 +541,7 @@ protected function render_hidden_fields() { * If the DB value is empty we can auto-generate a slug. * But if not empty, we should not touch it anymore. */ - \esc_attr( $this->get_metabox_post()->post_name ) + \esc_attr( $this->get_metabox_post()->post_name ), ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output should be escaped in the filter. @@ -574,7 +574,7 @@ protected function get_metabox_post() { */ protected function get_metabox_script_data( $permalink ) { $post_formatter = new WPSEO_Metabox_Formatter( - new WPSEO_Post_Metabox_Formatter( $this->get_metabox_post(), [], $permalink ) + new WPSEO_Post_Metabox_Formatter( $this->get_metabox_post(), [], $permalink ), ); $values = $post_formatter->get_values(); @@ -758,7 +758,7 @@ protected function get_custom_fields_replace_vars( $post ) { [ \YoastSEO()->meta->for_post( $post->ID )->presentation->title, \YoastSEO()->meta->for_post( $post->ID )->presentation->meta_description, - ] + ], ); \preg_match_all( '/%%cf_([A-Za-z0-9_]+)%%/', $replace_vars_fields, $matches ); diff --git a/src/integrations/third-party/wpml-wpseo-notification.php b/src/integrations/third-party/wpml-wpseo-notification.php index 1e32e4bc291..df73a048ac7 100644 --- a/src/integrations/third-party/wpml-wpseo-notification.php +++ b/src/integrations/third-party/wpml-wpseo-notification.php @@ -109,12 +109,12 @@ protected function get_notification() { /* translators: %1$s expands to an opening anchor tag, %2$s expands to an closing anchor tag. */ \__( 'We notice that you have installed WPML. To make sure your canonical URLs are set correctly, %1$sinstall and activate the WPML SEO add-on%2$s as well!', 'wordpress-seo' ), '', - '' + '', ), [ 'id' => self::NOTIFICATION_ID, 'type' => Yoast_Notification::WARNING, - ] + ], ); } } diff --git a/src/integrations/watchers/addon-update-watcher.php b/src/integrations/watchers/addon-update-watcher.php index 2e6ef3eb742..133293c0cbc 100644 --- a/src/integrations/watchers/addon-update-watcher.php +++ b/src/integrations/watchers/addon-update-watcher.php @@ -83,8 +83,8 @@ public function replace_auto_update_toggles_of_addons( $old_html, $plugin ) { \sprintf( /* Translators: %1$s resolves to Yoast SEO. */ \esc_html__( 'Auto-updates are enabled based on this setting for %1$s.', 'wordpress-seo' ), - 'Yoast SEO' - ) + 'Yoast SEO', + ), ); } @@ -93,8 +93,8 @@ public function replace_auto_update_toggles_of_addons( $old_html, $plugin ) { \sprintf( /* Translators: %1$s resolves to Yoast SEO. */ \esc_html__( 'Auto-updates are disabled based on this setting for %1$s.', 'wordpress-seo' ), - 'Yoast SEO' - ) + 'Yoast SEO', + ), ); } diff --git a/src/integrations/watchers/indexable-ancestor-watcher.php b/src/integrations/watchers/indexable-ancestor-watcher.php index 515f528a75a..bd47e6fb5c6 100644 --- a/src/integrations/watchers/indexable-ancestor-watcher.php +++ b/src/integrations/watchers/indexable-ancestor-watcher.php @@ -153,7 +153,7 @@ public function get_children_for_term( $term_id, array $child_indexables ) { $child_indexables, static function ( $indexable ) { return $indexable->object_type === 'post'; - } + }, ); $existing_post_object_ids = \wp_list_pluck( $existing_post_indexables, 'object_id' ); @@ -218,8 +218,8 @@ protected function get_object_ids_for_term( $term_id, $child_indexables ) { FROM %i WHERE term_id IN( ' . \implode( ', ', \array_fill( 0, ( \count( $child_object_ids ) ), '%s' ) ) . ' )', $wpdb->term_taxonomy, - ...$child_object_ids - ) + ...$child_object_ids, + ), ); // In the case of faulty data having been saved the above query can return 0 results. @@ -235,8 +235,8 @@ protected function get_object_ids_for_term( $term_id, $child_indexables ) { FROM %i WHERE term_taxonomy_id IN( ' . \implode( ', ', \array_fill( 0, \count( $term_taxonomy_ids ), '%s' ) ) . ' )', $wpdb->term_relationships, - ...$term_taxonomy_ids - ) + ...$term_taxonomy_ids, + ), ); } } diff --git a/src/integrations/watchers/indexable-author-archive-watcher.php b/src/integrations/watchers/indexable-author-archive-watcher.php index 7452cc42161..f8ab5e67f4b 100644 --- a/src/integrations/watchers/indexable-author-archive-watcher.php +++ b/src/integrations/watchers/indexable-author-archive-watcher.php @@ -39,7 +39,7 @@ public function register_hooks() { 'update_option_wpseo_titles', [ $this, 'reschedule_indexable_cleanup_when_author_archives_are_disabled' ], 10, - 2 + 2, ); } diff --git a/src/integrations/watchers/indexable-post-watcher.php b/src/integrations/watchers/indexable-post-watcher.php index a9cf31f92b0..f8cd88d3214 100644 --- a/src/integrations/watchers/indexable-post-watcher.php +++ b/src/integrations/watchers/indexable-post-watcher.php @@ -321,7 +321,7 @@ protected function get_related_indexables( $post ) { } $related_indexables = \array_merge( $related_indexables, - $this->repository->find_by_multiple_ids_and_type( $term_ids, 'term', false ) + $this->repository->find_by_multiple_ids_and_type( $term_ids, 'term', false ), ); return \array_filter( $related_indexables ); diff --git a/src/integrations/watchers/option-titles-watcher.php b/src/integrations/watchers/option-titles-watcher.php index 89bf758c845..0225ffa4748 100644 --- a/src/integrations/watchers/option-titles-watcher.php +++ b/src/integrations/watchers/option-titles-watcher.php @@ -121,8 +121,8 @@ protected function delete_ancestors( $post_types ) { )', $hierarchy_table, $indexable_table, - ...$post_types - ) + ...$post_types, + ), ); return $result !== false; diff --git a/src/integrations/watchers/search-engines-discouraged-watcher.php b/src/integrations/watchers/search-engines-discouraged-watcher.php index 0ba2a5563b2..838d4d89f2e 100644 --- a/src/integrations/watchers/search-engines-discouraged-watcher.php +++ b/src/integrations/watchers/search-engines-discouraged-watcher.php @@ -212,7 +212,7 @@ protected function show_search_engines_discouraged_notice() { \printf( '
    %1$s
    ', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output from present() is considered safe. - $this->presenter->present() + $this->presenter->present(), ); } @@ -229,7 +229,7 @@ protected function notification() { 'id' => self::NOTIFICATION_ID, 'capabilities' => 'wpseo_manage_options', 'priority' => 1, - ] + ], ); } diff --git a/src/integrations/watchers/woocommerce-beta-editor-watcher.php b/src/integrations/watchers/woocommerce-beta-editor-watcher.php index f8b9a773a58..88e0241e47c 100644 --- a/src/integrations/watchers/woocommerce-beta-editor-watcher.php +++ b/src/integrations/watchers/woocommerce-beta-editor-watcher.php @@ -140,7 +140,7 @@ protected function notification() { 'id' => self::NOTIFICATION_ID, 'capabilities' => 'wpseo_manage_options', 'priority' => 1, - ] + ], ); } } diff --git a/src/integrations/woocommerce-product-category-permalink-integration.php b/src/integrations/woocommerce-product-category-permalink-integration.php index cd5ae3e3d94..a564724883a 100644 --- a/src/integrations/woocommerce-product-category-permalink-integration.php +++ b/src/integrations/woocommerce-product-category-permalink-integration.php @@ -69,7 +69,7 @@ public function restore_legacy_permalink_category( $category, $terms ) { [ 'parent' => 'DESC', 'term_id' => 'ASC', - ] + ], ); return $sorted_terms[0]; } diff --git a/src/introductions/application/delayed-premium-upsell.php b/src/introductions/application/delayed-premium-upsell.php index bfce0b1a474..2564a81f345 100644 --- a/src/introductions/application/delayed-premium-upsell.php +++ b/src/introductions/application/delayed-premium-upsell.php @@ -134,7 +134,7 @@ private function is_last_introduction_seen_older_than_a_week(): bool { $seen_introductions, static function ( $item ) { return \is_bool( $item ); - } + }, ); if ( ! empty( $old_format_introductions ) ) { @@ -151,7 +151,7 @@ static function ( $carry, $item ) { return $item; } return $carry; - } + }, ); // If the most recent introduction seen is older than a week, return true. diff --git a/src/introductions/application/introductions-collector.php b/src/introductions/application/introductions-collector.php index 317cd49d4f1..815680616af 100644 --- a/src/introductions/application/introductions-collector.php +++ b/src/introductions/application/introductions-collector.php @@ -47,7 +47,7 @@ public function get_for( $user_id ) { continue; } $bucket->add_introduction( - new Introduction_Item( $introduction->get_id(), $introduction->get_priority() ) + new Introduction_Item( $introduction->get_id(), $introduction->get_priority() ), ); } @@ -76,7 +76,7 @@ private function add_introductions( Introduction_Interface ...$introductions ) { $filtered_introductions, static function ( $introduction ) { return \is_a( $introduction, Introduction_Interface::class ); - } + }, ); } diff --git a/src/introductions/domain/introductions-bucket.php b/src/introductions/domain/introductions-bucket.php index 51a24806ae0..08018c3d9d7 100644 --- a/src/introductions/domain/introductions-bucket.php +++ b/src/introductions/domain/introductions-bucket.php @@ -43,7 +43,7 @@ public function to_array() { static function ( $item ) { return $item->to_array(); }, - $this->introductions + $this->introductions, ); } } diff --git a/src/introductions/user-interface/introductions-integration.php b/src/introductions/user-interface/introductions-integration.php index 4ab5faefaae..7075ccc364f 100644 --- a/src/introductions/user-interface/introductions-integration.php +++ b/src/introductions/user-interface/introductions-integration.php @@ -153,7 +153,7 @@ public function enqueue_assets() { 'pluginUrl' => \plugins_url( '', \WPSEO_FILE ), 'wistiaEmbedPermission' => $this->wistia_embed_permission_repository->get_value_for_user( $user_id ), 'isWooEnabled' => $this->woocommerce_conditional->is_met(), - ] + ], ); $this->admin_asset_manager->enqueue_style( 'introductions' ); } @@ -182,7 +182,7 @@ private function update_user_introductions( $user_id, $introductions ) { static function ( $carry, $item ) { return ( $carry === null || $item['priority'] < $carry['priority'] ) ? $item : $carry; }, - null + null, ); if ( $highest_priority_intro === null ) { diff --git a/src/introductions/user-interface/introductions-seen-route.php b/src/introductions/user-interface/introductions-seen-route.php index f19e86c3d79..dcf39b7544d 100644 --- a/src/introductions/user-interface/introductions-seen-route.php +++ b/src/introductions/user-interface/introductions-seen-route.php @@ -95,7 +95,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -119,7 +119,7 @@ public function set_introduction_seen( WP_REST_Request $request ) { return new WP_Error( 'wpseo_introductions_seen_error', $exception->getMessage(), - (object) [] + (object) [], ); } @@ -129,7 +129,7 @@ public function set_introduction_seen( WP_REST_Request $request ) { 'success' => $result, ], ], - ( $result ) ? 200 : 400 + ( $result ) ? 200 : 400, ); } return new WP_REST_Response( [], 400 ); diff --git a/src/introductions/user-interface/wistia-embed-permission-route.php b/src/introductions/user-interface/wistia-embed-permission-route.php index 619b811ac5a..a1b166748a6 100644 --- a/src/introductions/user-interface/wistia-embed-permission-route.php +++ b/src/introductions/user-interface/wistia-embed-permission-route.php @@ -81,7 +81,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -98,7 +98,7 @@ public function get_wistia_embed_permission() { return new WP_Error( 'wpseo_wistia_embed_permission_error', $exception->getMessage(), - (object) [] + (object) [], ); } @@ -107,7 +107,7 @@ public function get_wistia_embed_permission() { 'json' => (object) [ 'value' => $value, ], - ] + ], ); } @@ -120,7 +120,7 @@ public function get_wistia_embed_permission() { */ public function set_wistia_embed_permission( WP_REST_Request $request ) { $params = $request->get_json_params(); - $value = \boolval( $params['value'] ); + $value = (bool) $params['value']; try { $user_id = $this->user_helper->get_current_user_id(); @@ -129,7 +129,7 @@ public function set_wistia_embed_permission( WP_REST_Request $request ) { return new WP_Error( 'wpseo_wistia_embed_permission_error', $exception->getMessage(), - (object) [] + (object) [], ); } @@ -139,7 +139,7 @@ public function set_wistia_embed_permission( WP_REST_Request $request ) { 'success' => $result, ], ], - ( $result ) ? 200 : 400 + ( $result ) ? 200 : 400, ); } diff --git a/src/llms-txt/application/file/file-failure-notification-presenter.php b/src/llms-txt/application/file/file-failure-notification-presenter.php index 36e9dfe33a9..c408871ce86 100644 --- a/src/llms-txt/application/file/file-failure-notification-presenter.php +++ b/src/llms-txt/application/file/file-failure-notification-presenter.php @@ -38,7 +38,7 @@ protected function get_message() { /* translators: 1: Link start tag to the WordPress Reading Settings page, 2: Link closing tag. */ \esc_html__( 'An existing llms.txt file wasn\'t created by Yoast or has been edited manually. Yoast won\'t overwrite it. %1$sDelete it manually%2$s or turn off this feature.', 'wordpress-seo' ), '', - '' + '', ); break; case 'filesystem_permissions': @@ -53,7 +53,7 @@ protected function get_message() { return \sprintf( '%1$s %2$s', \esc_html__( 'Your llms.txt file couldn\'t be auto-generated', 'wordpress-seo' ), - $message + $message, ); } } diff --git a/src/llms-txt/application/markdown-builders/intro-builder.php b/src/llms-txt/application/markdown-builders/intro-builder.php index 9cdfc8fd634..2b28885db4e 100644 --- a/src/llms-txt/application/markdown-builders/intro-builder.php +++ b/src/llms-txt/application/markdown-builders/intro-builder.php @@ -27,7 +27,7 @@ protected function get_generator_version(): string { public function build_intro(): Intro { $intro_content = \sprintf( 'Generated by %s, this is an llms.txt file, meant for consumption by LLMs.', - $this->get_generator_version() + $this->get_generator_version(), ); return new Intro( $intro_content, [] ); diff --git a/src/llms-txt/application/markdown-builders/link-lists-builder.php b/src/llms-txt/application/markdown-builders/link-lists-builder.php index edee4c9f0ee..b1dcd516b5b 100644 --- a/src/llms-txt/application/markdown-builders/link-lists-builder.php +++ b/src/llms-txt/application/markdown-builders/link-lists-builder.php @@ -48,7 +48,7 @@ public function __construct( public function build_link_lists(): array { return \array_merge( $this->content_types_collector->get_content_types_lists(), - $this->terms_collector->get_terms_lists() + $this->terms_collector->get_terms_lists(), ); } } diff --git a/src/llms-txt/domain/content-types/content-type-entry.php b/src/llms-txt/domain/content-types/content-type-entry.php index 9264cba6b21..b2ab07d67d7 100644 --- a/src/llms-txt/domain/content-types/content-type-entry.php +++ b/src/llms-txt/domain/content-types/content-type-entry.php @@ -127,7 +127,7 @@ public static function from_meta( Meta $meta ): self { $meta->post->post_title, $meta->canonical, $meta->post->post_excerpt, - $meta->post->post_name + $meta->post->post_name, ); } @@ -145,7 +145,7 @@ public static function from_post( WP_Post $post, string $permalink ): self { $post->post_title, $permalink, $post->post_excerpt, - $post->post_name + $post->post_name, ); } } diff --git a/src/llms-txt/domain/markdown/sections/intro.php b/src/llms-txt/domain/markdown/sections/intro.php index 855452f7187..3fef9827fb8 100644 --- a/src/llms-txt/domain/markdown/sections/intro.php +++ b/src/llms-txt/domain/markdown/sections/intro.php @@ -73,12 +73,12 @@ public function render(): string { static function ( $link ) { return $link->render(); }, - $this->intro_links + $this->intro_links, ); $this->intro_content = \sprintf( $this->intro_content, - ...$rendered_links + ...$rendered_links, ); return $this->intro_content; } diff --git a/src/llms-txt/infrastructure/file/wordpress-file-system-adapter.php b/src/llms-txt/infrastructure/file/wordpress-file-system-adapter.php index 1add0ed8f63..edeeab169f2 100644 --- a/src/llms-txt/infrastructure/file/wordpress-file-system-adapter.php +++ b/src/llms-txt/infrastructure/file/wordpress-file-system-adapter.php @@ -23,7 +23,7 @@ public function set_file_content( string $content ): bool { $result = $wp_filesystem->put_contents( $this->get_llms_file_path(), $content, - \FS_CHMOD_FILE + \FS_CHMOD_FILE, ); return $result; diff --git a/src/llms-txt/infrastructure/markdown-services/terms-collector.php b/src/llms-txt/infrastructure/markdown-services/terms-collector.php index ca50caf2acf..abfa8ca3d40 100644 --- a/src/llms-txt/infrastructure/markdown-services/terms-collector.php +++ b/src/llms-txt/infrastructure/markdown-services/terms-collector.php @@ -48,7 +48,7 @@ public function get_terms_lists(): array { 'number' => 5, 'orderby' => 'count', 'order' => 'DESC', - ] + ], ); $term_links = new Link_List( $taxonomy->label, [] ); diff --git a/src/llms-txt/user-interface/available-posts-route.php b/src/llms-txt/user-interface/available-posts-route.php index 0734d0f78d6..517f4a5fb60 100644 --- a/src/llms-txt/user-interface/available-posts-route.php +++ b/src/llms-txt/user-interface/available-posts-route.php @@ -91,7 +91,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -113,13 +113,13 @@ public function get_available_posts( WP_REST_Request $request ): WP_REST_Respons [ 'error' => $exception->getMessage(), ], - $exception->getCode() + $exception->getCode(), ); } return new WP_REST_Response( $available_posts_container->to_array(), - 200 + 200, ); } diff --git a/src/llms-txt/user-interface/file-failure-llms-txt-notification-integration.php b/src/llms-txt/user-interface/file-failure-llms-txt-notification-integration.php index ae8c82e7f77..0f72c6ade2c 100644 --- a/src/llms-txt/user-interface/file-failure-llms-txt-notification-integration.php +++ b/src/llms-txt/user-interface/file-failure-llms-txt-notification-integration.php @@ -121,7 +121,7 @@ private function maybe_add_file_failure_notification() { 'id' => self::NOTIFICATION_ID, 'capabilities' => 'wpseo_manage_options', 'priority' => 1, - ] + ], ); $this->notification_center->restore_notification( $notification ); $this->notification_center->add_notification( $notification ); diff --git a/src/llms-txt/user-interface/health-check/file-reports.php b/src/llms-txt/user-interface/health-check/file-reports.php index 1949fafa3ab..2dbb040ed4b 100644 --- a/src/llms-txt/user-interface/health-check/file-reports.php +++ b/src/llms-txt/user-interface/health-check/file-reports.php @@ -68,7 +68,7 @@ public function get_generation_failure_result( $reason ) { '

    ', '

    ', '

    ', - '

    ' + '

    ', ); break; case 'filesystem_permissions': @@ -79,7 +79,7 @@ public function get_generation_failure_result( $reason ) { '

    ', '

    ', '

    ', - '

    ' + '

    ', ); break; default: diff --git a/src/llms-txt/user-interface/llms-txt-cron-callback-integration.php b/src/llms-txt/user-interface/llms-txt-cron-callback-integration.php index 0380afcde0e..c451256e6ca 100644 --- a/src/llms-txt/user-interface/llms-txt-cron-callback-integration.php +++ b/src/llms-txt/user-interface/llms-txt-cron-callback-integration.php @@ -75,7 +75,7 @@ public function register_hooks() { [ $this, 'populate_file', - ] + ], ); } diff --git a/src/loader.php b/src/loader.php index 5ebb14ef71b..22f46433c80 100644 --- a/src/loader.php +++ b/src/loader.php @@ -257,8 +257,8 @@ protected function conditionals_are_met( $loadable_class ) { /* translators: %1$s expands to Yoast SEO, %2$s expands to the name of the class that could not be found. */ \__( '%1$s attempted to load the class %2$s but it could not be found.', 'wordpress-seo' ), 'Yoast SEO', - $loadable_class - ) + $loadable_class, + ), ); } return false; diff --git a/src/main.php b/src/main.php index 9040dbb9984..37b0328eaf5 100644 --- a/src/main.php +++ b/src/main.php @@ -49,7 +49,7 @@ protected function get_container() { __DIR__ . '/generated/container.php', __DIR__ . '/../config/dependency-injection/services.php', __DIR__ . '/../vendor/composer/autoload_classmap.php', - 'Yoast\WP\SEO\Generated' + 'Yoast\WP\SEO\Generated', ); } diff --git a/src/memoizers/meta-tags-context-memoizer.php b/src/memoizers/meta-tags-context-memoizer.php index b54aa929381..d293456e7c5 100644 --- a/src/memoizers/meta-tags-context-memoizer.php +++ b/src/memoizers/meta-tags-context-memoizer.php @@ -146,7 +146,7 @@ public function get( Indexable $indexable, $page_type ) { 'blocks' => $blocks, 'post' => $post, 'page_type' => $page_type, - ] + ], ); $context->presentation = $this->presentation_memoizer->get( $indexable, $context, $page_type ); diff --git a/src/memoizers/presentation-memoizer.php b/src/memoizers/presentation-memoizer.php index 366f00be59e..fb619564a46 100644 --- a/src/memoizers/presentation-memoizer.php +++ b/src/memoizers/presentation-memoizer.php @@ -57,7 +57,7 @@ public function get( Indexable $indexable, Meta_Tags_Context $context, $page_typ [ 'model' => $indexable, 'context' => $context, - ] + ], ); $this->cache[ $indexable->id ] = $context->presentation; diff --git a/src/models/indexable-extension.php b/src/models/indexable-extension.php index 72b9fdaf31b..19b4a254d8d 100644 --- a/src/models/indexable-extension.php +++ b/src/models/indexable-extension.php @@ -22,9 +22,7 @@ abstract class Indexable_Extension extends Model { * @return Indexable The indexable. */ public function indexable() { - if ( $this->indexable === null ) { - $this->indexable = $this->belongs_to( 'Indexable', 'indexable_id', 'id' )->find_one(); - } + $this->indexable ??= $this->belongs_to( 'Indexable', 'indexable_id', 'id' )->find_one(); return $this->indexable; } diff --git a/src/plans/user-interface/upgrade-sidebar-menu-integration.php b/src/plans/user-interface/upgrade-sidebar-menu-integration.php index 178e22e5175..d4e94c8fa11 100644 --- a/src/plans/user-interface/upgrade-sidebar-menu-integration.php +++ b/src/plans/user-interface/upgrade-sidebar-menu-integration.php @@ -160,6 +160,6 @@ public function do_redirect(): void { } \wp_redirect( $link );//phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- Safe redirect is used here. - exit; + exit(); } } diff --git a/src/presentations/indexable-post-type-presentation.php b/src/presentations/indexable-post-type-presentation.php index e497ef14abf..dfd150cb125 100644 --- a/src/presentations/indexable-post-type-presentation.php +++ b/src/presentations/indexable-post-type-presentation.php @@ -314,7 +314,7 @@ public function generate_robots() { 'imageindex' => ( $this->model->is_robots_noimageindex === true ) ? 'noimageindex' : null, 'archive' => ( $this->model->is_robots_noarchive === true ) ? 'noarchive' : null, 'snippet' => ( $this->model->is_robots_nosnippet === true ) ? 'nosnippet' : null, - ] + ], ); // No snippet means max snippet can be omitted. diff --git a/src/presenters/abstract-indexable-tag-presenter.php b/src/presenters/abstract-indexable-tag-presenter.php index b9cef1acb17..41e92bb10c0 100644 --- a/src/presenters/abstract-indexable-tag-presenter.php +++ b/src/presenters/abstract-indexable-tag-presenter.php @@ -48,7 +48,7 @@ public function present() { $this->tag_format, $this->escape_value( $value ), $this->key, - \is_admin_bar_showing() ? ' class="yoast-seo-meta-tag"' : '' + \is_admin_bar_showing() ? ' class="yoast-seo-meta-tag"' : '', ); } diff --git a/src/presenters/admin/badge-presenter.php b/src/presenters/admin/badge-presenter.php index 217eb9977e2..088aa244ebe 100644 --- a/src/presenters/admin/badge-presenter.php +++ b/src/presenters/admin/badge-presenter.php @@ -77,14 +77,14 @@ public function present() { '%3$s', \esc_attr( $this->id ), \esc_url( $this->link ), - \esc_html__( 'New', 'wordpress-seo' ) + \esc_html__( 'New', 'wordpress-seo' ), ); } return \sprintf( '%2$s', \esc_attr( $this->id ), - \esc_html__( 'New', 'wordpress-seo' ) + \esc_html__( 'New', 'wordpress-seo' ), ); } diff --git a/src/presenters/admin/beta-badge-presenter.php b/src/presenters/admin/beta-badge-presenter.php index 684d1eb7bd1..04fce751857 100644 --- a/src/presenters/admin/beta-badge-presenter.php +++ b/src/presenters/admin/beta-badge-presenter.php @@ -46,14 +46,14 @@ public function present() { '%3$s', \esc_attr( $this->id ), \esc_url( $this->link ), - 'Beta' // We don't want this string to be translatable. + 'Beta', // We don't want this string to be translatable. ); } return \sprintf( '%2$s', \esc_attr( $this->id ), - 'Beta' // We don't want this string to be translatable. + 'Beta', // We don't want this string to be translatable. ); } } diff --git a/src/presenters/admin/help-link-presenter.php b/src/presenters/admin/help-link-presenter.php index 45db58bfa64..b8a7256c72b 100644 --- a/src/presenters/admin/help-link-presenter.php +++ b/src/presenters/admin/help-link-presenter.php @@ -80,7 +80,7 @@ public function present() { '%3$s', \esc_url( $this->link ), $target_blank_attribute, - \esc_html( $this->link_text . $new_tab_message ) + \esc_html( $this->link_text . $new_tab_message ), ); } } diff --git a/src/presenters/admin/indexing-error-presenter.php b/src/presenters/admin/indexing-error-presenter.php index e5079f0a9af..7c773569880 100644 --- a/src/presenters/admin/indexing-error-presenter.php +++ b/src/presenters/admin/indexing-error-presenter.php @@ -63,7 +63,7 @@ public function __construct( protected function generate_first_paragraph( $is_premium, $has_valid_premium_subscription ) { $message = \__( 'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please click the button again to re-start the process. ', - 'wordpress-seo' + 'wordpress-seo', ); if ( $is_premium ) { @@ -75,10 +75,10 @@ protected function generate_first_paragraph( $is_premium, $has_valid_premium_sub /* translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. */ \__( 'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please make sure to activate your subscription in MyYoast by completing %1$sthese steps%2$s.', - 'wordpress-seo' + 'wordpress-seo', ), '', - '' + '', ); } } @@ -101,10 +101,10 @@ protected function generate_second_paragraph( $is_premium, $has_valid_premium_su /* translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. */ \__( 'Below are the technical details for the error. See %1$sthis page%2$s for a more detailed explanation.', - 'wordpress-seo' + 'wordpress-seo', ), '', - '' + '', ); } diff --git a/src/presenters/admin/indexing-failed-notification-presenter.php b/src/presenters/admin/indexing-failed-notification-presenter.php index 28ce7287ae4..0ba6d675412 100644 --- a/src/presenters/admin/indexing-failed-notification-presenter.php +++ b/src/presenters/admin/indexing-failed-notification-presenter.php @@ -58,10 +58,10 @@ public function present() { /* Translators: %1$s expands to an opening anchor tag for a link leading to the Yoast SEO tools page, %2$s expands to a closing anchor tag. */ \esc_html__( 'Something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please %1$sre-start the process%2$s.', - 'wordpress-seo' + 'wordpress-seo', ), '', - '' + '', ); if ( $this->product_helper->is_premium() ) { @@ -76,10 +76,10 @@ public function present() { /* Translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. */ \esc_html__( 'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please make sure to activate your subscription in MyYoast by completing %1$sthese steps%2$s.', - 'wordpress-seo' + 'wordpress-seo', ), '', - '' + '', ); } } diff --git a/src/presenters/admin/indexing-list-item-presenter.php b/src/presenters/admin/indexing-list-item-presenter.php index 09a0458ec46..38f24353d62 100644 --- a/src/presenters/admin/indexing-list-item-presenter.php +++ b/src/presenters/admin/indexing-list-item-presenter.php @@ -39,7 +39,7 @@ public function present() { '%1$s %3$s', \esc_html__( 'You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. If you have a lot of content it might take a while, but trust us, it\'s worth it.', 'wordpress-seo' ), \esc_url( $this->short_link_helper->get( 'https://yoa.st/3-z' ) ), - \esc_html__( 'Learn more about the benefits of optimized SEO data.', 'wordpress-seo' ) + \esc_html__( 'Learn more about the benefits of optimized SEO data.', 'wordpress-seo' ), ); $output .= '
    '; diff --git a/src/presenters/admin/indexing-notification-presenter.php b/src/presenters/admin/indexing-notification-presenter.php index f57b343a971..03b96c2fefd 100644 --- a/src/presenters/admin/indexing-notification-presenter.php +++ b/src/presenters/admin/indexing-notification-presenter.php @@ -127,7 +127,7 @@ protected function get_time_estimate( $total_unindexed ) { $estimate .= \sprintf( /* translators: 1: Expands to Yoast SEO */ \esc_html__( 'Wait for a week or so, until %1$s automatically processes most of your content in the background.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); $estimate .= ''; $estimate .= '
  • '; @@ -136,7 +136,7 @@ protected function get_time_estimate( $total_unindexed ) { \esc_html__( '%1$sRun the indexation process on your server%2$s using %3$sWP CLI%2$s.', 'wordpress-seo' ), '', '', - '' + '', ); $estimate .= '
  • '; diff --git a/src/presenters/admin/light-switch-presenter.php b/src/presenters/admin/light-switch-presenter.php index 837c4bc4642..2ad3ec1d26c 100644 --- a/src/presenters/admin/light-switch-presenter.php +++ b/src/presenters/admin/light-switch-presenter.php @@ -137,7 +137,7 @@ public function present() { $strong_class, // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $strong_class output is hardcoded. \esc_attr( $this->var . '-label' ), \esc_html( $this->label ), - $this->help // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: The help contains HTML. + $this->help, // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: The help contains HTML. ); $output .= '', - '' + '', ); $reassurance = \sprintf( /* translators: %s: Yoast SEO. */ \esc_html__( 'Your site will continue to work normally, but won\'t take full advantage of %s.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); $debug_info = \sprintf( '
    %1$s

    %2$s

    ', \esc_html__( 'Show debug information', 'wordpress-seo' ), - \esc_html( $this->migration_error['message'] ) + \esc_html( $this->migration_error['message'] ), ); return \sprintf( @@ -71,7 +71,7 @@ public function present() { $message, $support, $reassurance, - $debug_info + $debug_info, ); } } diff --git a/src/presenters/admin/notice-presenter.php b/src/presenters/admin/notice-presenter.php index d7d5bd70fc2..abd048b9de2 100644 --- a/src/presenters/admin/notice-presenter.php +++ b/src/presenters/admin/notice-presenter.php @@ -105,7 +105,7 @@ public function present() { $out .= ''; $out .= \sprintf( '

    %s

    ', - \esc_html( $this->title ) + \esc_html( $this->title ), ); $out .= '
    '; $out .= '
    '; diff --git a/src/presenters/admin/premium-badge-presenter.php b/src/presenters/admin/premium-badge-presenter.php index bfb8d95ad4c..3b4de118658 100644 --- a/src/presenters/admin/premium-badge-presenter.php +++ b/src/presenters/admin/premium-badge-presenter.php @@ -46,14 +46,14 @@ public function present() { '%3$s', \esc_attr( $this->id ), \esc_url( $this->link ), - 'Premium' // We don't want this string to be translatable. + 'Premium', // We don't want this string to be translatable. ); } return \sprintf( '%2$s', \esc_attr( $this->id ), - 'Premium' // We don't want this string to be translatable. + 'Premium', // We don't want this string to be translatable. ); } } diff --git a/src/presenters/admin/search-engines-discouraged-presenter.php b/src/presenters/admin/search-engines-discouraged-presenter.php index c8ef2a30e86..035872f53b9 100644 --- a/src/presenters/admin/search-engines-discouraged-presenter.php +++ b/src/presenters/admin/search-engines-discouraged-presenter.php @@ -35,10 +35,10 @@ protected function get_message() { /* translators: 1: Link start tag to the WordPress Reading Settings page, 2: Link closing tag. */ \esc_html__( 'If you want search engines to show this site in their results, you must %1$sgo to your Reading Settings%2$s and uncheck the box for Search Engine Visibility.', 'wordpress-seo' ), '', - '' + '', ), \esc_js( \wp_create_nonce( 'wpseo-ignore' ) ), - \esc_html__( 'I don\'t want this site to show in the search results.', 'wordpress-seo' ) + \esc_html__( 'I don\'t want this site to show in the search results.', 'wordpress-seo' ), ); } } diff --git a/src/presenters/admin/woocommerce-beta-editor-presenter.php b/src/presenters/admin/woocommerce-beta-editor-presenter.php index 048121b51c6..feada41238f 100644 --- a/src/presenters/admin/woocommerce-beta-editor-presenter.php +++ b/src/presenters/admin/woocommerce-beta-editor-presenter.php @@ -53,8 +53,8 @@ protected function get_message() { \esc_html__( 'The %1$s interface is currently unavailable in the beta WooCommerce product editor. To resolve any issues, please disable the beta editor. %2$sLearn how to disable the beta WooCommerce product editor.%3$s', 'wordpress-seo' ), 'Yoast SEO', '', - '' - ) + '', + ), ); } } diff --git a/src/presenters/debug/marker-close-presenter.php b/src/presenters/debug/marker-close-presenter.php index b36ad7fa6f5..8b534442069 100644 --- a/src/presenters/debug/marker-close-presenter.php +++ b/src/presenters/debug/marker-close-presenter.php @@ -26,7 +26,7 @@ public function present() { return \sprintf( '', - \esc_html( $this->helpers->product->get_name() ) + \esc_html( $this->helpers->product->get_name() ), ); } diff --git a/src/presenters/debug/marker-open-presenter.php b/src/presenters/debug/marker-open-presenter.php index 09c821a65f4..b6679213bcd 100644 --- a/src/presenters/debug/marker-open-presenter.php +++ b/src/presenters/debug/marker-open-presenter.php @@ -34,7 +34,7 @@ public function present() { '', $product_name, $version, - $url + $url, ); } diff --git a/src/presenters/meta-description-presenter.php b/src/presenters/meta-description-presenter.php index 699632a6e86..57ead3c5aaf 100644 --- a/src/presenters/meta-description-presenter.php +++ b/src/presenters/meta-description-presenter.php @@ -34,7 +34,7 @@ public function present() { /* translators: %1$s resolves to Yoast SEO, %2$s resolves to the Settings submenu item. */ \esc_html__( 'Admin only notice: this page does not show a meta description because it does not have one, either write it for this page specifically or go into the [%1$s - %2$s] menu and set up a template.', 'wordpress-seo' ), \esc_html__( 'Yoast SEO', 'wordpress-seo' ), - \esc_html__( 'Settings', 'wordpress-seo' ) + \esc_html__( 'Settings', 'wordpress-seo' ), ) . ' -->'; } diff --git a/src/presenters/open-graph/image-presenter.php b/src/presenters/open-graph/image-presenter.php index 7da1a3119b7..f2e0f8944de 100644 --- a/src/presenters/open-graph/image-presenter.php +++ b/src/presenters/open-graph/image-presenter.php @@ -78,7 +78,7 @@ public function get() { // First filter the object. $this->filter( $open_graph_image ), // Then strip all keys that aren't in the image tags or the url. - \array_flip( \array_merge( static::$image_tags, [ 'url' ] ) ) + \array_flip( \array_merge( static::$image_tags, [ 'url' ] ) ), ); } diff --git a/src/presenters/score-icon-presenter.php b/src/presenters/score-icon-presenter.php index 322684c15c4..eb3d122eeee 100644 --- a/src/presenters/score-icon-presenter.php +++ b/src/presenters/score-icon-presenter.php @@ -42,7 +42,7 @@ public function present() { '', \esc_attr( $this->title ), \esc_html( $this->title ), - \esc_attr( $this->css_class ) + \esc_attr( $this->css_class ), ); } } diff --git a/src/promotions/domain/black-friday-promotion.php b/src/promotions/domain/black-friday-promotion.php index fbf0e4958e4..fba11dded86 100644 --- a/src/promotions/domain/black-friday-promotion.php +++ b/src/promotions/domain/black-friday-promotion.php @@ -13,7 +13,7 @@ class Black_Friday_Promotion extends Abstract_Promotion implements Promotion_Int public function __construct() { parent::__construct( 'black-friday-promotion', - new Time_Interval( \gmmktime( 10, 00, 00, 11, 27, 2025 ), \gmmktime( 10, 00, 00, 12, 2, 2025 ) ) + new Time_Interval( \gmmktime( 10, 00, 00, 11, 27, 2025 ), \gmmktime( 10, 00, 00, 12, 2, 2025 ) ), ); } } diff --git a/src/repositories/indexable-cleanup-repository.php b/src/repositories/indexable-cleanup-repository.php index 11c630a8880..61ece88f8fc 100644 --- a/src/repositories/indexable-cleanup-repository.php +++ b/src/repositories/indexable-cleanup-repository.php @@ -149,7 +149,7 @@ public function clean_indexables_for_non_publicly_viewable_post( $limit ) { WHERE object_type = 'post' AND object_sub_type IS NOT NULL LIMIT %d", - $limit + $limit, ); } else { @@ -160,7 +160,7 @@ public function clean_indexables_for_non_publicly_viewable_post( $limit ) { AND object_sub_type IS NOT NULL AND object_sub_type NOT IN ( " . \implode( ', ', \array_fill( 0, \count( $included_post_types ), '%s' ) ) . ' ) LIMIT %d', - \array_merge( $included_post_types, [ $limit ] ) + \array_merge( $included_post_types, [ $limit ] ), ); } // phpcs:enable @@ -217,7 +217,7 @@ public function clean_indexables_for_non_publicly_viewable_taxonomies( $limit ) WHERE object_type = 'term' AND object_sub_type IS NOT NULL LIMIT %d", - $limit + $limit, ); } else { @@ -228,7 +228,7 @@ public function clean_indexables_for_non_publicly_viewable_taxonomies( $limit ) AND object_sub_type IS NOT NULL AND object_sub_type NOT IN ( " . \implode( ', ', \array_fill( 0, \count( $included_taxonomies ), '%s' ) ) . ' ) LIMIT %d', - \array_merge( $included_taxonomies, [ $limit ] ) + \array_merge( $included_taxonomies, [ $limit ] ), ); } // phpcs:enable @@ -265,7 +265,7 @@ public function clean_indexables_for_non_publicly_viewable_post_type_archive_pag WHERE object_type = 'post-type-archive' AND object_sub_type IS NOT NULL LIMIT %d", - $limit + $limit, ); } else { @@ -276,7 +276,7 @@ public function clean_indexables_for_non_publicly_viewable_post_type_archive_pag AND object_sub_type IS NOT NULL AND object_sub_type NOT IN ( " . \implode( ', ', \array_fill( 0, \count( $post_archives ), '%s' ) ) . ' ) LIMIT %d', - \array_merge( $post_archives, [ $limit ] ) + \array_merge( $post_archives, [ $limit ] ), ); } // phpcs:enable @@ -409,7 +409,7 @@ public function clean_indexables_for_authors_without_archive( $limit ) { WHERE post_type IN ( " . \implode( ', ', \array_fill( 0, \count( $author_archive_post_types ), '%s' ) ) . ' ) AND post_status IN ( ' . \implode( ', ', \array_fill( 0, \count( $viewable_post_stati ), '%s' ) ) . ' ) ) LIMIT %d', - \array_merge( $author_archive_post_types, $viewable_post_stati, [ $limit ] ) + \array_merge( $author_archive_post_types, $viewable_post_stati, [ $limit ] ), ); // phpcs:enable @@ -443,7 +443,7 @@ public function count_indexables_for_authors_without_archive() { WHERE post_type IN ( " . \implode( ', ', \array_fill( 0, \count( $author_archive_post_types ), '%s' ) ) . ' ) AND post_status IN ( ' . \implode( ', ', \array_fill( 0, \count( $viewable_post_stati ), '%s' ) ) . ' ) )', - \array_merge( $author_archive_post_types, $viewable_post_stati ) + \array_merge( $author_archive_post_types, $viewable_post_stati ), ); // phpcs:enable @@ -480,7 +480,7 @@ public function clean_indexables_for_object_type_and_source_table( $source_table AND indexable_table.object_id IS NOT NULL AND indexable_table.object_type = '{$object_type}' LIMIT %d", - $limit + $limit, ); // phpcs:enable @@ -518,7 +518,7 @@ public function clean_indexables_for_orphaned_users( $limit ) { AND indexable_table.object_id IS NOT NULL AND indexable_table.object_type = 'user' LIMIT %d", - $limit + $limit, ); // phpcs:enable @@ -555,7 +555,7 @@ public function count_indexables_for_object_type_and_source_table( string $sourc ON indexable_table.object_id = source_table.{$source_identifier} WHERE source_table.{$source_identifier} IS NULL AND indexable_table.object_id IS NOT NULL - AND indexable_table.object_type = '{$object_type}'" + AND indexable_table.object_type = '{$object_type}'", )[0]; // phpcs:enable } @@ -578,7 +578,7 @@ public function count_indexables_for_orphaned_users() { ON indexable_table.object_id = source_table.ID WHERE source_table.ID IS NULL AND indexable_table.object_id IS NOT NULL - AND indexable_table.object_type = 'user'" + AND indexable_table.object_type = 'user'", )[0]; // phpcs:enable } @@ -609,7 +609,7 @@ public function cleanup_orphaned_from_table( $table, $column, $limit ) { WHERE indexable_table.id IS NULL AND table_to_clean.{$column} IS NOT NULL LIMIT %d", - $limit + $limit, ); // phpcs:enable @@ -647,7 +647,7 @@ public function count_orphaned_from_table( string $table, string $column ) { LEFT JOIN {$indexable_table} AS indexable_table ON table_to_clean.{$column} = indexable_table.id WHERE indexable_table.id IS NULL - AND table_to_clean.{$column} IS NOT NULL" + AND table_to_clean.{$column} IS NOT NULL", )[0]; // phpcs:enable } @@ -697,7 +697,7 @@ private function get_reassigned_authors( $limit ) { GROUP BY {$indexable_table}.author_id, {$posts_table}.post_author ORDER BY {$indexable_table}.author_id LIMIT %d", - $limit + $limit, ); // phpcs:enable @@ -724,7 +724,7 @@ private function update_indexable_authors( $reassigned_authors_objs, $limit ) { static function ( $obj ) { return (array) $obj; }, - $reassigned_authors_objs + $reassigned_authors_objs, ); $reassigned_authors = \array_combine( \array_column( $reassigned_authors_array, 'author_id' ), \array_column( $reassigned_authors_array, 'post_author' ) ); @@ -738,7 +738,7 @@ static function ( $obj ) { WHERE {$indexable_table}.author_id = {$old_author_id} AND object_type='post' LIMIT %d", - $limit + $limit, ); // phpcs:enable diff --git a/src/repositories/indexable-hierarchy-repository.php b/src/repositories/indexable-hierarchy-repository.php index 1d83ed759b7..3db994da330 100644 --- a/src/repositories/indexable-hierarchy-repository.php +++ b/src/repositories/indexable-hierarchy-repository.php @@ -84,7 +84,7 @@ public function add_ancestor( $indexable_id, $ancestor_id, $depth ) { 'ancestor_id' => $ancestor_id, 'depth' => $depth, 'blog_id' => \get_current_blog_id(), - ] + ], ); return $hierarchy->save(); diff --git a/src/repositories/indexable-repository.php b/src/repositories/indexable-repository.php index 1839b86dc08..76ea78a3542 100644 --- a/src/repositories/indexable-repository.php +++ b/src/repositories/indexable-repository.php @@ -149,7 +149,7 @@ public function for_current_page() { 'object_type' => 'unknown', 'post_status' => 'unindexed', 'version' => 1, - ] + ], ); } @@ -600,7 +600,7 @@ public function reset_permalink( $type = null, $subtype = null, $object_id = nul 'permalink' => null, 'permalink_hash' => null, 'version' => 0, - ] + ], ); if ( $type !== null ) { diff --git a/src/repositories/seo-links-repository.php b/src/repositories/seo-links-repository.php index 325f9ed2b65..a0648fe8050 100644 --- a/src/repositories/seo-links-repository.php +++ b/src/repositories/seo-links-repository.php @@ -175,7 +175,7 @@ public function get_incoming_link_counts_for_indexable_ids( $indexable_ids ) { // Loop over the original ID's and search them in the returned ID's. If they don't exist, add them with an incoming count of 0. foreach ( $indexable_ids as $id ) { // Cast the ID to string, as the arrays only contain stringified versions of the ID. - $id = \strval( $id ); + $id = (string) $id; if ( isset( $returned_ids[ $id ] ) === false ) { $indexable_counts[] = [ 'incoming' => '0', diff --git a/src/routes/abstract-action-route.php b/src/routes/abstract-action-route.php index 9ee3f07aa6e..e26ef329629 100644 --- a/src/routes/abstract-action-route.php +++ b/src/routes/abstract-action-route.php @@ -24,7 +24,7 @@ protected function respond_with( $objects, $next_url ) { [ 'objects' => $objects, 'next_url' => $next_url, - ] + ], ); } } diff --git a/src/routes/alert-dismissal-route.php b/src/routes/alert-dismissal-route.php index b6056647f34..515eaf8cce9 100644 --- a/src/routes/alert-dismissal-route.php +++ b/src/routes/alert-dismissal-route.php @@ -89,7 +89,7 @@ public function dismiss( WP_REST_Request $request ) { 'success' => $success, 'status' => $status, ], - $status + $status, ); } diff --git a/src/routes/first-time-configuration-route.php b/src/routes/first-time-configuration-route.php index 7774bfe58dc..41b339a9a5a 100644 --- a/src/routes/first-time-configuration-route.php +++ b/src/routes/first-time-configuration-route.php @@ -218,7 +218,7 @@ public function set_social_profiles( WP_REST_Request $request ) { ->set_social_profiles( $request->get_json_params() ); return new WP_REST_Response( - [ 'json' => $data ] + [ 'json' => $data ], ); } diff --git a/src/routes/importing-route.php b/src/routes/importing-route.php index c30ad66f11e..91882146b4e 100644 --- a/src/routes/importing-route.php +++ b/src/routes/importing-route.php @@ -68,7 +68,7 @@ public function register_routes() { 'callback' => [ $this, 'execute' ], 'permission_callback' => [ $this, 'is_user_permitted_to_import' ], 'methods' => [ 'POST' ], - ] + ], ); } @@ -94,7 +94,7 @@ public function execute( $data ) { 'Requested importer not found', [ 'status' => 404, - ] + ], ); } @@ -106,21 +106,21 @@ public function execute( $data ) { return $this->respond_with( $result, - $next_url + $next_url, ); } catch ( Exception $exception ) { if ( $exception instanceof Aioseo_Validation_Exception ) { return new WP_Error( 'wpseo_error_validation', $exception->getMessage(), - [ 'stackTrace' => $exception->getTraceAsString() ] + [ 'stackTrace' => $exception->getTraceAsString() ], ); } return new WP_Error( 'wpseo_error_indexing', $exception->getMessage(), - [ 'stackTrace' => $exception->getTraceAsString() ] + [ 'stackTrace' => $exception->getTraceAsString() ], ); } } diff --git a/src/routes/indexing-route.php b/src/routes/indexing-route.php index 03f98c84d43..898907cefc3 100644 --- a/src/routes/indexing-route.php +++ b/src/routes/indexing-route.php @@ -424,7 +424,7 @@ protected function run_indexation_action( Indexation_Action_Interface $indexatio return new WP_Error( 'wpseo_error_indexing', $exception->getMessage(), - [ 'stackTrace' => $exception->getTraceAsString() ] + [ 'stackTrace' => $exception->getTraceAsString() ], ); } } diff --git a/src/routes/integrations-route.php b/src/routes/integrations-route.php index 2e6dec53d14..b457735dcc3 100644 --- a/src/routes/integrations-route.php +++ b/src/routes/integrations-route.php @@ -95,7 +95,7 @@ public function set_integration_active( WP_REST_Request $request ) { ->set_integration_active( $integration_name, $value ); return new WP_REST_Response( - [ 'json' => $data ] + [ 'json' => $data ], ); } } diff --git a/src/routes/semrush-route.php b/src/routes/semrush-route.php index 9e089c8714c..78176504a65 100644 --- a/src/routes/semrush-route.php +++ b/src/routes/semrush-route.php @@ -220,7 +220,7 @@ public function get_related_keyphrases( WP_REST_Request $request ) { ->phrases_action ->get_related_keyphrases( $request['keyphrase'], - $request['country_code'] + $request['country_code'], ); return new WP_REST_Response( $data, $data->status ); diff --git a/src/routes/supported-features-route.php b/src/routes/supported-features-route.php index dd19898ef4d..14fc519d1ff 100644 --- a/src/routes/supported-features-route.php +++ b/src/routes/supported-features-route.php @@ -53,7 +53,7 @@ public function get_supported_features() { return new WP_REST_Response( [ 'addon-installation' => 1, - ] + ], ); } } diff --git a/src/routes/workouts-route.php b/src/routes/workouts-route.php index af97b54ad35..921e9a16701 100644 --- a/src/routes/workouts-route.php +++ b/src/routes/workouts-route.php @@ -81,7 +81,7 @@ public function get_workouts() { $workouts_option = \apply_filters( 'Yoast\WP\SEO\workouts_options', $workouts_option ); return new WP_REST_Response( - [ 'json' => $workouts_option ] + [ 'json' => $workouts_option ], ); } @@ -105,7 +105,7 @@ public function set_workouts( $request ) { $result = \apply_filters( 'Yoast\WP\SEO\workouts_route_save', null, $workouts_data ); return new WP_REST_Response( - [ 'json' => $result ] + [ 'json' => $result ], ); } diff --git a/src/schema/application/configuration/schema-configuration.php b/src/schema/application/configuration/schema-configuration.php index 06c04080489..a9a7917fe3c 100644 --- a/src/schema/application/configuration/schema-configuration.php +++ b/src/schema/application/configuration/schema-configuration.php @@ -92,7 +92,7 @@ public function get_schema_api_integrations(): array { $woocommerce_seo_activate_url = \wp_nonce_url( \self_admin_url( 'plugins.php?action=activate&plugin=' . $woocommerce_seo_file ), - 'activate-plugin_' . $woocommerce_seo_file + 'activate-plugin_' . $woocommerce_seo_file, ); $is_premium = $this->product_helper->is_premium(); diff --git a/src/services/health-check/default-tagline-reports.php b/src/services/health-check/default-tagline-reports.php index 413b0689b53..46aef484679 100644 --- a/src/services/health-check/default-tagline-reports.php +++ b/src/services/health-check/default-tagline-reports.php @@ -62,7 +62,7 @@ private function get_actions() { /* translators: 1: link open tag; 2: link close tag. */ \esc_html__( '%1$sYou can change the tagline in the customizer%2$s.', 'wordpress-seo' ), '', - '' + '', ); } } diff --git a/src/services/health-check/links-table-reports.php b/src/services/health-check/links-table-reports.php index 1e71e23b712..e06bebd1b78 100644 --- a/src/services/health-check/links-table-reports.php +++ b/src/services/health-check/links-table-reports.php @@ -72,7 +72,7 @@ private function get_success_description() { /* translators: 1: Link to the Yoast SEO blog, 2: Link closing tag. */ \esc_html__( 'The text link counter helps you improve your site structure. %1$sFind out how the text link counter can enhance your SEO%2$s.', 'wordpress-seo' ), '', - WPSEO_Admin_Utils::get_new_tab_message() . '' + WPSEO_Admin_Utils::get_new_tab_message() . '', ); } @@ -85,7 +85,7 @@ private function get_links_table_not_accessible_description() { return \sprintf( /* translators: 1: Yoast SEO. */ \__( 'For this feature to work, %1$s needs to create a table in your database. We were unable to create this table automatically.', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); } @@ -99,7 +99,7 @@ private function get_actions() { /* translators: 1: Link to the Yoast help center, 2: Link closing tag. */ \esc_html__( '%1$sFind out how to solve this problem on our help center%2$s.', 'wordpress-seo' ), '', - WPSEO_Admin_Utils::get_new_tab_message() . '' + WPSEO_Admin_Utils::get_new_tab_message() . '', ); } } diff --git a/src/services/health-check/page-comments-reports.php b/src/services/health-check/page-comments-reports.php index 17812d2c648..4e0f345c28a 100644 --- a/src/services/health-check/page-comments-reports.php +++ b/src/services/health-check/page-comments-reports.php @@ -57,7 +57,7 @@ private function get_has_comments_on_multiple_pages_actions() { /* translators: 1: Opening tag of the link to the discussion settings page, 2: Link closing tag. */ \esc_html__( '%1$sGo to the Discussion Settings page%2$s', 'wordpress-seo' ), '', - '' + '', ); } } diff --git a/src/services/health-check/postname-permalink-reports.php b/src/services/health-check/postname-permalink-reports.php index 6cbe125363f..469f7fa7610 100644 --- a/src/services/health-check/postname-permalink-reports.php +++ b/src/services/health-check/postname-permalink-reports.php @@ -56,7 +56,7 @@ private function get_has_no_postname_in_permalink_description() { return \sprintf( /* translators: %s expands to '/%postname%/' */ \__( 'It\'s highly recommended to have your postname in the URL of your posts and pages. Consider setting your permalink structure to %s.', 'wordpress-seo' ), - '/%postname%/' + '/%postname%/', ); } @@ -70,7 +70,7 @@ private function get_has_no_postname_in_permalink_actions() { /* translators: %1$s is a link start tag to the permalink settings page, %2$s is the link closing tag. */ \__( 'You can fix this on the %1$sPermalink settings page%2$s.', 'wordpress-seo' ), '', - '' + '', ); } } diff --git a/src/services/health-check/report-builder.php b/src/services/health-check/report-builder.php index 1e56466191e..1d5ae6b98ec 100644 --- a/src/services/health-check/report-builder.php +++ b/src/services/health-check/report-builder.php @@ -201,7 +201,7 @@ private function get_signature() { \esc_html__( '%1$sThis was reported by the %2$s plugin%3$s', 'wordpress-seo' ), '

    ', 'Yoast SEO', - '

    ' + '

    ', ); } } diff --git a/src/services/importing/aioseo/aioseo-replacevar-service.php b/src/services/importing/aioseo/aioseo-replacevar-service.php index a7ef3324a22..3f9cd130ac5 100644 --- a/src/services/importing/aioseo/aioseo-replacevar-service.php +++ b/src/services/importing/aioseo/aioseo-replacevar-service.php @@ -81,7 +81,7 @@ public function transform( $aioseo_replacevar ) { static function ( $cf_matches ) { return '%%cf_' . $cf_matches[1] . '%%'; }, - $yoast_replacevar + $yoast_replacevar, ); // Transform the '#tax_name-' tags into '%%ct_%%' ones. @@ -90,7 +90,7 @@ static function ( $cf_matches ) { static function ( $ct_matches ) { return '%%ct_' . $ct_matches[1] . '%%'; }, - $yoast_replacevar + $yoast_replacevar, ); return $yoast_replacevar; diff --git a/src/services/importing/aioseo/aioseo-social-images-provider-service.php b/src/services/importing/aioseo/aioseo-social-images-provider-service.php index ad4871f680b..05044c692a0 100644 --- a/src/services/importing/aioseo/aioseo-social-images-provider-service.php +++ b/src/services/importing/aioseo/aioseo-social-images-provider-service.php @@ -126,7 +126,7 @@ public function get_first_attached_image( $post_id ) { 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', - ] + ], ); if ( $attachments && ! empty( $attachments ) ) { diff --git a/src/services/importing/importable-detector-service.php b/src/services/importing/importable-detector-service.php index b779b54d84d..66330bc1475 100644 --- a/src/services/importing/importable-detector-service.php +++ b/src/services/importing/importable-detector-service.php @@ -80,7 +80,7 @@ public function filter_actions( $all_actions, $plugin = null, $type = null ) { $all_actions, static function ( $action ) use ( $plugin, $type ) { return $action->is_compatible_with( $plugin, $type ); - } + }, ); } } diff --git a/src/surfaces/meta-surface.php b/src/surfaces/meta-surface.php index f54b14dbc70..ebcd6c92750 100644 --- a/src/surfaces/meta-surface.php +++ b/src/surfaces/meta-surface.php @@ -145,9 +145,7 @@ public function for_posts_page() { * @return Meta|false The meta values. False if none could be found. */ public function for_post_type_archive( $post_type = null ) { - if ( $post_type === null ) { - $post_type = \get_post_type(); - } + $post_type ??= \get_post_type(); $indexable = $this->repository->find_for_post_type_archive( $post_type ); @@ -226,7 +224,7 @@ public function for_posts( $ids ) { function ( $indexable ) { return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) ); }, - $indexables + $indexables, ); } @@ -277,9 +275,7 @@ public function for_indexable( $indexable, $page_type = null ) { if ( ! \is_a( $indexable, Indexable::class ) ) { return false; } - if ( $page_type === null ) { - $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); - } + $page_type ??= $this->indexable_helper->get_page_type_for_indexable( $indexable ); return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) ); } @@ -294,10 +290,8 @@ public function for_indexable( $indexable, $page_type = null ) { */ public function for_indexables( $indexables, $page_type = null ) { $closure = function ( $indexable ) use ( $page_type ) { - $this_page_type = $page_type; - if ( $this_page_type === null ) { - $this_page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); - } + $this_page_type = $page_type; + $this_page_type ??= $this->indexable_helper->get_page_type_for_indexable( $indexable ); return $this->build_meta( $this->context_memoizer->get( $indexable, $this_page_type ) ); }; diff --git a/src/task-list/application/tasks/complete-ftc.php b/src/task-list/application/tasks/complete-ftc.php index ad137e22529..162fb7185d1 100644 --- a/src/task-list/application/tasks/complete-ftc.php +++ b/src/task-list/application/tasks/complete-ftc.php @@ -77,7 +77,7 @@ public function get_call_to_action(): Call_To_Action_Entry { return new Call_To_Action_Entry( \__( 'Start configuration', 'wordpress-seo' ), 'link', - $this->get_link() + $this->get_link(), ); } diff --git a/src/task-list/application/tasks/create-new-content.php b/src/task-list/application/tasks/create-new-content.php index 7624b3da101..f17033d040e 100644 --- a/src/task-list/application/tasks/create-new-content.php +++ b/src/task-list/application/tasks/create-new-content.php @@ -70,7 +70,7 @@ public function get_is_completed(): bool { 'after' => '30 days ago', ], ], - ] + ], ); return ! empty( $recent_posts ); @@ -94,7 +94,7 @@ public function get_call_to_action(): Call_To_Action_Entry { return new Call_To_Action_Entry( \__( 'Create new post', 'wordpress-seo' ), 'add', - $this->get_link() + $this->get_link(), ); } @@ -107,7 +107,7 @@ public function get_copy_set(): Copy_Set { return new Copy_Set( \__( 'Create new content', 'wordpress-seo' ), \__( 'Long gaps without new content slow down your traffic growth. Publishing regularly gives search engines and visitors a reason to return.', 'wordpress-seo' ), - \__( 'Plan a topic, write your post, and use the SEO and Readability Analyses to refine it before publishing.', 'wordpress-seo' ) + \__( 'Plan a topic, write your post, and use the SEO and Readability Analyses to refine it before publishing.', 'wordpress-seo' ), ); } } diff --git a/src/task-list/application/tasks/delete-hello-world.php b/src/task-list/application/tasks/delete-hello-world.php index 01fe6c899c3..9ec587b5e50 100644 --- a/src/task-list/application/tasks/delete-hello-world.php +++ b/src/task-list/application/tasks/delete-hello-world.php @@ -53,7 +53,7 @@ public function get_is_completed(): bool { 'post_id' => 1, 'number' => 1, 'order' => 'ASC', - ] + ], ); if ( empty( $comments ) || \is_a( $comments[0], WP_Comment::class ) === false || $comments[0]->comment_author_email !== 'wapuu@wordpress.example' ) { @@ -101,7 +101,7 @@ public function get_call_to_action(): Call_To_Action_Entry { return new Call_To_Action_Entry( \__( 'Delete for me', 'wordpress-seo' ), 'delete', - $this->get_link() + $this->get_link(), ); } @@ -114,7 +114,7 @@ public function get_copy_set(): Copy_Set { return new Copy_Set( \__( 'Remove the “Hello World” post', 'wordpress-seo' ), \__( 'Leaving placeholder content makes your site look unfinished and untrustworthy. Removing it keeps your site clean and professional for visitors and search engines.', 'wordpress-seo' ), - null + null, ); } } diff --git a/src/task-list/application/tasks/enable-llms-txt.php b/src/task-list/application/tasks/enable-llms-txt.php index 85a31d9b5c3..9d7dbd42a55 100644 --- a/src/task-list/application/tasks/enable-llms-txt.php +++ b/src/task-list/application/tasks/enable-llms-txt.php @@ -93,7 +93,7 @@ public function get_call_to_action(): Call_To_Action_Entry { return new Call_To_Action_Entry( \__( 'Enable llms.txt', 'wordpress-seo' ), 'default', - $this->get_link() + $this->get_link(), ); } @@ -105,7 +105,7 @@ public function get_call_to_action(): Call_To_Action_Entry { public function get_copy_set(): Copy_Set { return new Copy_Set( \__( 'Create an llms.txt file', 'wordpress-seo' ), - \__( 'Without llms.txt, AI crawlers may not know how to treat your content. Publishing it helps communicate your preferences in a clearer way to AI tools.', 'wordpress-seo' ) + \__( 'Without llms.txt, AI crawlers may not know how to treat your content. Publishing it helps communicate your preferences in a clearer way to AI tools.', 'wordpress-seo' ), ); } diff --git a/src/task-list/application/tasks/set-search-appearance-templates.php b/src/task-list/application/tasks/set-search-appearance-templates.php index cee97ea166b..4b77f74830f 100644 --- a/src/task-list/application/tasks/set-search-appearance-templates.php +++ b/src/task-list/application/tasks/set-search-appearance-templates.php @@ -100,7 +100,7 @@ public function get_link(): ?string { $post_type = \get_post_type_object( $this->get_post_type() ); $link = \sprintf( 'admin.php?page=wpseo_page_settings#/post-type/%s', - $this->route_helper->get_route( $post_type->name, $post_type->rewrite, $post_type->rest_base ) + $this->route_helper->get_route( $post_type->name, $post_type->rewrite, $post_type->rest_base ), ); return \self_admin_url( $link ); @@ -115,7 +115,7 @@ public function get_call_to_action(): Call_To_Action_Entry { return new Call_To_Action_Entry( \__( 'Set search templates', 'wordpress-seo' ), 'link', - $this->get_link() + $this->get_link(), ); } @@ -132,7 +132,7 @@ public function get_copy_set(): Copy_Set { \sprintf( \__( 'Set search appearance templates for your content type: %1$s', 'wordpress-seo' ), $post_type->label ), /* translators: %1$s expands to the post type name this task is about */ \sprintf( \__( 'Generic titles and descriptions make your results unclear in search. Templates ensure every %1$s has a clear, click-worthy snippet automatically.', 'wordpress-seo' ), $post_type->name ), - \__( 'Go to Search appearance, choose your post type, and set default title and meta description patterns.', 'wordpress-seo' ) + \__( 'Go to Search appearance, choose your post type, and set default title and meta description patterns.', 'wordpress-seo' ), ); } } diff --git a/src/task-list/infrastructure/tasks-collectors/tasks-collector.php b/src/task-list/infrastructure/tasks-collectors/tasks-collector.php index b6802e1fecf..0781b80fe15 100644 --- a/src/task-list/infrastructure/tasks-collectors/tasks-collector.php +++ b/src/task-list/infrastructure/tasks-collectors/tasks-collector.php @@ -136,9 +136,9 @@ public function get_tasks_data(): array { $task->get_call_to_action()->get_label(), $task->get_call_to_action()->get_type(), $this->tracking_link_adapter->create_tracking_link_for_tasks( - $task->get_call_to_action()->get_href() - ) - ) + $task->get_call_to_action()->get_href(), + ), + ), ); $tasks_data[ $task->get_id() ] = $task->to_array(); diff --git a/src/task-list/user-interface/tasks/complete-task-route.php b/src/task-list/user-interface/tasks/complete-task-route.php index 6e974b3bde7..5efd5506a51 100644 --- a/src/task-list/user-interface/tasks/complete-task-route.php +++ b/src/task-list/user-interface/tasks/complete-task-route.php @@ -111,7 +111,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -142,7 +142,7 @@ public function complete_task( WP_REST_Request $request ): WP_REST_Response { 'success' => false, 'error' => $exception->getMessage(), ], - $exception->getCode() + $exception->getCode(), ); } @@ -152,7 +152,7 @@ public function complete_task( WP_REST_Request $request ): WP_REST_Response { [ 'success' => true, ], - 200 + 200, ); } diff --git a/src/task-list/user-interface/tasks/get-tasks-route.php b/src/task-list/user-interface/tasks/get-tasks-route.php index 1d6a7632286..1f61a6541e3 100644 --- a/src/task-list/user-interface/tasks/get-tasks-route.php +++ b/src/task-list/user-interface/tasks/get-tasks-route.php @@ -113,7 +113,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -133,7 +133,7 @@ public function get_tasks(): WP_REST_Response { 'success' => false, 'error' => $exception->getMessage(), ], - $exception->getCode() + $exception->getCode(), ); } @@ -142,7 +142,7 @@ public function get_tasks(): WP_REST_Response { 'success' => true, 'tasks' => $tasks_data, ], - 200 + 200, ); } diff --git a/src/tracking/infrastructure/tracking-link-adapter.php b/src/tracking/infrastructure/tracking-link-adapter.php index 61b96fefab4..a2ed73befa6 100644 --- a/src/tracking/infrastructure/tracking-link-adapter.php +++ b/src/tracking/infrastructure/tracking-link-adapter.php @@ -25,7 +25,7 @@ public function create_tracking_link_for_tasks( ?string $url ): ?string { 'wpseo_tracked_action' => 'task_first_actioned_on', 'wpseo_tracking_nonce' => \wp_create_nonce( 'wpseo_tracking_nonce' ), ], - $url + $url, ); } } diff --git a/src/tracking/user-interface/action-tracking-route.php b/src/tracking/user-interface/action-tracking-route.php index 5145b257313..82edd93ed6b 100644 --- a/src/tracking/user-interface/action-tracking-route.php +++ b/src/tracking/user-interface/action-tracking-route.php @@ -96,7 +96,7 @@ public function register_routes() { ], ], ], - ] + ], ); } @@ -124,7 +124,7 @@ public function track_action( WP_REST_Request $request ): WP_REST_Response { 'success' => false, 'error' => $exception->getMessage(), ], - $exception->getCode() + $exception->getCode(), ); } @@ -133,7 +133,7 @@ public function track_action( WP_REST_Request $request ): WP_REST_Response { 'success' => true, 'action' => $action_to_track, ], - 200 + 200, ); } diff --git a/src/user-meta/application/custom-meta-collector.php b/src/user-meta/application/custom-meta-collector.php index e09f620602b..d3856a3997d 100644 --- a/src/user-meta/application/custom-meta-collector.php +++ b/src/user-meta/application/custom-meta-collector.php @@ -48,7 +48,7 @@ public function get_sorted_custom_meta(): array { $custom_meta, static function ( Custom_Meta_Interface $a, Custom_Meta_Interface $b ) { return ( $a->get_render_priority() <=> $b->get_render_priority() ); - } + }, ); return $custom_meta; diff --git a/src/user-meta/infrastructure/cleanup-repository.php b/src/user-meta/infrastructure/cleanup-repository.php index 22bdc90255f..fe6a1833377 100644 --- a/src/user-meta/infrastructure/cleanup-repository.php +++ b/src/user-meta/infrastructure/cleanup-repository.php @@ -25,7 +25,7 @@ public function delete_empty_usermeta_query( $meta_keys, $limit ) { AND meta_value = "" ORDER BY user_id LIMIT %d', - \array_merge( [ $wpdb->usermeta ], $meta_keys, [ $limit ] ) + \array_merge( [ $wpdb->usermeta ], $meta_keys, [ $limit ] ), ); // phpcs:enable diff --git a/src/user-meta/user-interface/cleanup-integration.php b/src/user-meta/user-interface/cleanup-integration.php index a3ecbcf7864..3cde4802175 100644 --- a/src/user-meta/user-interface/cleanup-integration.php +++ b/src/user-meta/user-interface/cleanup-integration.php @@ -52,7 +52,7 @@ public function add_user_meta_cleanup_tasks( $tasks ) { 'clean_selected_empty_usermeta' => function ( $limit ) { return $this->cleanup_service->cleanup_selected_empty_usermeta( $limit ); }, - ] + ], ); } } diff --git a/src/values/oauth/oauth-token.php b/src/values/oauth/oauth-token.php index 3a9dd75b060..8429dd33e80 100644 --- a/src/values/oauth/oauth-token.php +++ b/src/values/oauth/oauth-token.php @@ -108,7 +108,7 @@ public static function from_response( AccessTokenInterface $response ) { $response->getRefreshToken(), $response->getExpires(), $response->hasExpired(), - \time() + \time(), ); } diff --git a/src/wrappers/wp-remote-handler.php b/src/wrappers/wp-remote-handler.php index 0790a7f62ac..93e427f70fe 100644 --- a/src/wrappers/wp-remote-handler.php +++ b/src/wrappers/wp-remote-handler.php @@ -57,7 +57,7 @@ public function __invoke( RequestInterface $request, array $options ) { $raw_response['headers']->getAll(), $raw_response['body'], $args['httpVersion'], - $raw_response['response']['message'] + $raw_response['response']['message'], ); return new FulfilledPromise( $response ); diff --git a/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Constructor_Test.php b/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Constructor_Test.php index 3b7f57f1ac4..5b53bc999db 100644 --- a/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Constructor_Test.php +++ b/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Constructor_Test.php @@ -24,11 +24,11 @@ final class Constructor_Test extends Abstract_Code_Verifier_Handler_Test { public function test_constructor() { $this->assertInstanceOf( Date_Helper::class, - $this->getPropertyValue( $this->instance, 'date_helper' ) + $this->getPropertyValue( $this->instance, 'date_helper' ), ); $this->assertInstanceOf( Code_Verifier_User_Meta_Repository::class, - $this->getPropertyValue( $this->instance, 'code_verifier_repository' ) + $this->getPropertyValue( $this->instance, 'code_verifier_repository' ), ); } } diff --git a/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Generate_Test.php b/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Generate_Test.php index 06f1f21db66..3f30d3bfaba 100644 --- a/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Generate_Test.php +++ b/tests/Unit/AI_Authorization/Application/Code_Verifier_Handler/Generate_Test.php @@ -21,7 +21,7 @@ final class Generate_Test extends Abstract_Code_Verifier_Handler_Test { */ public function test_generate() { $user_email = 'test@example.com'; - $current_time = 1640995200; + $current_time = 1_640_995_200; $generated_code = 'mocked_generated_code_123'; $this->code_generator diff --git a/tests/Unit/AI_Authorization/Application/Token_Manager/Constructor_Test.php b/tests/Unit/AI_Authorization/Application/Token_Manager/Constructor_Test.php index d77a76069c0..3e9eca25b32 100644 --- a/tests/Unit/AI_Authorization/Application/Token_Manager/Constructor_Test.php +++ b/tests/Unit/AI_Authorization/Application/Token_Manager/Constructor_Test.php @@ -30,35 +30,35 @@ final class Constructor_Test extends Abstract_Token_Manager_Test { public function test_constructor() { $this->assertInstanceOf( Access_Token_User_Meta_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'access_token_repository' ) + $this->getPropertyValue( $this->instance, 'access_token_repository' ), ); $this->assertInstanceOf( Code_Verifier_Handler::class, - $this->getPropertyValue( $this->instance, 'code_verifier' ) + $this->getPropertyValue( $this->instance, 'code_verifier' ), ); $this->assertInstanceOf( Consent_Handler::class, - $this->getPropertyValue( $this->instance, 'consent_handler' ) + $this->getPropertyValue( $this->instance, 'consent_handler' ), ); $this->assertInstanceOf( Refresh_Token_User_Meta_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'refresh_token_repository' ) + $this->getPropertyValue( $this->instance, 'refresh_token_repository' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); $this->assertInstanceOf( Request_Handler::class, - $this->getPropertyValue( $this->instance, 'request_handler' ) + $this->getPropertyValue( $this->instance, 'request_handler' ), ); $this->assertInstanceOf( Code_Verifier_User_Meta_Repository::class, - $this->getPropertyValue( $this->instance, 'code_verifier_repository' ) + $this->getPropertyValue( $this->instance, 'code_verifier_repository' ), ); $this->assertInstanceOf( WordPress_URLs::class, - $this->getPropertyValue( $this->instance, 'urls' ) + $this->getPropertyValue( $this->instance, 'urls' ), ); } } diff --git a/tests/Unit/AI_Authorization/Application/Token_Manager/Get_Or_Request_Access_Token_Test.php b/tests/Unit/AI_Authorization/Application/Token_Manager/Get_Or_Request_Access_Token_Test.php index 383a2097a38..7b138d7ccbb 100644 --- a/tests/Unit/AI_Authorization/Application/Token_Manager/Get_Or_Request_Access_Token_Test.php +++ b/tests/Unit/AI_Authorization/Application/Token_Manager/Get_Or_Request_Access_Token_Test.php @@ -66,7 +66,7 @@ public function test_get_or_request_access_token_no_token() { $new_access_jwt = 'new-access-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -146,7 +146,7 @@ public function test_get_or_request_access_token_null_token() { $new_access_jwt = 'new-access-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -227,7 +227,7 @@ public function test_get_or_request_access_token_non_string_token() { $new_access_jwt = 'new-access-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -304,14 +304,14 @@ public function test_get_or_request_access_token_expired_token_refresh_success() $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $new_access_jwt = 'refreshed-access-token'; $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -375,7 +375,7 @@ public function test_get_or_request_access_token_expired_token_refresh_unauthori $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $new_access_jwt = 'new-access-token'; $refresh_jwt = 'refresh-token'; @@ -383,7 +383,7 @@ public function test_get_or_request_access_token_expired_token_refresh_unauthori $code_verifier_refresh = Mockery::mock( Code_Verifier::class ); $code_verifier_request = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -492,13 +492,13 @@ public function test_get_or_request_access_token_expired_token_refresh_forbidden $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -562,7 +562,7 @@ public function test_get_or_request_access_token_token_request_bad_request() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -634,7 +634,7 @@ public function test_get_or_request_access_token_repository_runtime_exception() $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -712,13 +712,13 @@ public function test_get_or_request_access_token_refresh_internal_server_error() $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -775,13 +775,13 @@ public function test_get_or_request_access_token_refresh_not_found() { $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -838,13 +838,13 @@ public function test_get_or_request_access_token_refresh_payment_required() { $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -901,13 +901,13 @@ public function test_get_or_request_access_token_refresh_request_timeout() { $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -964,13 +964,13 @@ public function test_get_or_request_access_token_refresh_service_unavailable() { $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past. + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past. $expired_access_jwt = $this->create_jwt_token( $expired_time ); $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -1027,13 +1027,13 @@ public function test_get_or_request_access_token_refresh_too_many_requests() { $user->ID = 123; $user->user_email = 'test@example.com'; - $expired_time = ( 1640995200 - 3600 ); // 1 hour in the past + $expired_time = ( 1_640_995_200 - 3600 ); // 1 hour in the past $expired_access_jwt = $this->create_jwt_token( $expired_time ); $refresh_jwt = 'refresh-token'; $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $this->user_helper ->expects( 'get_meta' ) @@ -1092,8 +1092,8 @@ private function create_jwt_token( int $exp ): string { [ 'typ' => 'JWT', 'alg' => 'HS256', - ] - ) + ], + ), ); $payload = \base64_encode( \json_encode( [ 'exp' => $exp ] ) ); $signature = \base64_encode( 'fake-signature' ); diff --git a/tests/Unit/AI_Authorization/Application/Token_Manager/Has_Token_Expired_Test.php b/tests/Unit/AI_Authorization/Application/Token_Manager/Has_Token_Expired_Test.php index 97efdd81011..5d4f388f50e 100644 --- a/tests/Unit/AI_Authorization/Application/Token_Manager/Has_Token_Expired_Test.php +++ b/tests/Unit/AI_Authorization/Application/Token_Manager/Has_Token_Expired_Test.php @@ -151,7 +151,7 @@ public function test_has_token_expired_no_exp_field() { [ 'sub' => '1234567890', 'name' => 'John Doe', - ] + ], ); $encoded_payload = \base64_encode( $payload ); @@ -269,7 +269,7 @@ public function test_has_token_expired_realistic_expired_jwt() { 'exp' => $past_timestamp, 'iat' => ( $past_timestamp - 3600 ), 'scope' => 'ai-generation', - ] + ], ); $encoded_payload = \base64_encode( $payload ); @@ -296,7 +296,7 @@ public function test_has_token_expired_realistic_valid_jwt() { 'exp' => $future_timestamp, 'iat' => \time(), 'scope' => 'ai-generation', - ] + ], ); $encoded_payload = \base64_encode( $payload ); diff --git a/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Invalidate_Test.php b/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Invalidate_Test.php index fa02de50b74..de71139fa3b 100644 --- a/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Invalidate_Test.php +++ b/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Invalidate_Test.php @@ -43,8 +43,8 @@ static function ( Request $request ) use ( $user_id, $access_jwt ) { return $request->get_action_path() === '/token/invalidate' && $request->get_body() === [ 'user_id' => $user_id ] && $request->get_headers() === [ 'Authorization' => "Bearer $access_jwt" ]; - } - ) + }, + ), ) ->once(); @@ -86,8 +86,8 @@ static function ( Request $request ) use ( $user_id ) { return $request->get_action_path() === '/token/invalidate' && $request->get_body() === [ 'user_id' => $user_id ] && $request->get_headers() === [ 'Authorization' => 'Bearer ' ]; - } - ) + }, + ), ) ->once(); @@ -130,8 +130,8 @@ static function ( Request $request ) use ( $user_id, $access_jwt ) { return $request->get_action_path() === '/token/invalidate' && $request->get_body() === [ 'user_id' => $user_id ] && $request->get_headers() === [ 'Authorization' => "Bearer $access_jwt" ]; - } - ) + }, + ), ) ->once() ->andThrow( new Unauthorized_Exception( 'Unauthorized', 401 ) ); @@ -175,8 +175,8 @@ static function ( Request $request ) use ( $user_id, $access_jwt ) { return $request->get_action_path() === '/token/invalidate' && $request->get_body() === [ 'user_id' => $user_id ] && $request->get_headers() === [ 'Authorization' => "Bearer $access_jwt" ]; - } - ) + }, + ), ) ->once() ->andThrow( new Forbidden_Exception( 'Forbidden', 403 ) ); diff --git a/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Refresh_Test.php b/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Refresh_Test.php index 97c45dfb8ba..3d91600aae0 100644 --- a/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Refresh_Test.php +++ b/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Refresh_Test.php @@ -40,7 +40,7 @@ public function test_token_refresh_success() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -78,8 +78,8 @@ static function ( Request $request ) use ( $code, $refresh_jwt ) { return $request->get_action_path() === '/token/refresh' && $request->get_body() === [ 'code_challenge' => \hash( 'sha256', $code ) ] && $request->get_headers() === [ 'Authorization' => "Bearer $refresh_jwt" ]; - } - ) + }, + ), ) ->once(); @@ -123,7 +123,7 @@ public function test_token_refresh_bad_request_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -177,7 +177,7 @@ public function test_token_refresh_forbidden_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -231,7 +231,7 @@ public function test_token_refresh_unauthorized_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'expired-refresh-token'; $this->refresh_token_repository @@ -285,7 +285,7 @@ public function test_token_refresh_internal_server_error_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -339,7 +339,7 @@ public function test_token_refresh_not_found_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -393,7 +393,7 @@ public function test_token_refresh_payment_required_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -447,7 +447,7 @@ public function test_token_refresh_request_timeout_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -501,7 +501,7 @@ public function test_token_refresh_service_unavailable_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository @@ -555,7 +555,7 @@ public function test_token_refresh_too_many_requests_exception() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $refresh_jwt = 'valid-refresh-token'; $this->refresh_token_repository diff --git a/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Request_Test.php b/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Request_Test.php index 293da52797d..9c2825589f1 100644 --- a/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Request_Test.php +++ b/tests/Unit/AI_Authorization/Application/Token_Manager/Token_Request_Test.php @@ -30,7 +30,7 @@ public function test_token_request_success() { $code_verifier = Mockery::mock( Code_Verifier::class ); $code = 'test-code-verifier'; - $created_at = 1640995200; + $created_at = 1_640_995_200; $callback_url = 'https://example.com/callback'; $refresh_callback_url = 'https://example.com/refresh-callback'; diff --git a/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Constructor_Test.php b/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Constructor_Test.php index 876a6a8cfd5..0e64a69896a 100644 --- a/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Constructor_Test.php +++ b/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Constructor_Test.php @@ -22,7 +22,7 @@ final class Constructor_Test extends Abstract_Access_Token_User_Meta_Repository_ public function test_constructor() { $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } } diff --git a/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Store_Token_Test.php b/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Store_Token_Test.php index 7e2b4bc819f..deca0b69870 100644 --- a/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Store_Token_Test.php +++ b/tests/Unit/AI_Authorization/Infrastructure/Access_Token_User_Meta_Repository/Store_Token_Test.php @@ -26,7 +26,7 @@ public function test_store_token() { ->with( $user_id, '_yoast_wpseo_ai_generator_access_jwt', - $token + $token, ); $this->instance->store_token( $user_id, $token ); diff --git a/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Constructor_Test.php b/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Constructor_Test.php index f022fa72370..6dcc4c0bd31 100644 --- a/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Constructor_Test.php +++ b/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Constructor_Test.php @@ -23,11 +23,11 @@ final class Constructor_Test extends Abstract_Code_Verifier_User_Meta_Repository public function test_constructor() { $this->assertInstanceOf( Date_Helper::class, - $this->getPropertyValue( $this->instance, 'date_helper' ) + $this->getPropertyValue( $this->instance, 'date_helper' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } } diff --git a/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Store_Code_Verifier_Test.php b/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Store_Code_Verifier_Test.php index fed94186779..5ccc94f95e0 100644 --- a/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Store_Code_Verifier_Test.php +++ b/tests/Unit/AI_Authorization/Infrastructure/Code_Verifier_User_Meta_Repository/Store_Code_Verifier_Test.php @@ -36,7 +36,7 @@ public function test_store_code_verifier() { [ 'code' => $code, 'created_at' => $created_at, - ] + ], ); $this->instance->store_code_verifier( $user_id, $code, $created_at ); diff --git a/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Constructor_Test.php b/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Constructor_Test.php index 6e1eed51cb0..755dc10e802 100644 --- a/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Constructor_Test.php +++ b/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Constructor_Test.php @@ -22,7 +22,7 @@ final class Constructor_Test extends Abstract_Refresh_Token_User_Meta_Repository public function test_constructor() { $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } } diff --git a/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Store_Token_Test.php b/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Store_Token_Test.php index 5a4e329b972..ecb9e948918 100644 --- a/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Store_Token_Test.php +++ b/tests/Unit/AI_Authorization/Infrastructure/Refresh_Token_User_Meta_Repository/Store_Token_Test.php @@ -26,7 +26,7 @@ public function test_store_token() { ->with( $user_id, '_yoast_wpseo_ai_generator_refresh_jwt', - $token + $token, ); $this->instance->store_token( $user_id, $token ); diff --git a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Abstract_Callback_Route_Test.php b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Abstract_Callback_Route_Test.php index 5bce990fe02..6c6bd8ce352 100644 --- a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Abstract_Callback_Route_Test.php +++ b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Abstract_Callback_Route_Test.php @@ -61,7 +61,7 @@ protected function setUp(): void { $this->instance = new Callback_Route( $this->access_token_repository, $this->refresh_token_repository, - $this->code_verifier_repository + $this->code_verifier_repository, ); } } diff --git a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Callback_Test.php b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Callback_Test.php index 791a32ac541..5eda0df5b1e 100644 --- a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Callback_Test.php +++ b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Callback_Test.php @@ -88,7 +88,7 @@ public function test_callback() { [ 'message' => 'Tokens successfully stored.', 'code_verifier' => 'test', - ] + ], ); $result = $this->instance->callback( $wp_rest_request ); diff --git a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Constructor_Test.php b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Constructor_Test.php index 0fcea21a7a6..d65e62ebdb1 100644 --- a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Constructor_Test.php +++ b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Constructor_Test.php @@ -25,17 +25,17 @@ final class Constructor_Test extends Abstract_Callback_Route_Test { public function test_constructor() { $this->assertInstanceOf( Access_Token_User_Meta_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'access_token_repository' ) + $this->getPropertyValue( $this->instance, 'access_token_repository' ), ); $this->assertInstanceOf( Refresh_Token_User_Meta_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'refresh_token_repository' ) + $this->getPropertyValue( $this->instance, 'refresh_token_repository' ), ); $this->assertInstanceOf( Code_Verifier_User_Meta_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'code_verifier_repository' ) + $this->getPropertyValue( $this->instance, 'code_verifier_repository' ), ); } } diff --git a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Register_Routes_Test.php b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Register_Routes_Test.php index 64f2b190c62..3649689e467 100644 --- a/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Register_Routes_Test.php +++ b/tests/Unit/AI_Authorization/User_Interface/Callback_Route/Register_Routes_Test.php @@ -52,7 +52,7 @@ public function test_register_routes() { ], 'callback' => [ $this->instance, 'callback' ], 'permission_callback' => '__return_true', - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Abstract_Refresh_Callback_Route_Test.php b/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Abstract_Refresh_Callback_Route_Test.php index 9121dfc77c8..1adfbda5d91 100644 --- a/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Abstract_Refresh_Callback_Route_Test.php +++ b/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Abstract_Refresh_Callback_Route_Test.php @@ -61,7 +61,7 @@ protected function setUp(): void { $this->instance = new Refresh_Callback_Route( $this->access_token_repository, $this->refresh_token_repository, - $this->code_verifier_repository + $this->code_verifier_repository, ); } } diff --git a/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Register_Routes_Test.php b/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Register_Routes_Test.php index dba99fc2b49..5c0958a8f80 100644 --- a/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Register_Routes_Test.php +++ b/tests/Unit/AI_Authorization/User_Interface/Refresh_Callback_Route/Register_Routes_Test.php @@ -52,7 +52,7 @@ public function test_register_routes() { ], 'callback' => [ $this->instance, 'callback' ], 'permission_callback' => '__return_true', - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/AI_Consent/Application/Consent_Handler/Constructor_Test.php b/tests/Unit/AI_Consent/Application/Consent_Handler/Constructor_Test.php index c1a8cd70e02..808b40a700c 100644 --- a/tests/Unit/AI_Consent/Application/Consent_Handler/Constructor_Test.php +++ b/tests/Unit/AI_Consent/Application/Consent_Handler/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Consent_Handler_Test { public function test_constructor() { $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } } diff --git a/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Constructor_Test.php b/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Constructor_Test.php index 43ef8b77e62..be660202f64 100644 --- a/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Constructor_Test.php +++ b/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Constructor_Test.php @@ -25,15 +25,15 @@ final class Constructor_Test extends Abstract_AI_Consent_Integration_Test { public function test_constructor() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $this->instance, 'asset_manager' ) + $this->getPropertyValue( $this->instance, 'asset_manager' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); $this->assertInstanceOf( Short_Link_Helper::class, - $this->getPropertyValue( $this->instance, 'short_link_helper' ) + $this->getPropertyValue( $this->instance, 'short_link_helper' ), ); } } diff --git a/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Enqueue_Assets_Test.php b/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Enqueue_Assets_Test.php index 3dde19557f8..0ebfc12b106 100644 --- a/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Enqueue_Assets_Test.php +++ b/tests/Unit/AI_Consent/User_Interface/AI_Consent_Integration/Enqueue_Assets_Test.php @@ -44,7 +44,7 @@ public function test_enqueue_assets() { 'hasConsent' => true, 'pluginUrl' => 'https://example.com/wp-content/plugins/wordpress-seo', 'linkParams' => [], - ] + ], ); $this->short_link_helper->expects( 'get_query_params' )->andReturn( [] ); diff --git a/tests/Unit/AI_Consent/User_Interface/Consent_Route/Constructor_Test.php b/tests/Unit/AI_Consent/User_Interface/Consent_Route/Constructor_Test.php index 2e522c0c150..3485dfeefed 100644 --- a/tests/Unit/AI_Consent/User_Interface/Consent_Route/Constructor_Test.php +++ b/tests/Unit/AI_Consent/User_Interface/Consent_Route/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Consent_Route_Test { public function test_constructor() { $this->assertInstanceOf( Consent_Handler_Interface::class, - $this->getPropertyValue( $this->instance, 'consent_handler' ) + $this->getPropertyValue( $this->instance, 'consent_handler' ), ); } } diff --git a/tests/Unit/AI_Consent/User_Interface/Consent_Route/Register_Routes_Test.php b/tests/Unit/AI_Consent/User_Interface/Consent_Route/Register_Routes_Test.php index d16c6126861..a0eddc24f7d 100644 --- a/tests/Unit/AI_Consent/User_Interface/Consent_Route/Register_Routes_Test.php +++ b/tests/Unit/AI_Consent/User_Interface/Consent_Route/Register_Routes_Test.php @@ -37,7 +37,7 @@ public function test_register_routes() { ], 'callback' => [ $this->instance, 'consent' ], 'permission_callback' => [ $this->instance, 'check_permissions' ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/AI_Free_Sparks/Application/Free_Sparks_Handler/Constructor_Test.php b/tests/Unit/AI_Free_Sparks/Application/Free_Sparks_Handler/Constructor_Test.php index 20ebebd8ea2..72877971ec3 100644 --- a/tests/Unit/AI_Free_Sparks/Application/Free_Sparks_Handler/Constructor_Test.php +++ b/tests/Unit/AI_Free_Sparks/Application/Free_Sparks_Handler/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Free_Sparks_Handler_Test { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Constructor_Test.php b/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Constructor_Test.php index 20a7d8870ad..aa89d61d076 100644 --- a/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Constructor_Test.php +++ b/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Free_Sparks_Route_Test { public function test_constructor() { $this->assertInstanceOf( Free_Sparks_Handler_Interface::class, - $this->getPropertyValue( $this->instance, 'free_sparks_handler' ) + $this->getPropertyValue( $this->instance, 'free_sparks_handler' ), ); } } diff --git a/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Register_Routes_Test.php b/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Register_Routes_Test.php index 3968b7fe9d8..8486fae939b 100644 --- a/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Register_Routes_Test.php +++ b/tests/Unit/AI_Free_Sparks/User_Interface/Free_Sparks_Route/Register_Routes_Test.php @@ -30,7 +30,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'start' ], 'permission_callback' => [ $this->instance, 'can_edit_posts' ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/AI_Generator/Application/Suggestions_Provider/Abstract_Suggestions_Provider_Test.php b/tests/Unit/AI_Generator/Application/Suggestions_Provider/Abstract_Suggestions_Provider_Test.php index 83f2fcecea7..9358c98841e 100644 --- a/tests/Unit/AI_Generator/Application/Suggestions_Provider/Abstract_Suggestions_Provider_Test.php +++ b/tests/Unit/AI_Generator/Application/Suggestions_Provider/Abstract_Suggestions_Provider_Test.php @@ -71,7 +71,7 @@ protected function setUp(): void { $this->consent_handler, $this->request_handler, $this->token_manager, - $this->user_helper + $this->user_helper, ); } } diff --git a/tests/Unit/AI_Generator/Application/Suggestions_Provider/Constructor_Test.php b/tests/Unit/AI_Generator/Application/Suggestions_Provider/Constructor_Test.php index 1d5f6985974..bbdc9cd3908 100644 --- a/tests/Unit/AI_Generator/Application/Suggestions_Provider/Constructor_Test.php +++ b/tests/Unit/AI_Generator/Application/Suggestions_Provider/Constructor_Test.php @@ -26,22 +26,22 @@ final class Constructor_Test extends Abstract_Suggestions_Provider_Test { public function test_constructor() { $this->assertInstanceOf( Consent_Handler::class, - $this->getPropertyValue( $this->instance, 'consent_handler' ) + $this->getPropertyValue( $this->instance, 'consent_handler' ), ); $this->assertInstanceOf( Request_Handler::class, - $this->getPropertyValue( $this->instance, 'request_handler' ) + $this->getPropertyValue( $this->instance, 'request_handler' ), ); $this->assertInstanceOf( Token_Manager::class, - $this->getPropertyValue( $this->instance, 'token_manager' ) + $this->getPropertyValue( $this->instance, 'token_manager' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } } diff --git a/tests/Unit/AI_Generator/Application/Suggestions_Provider/Get_Suggestions_Test.php b/tests/Unit/AI_Generator/Application/Suggestions_Provider/Get_Suggestions_Test.php index 6fb23231246..da11c25d51e 100644 --- a/tests/Unit/AI_Generator/Application/Suggestions_Provider/Get_Suggestions_Test.php +++ b/tests/Unit/AI_Generator/Application/Suggestions_Provider/Get_Suggestions_Test.php @@ -54,7 +54,7 @@ public function test_get_suggestions() { '', '', '', - false + false, ); $this->assertArrayHasKey( 0, $suggestions_array ); @@ -107,7 +107,7 @@ public function test_get_suggestions_with_unauthorized_exception( $retry_on_unau '', '', '', - $retry_on_unauthorized + $retry_on_unauthorized, ); } @@ -161,7 +161,7 @@ public function test_get_suggestions_with_forbidden_exception() { '', '', '', - false + false, ); } } diff --git a/tests/Unit/AI_Generator/Infrastructure/WordPress_URLs/Get_License_Url_Test.php b/tests/Unit/AI_Generator/Infrastructure/WordPress_URLs/Get_License_Url_Test.php index f1fd885f3b4..d9ceb82915e 100644 --- a/tests/Unit/AI_Generator/Infrastructure/WordPress_URLs/Get_License_Url_Test.php +++ b/tests/Unit/AI_Generator/Infrastructure/WordPress_URLs/Get_License_Url_Test.php @@ -33,7 +33,7 @@ public function test_get_license_url() { $container = $this->create_container_with( [ Url_Helper::class => $url_helper, - ] + ], ); Functions\expect( 'YoastSEO' ) diff --git a/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Abstract_AI_Generator_Integration_Test.php b/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Abstract_AI_Generator_Integration_Test.php index 5c22d6e701b..f100a4c9e90 100644 --- a/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Abstract_AI_Generator_Integration_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Abstract_AI_Generator_Integration_Test.php @@ -101,7 +101,7 @@ public function setUp(): void { $this->current_page_helper, $this->options_helper, $this->user_helper, - $this->introductions_seen_repository + $this->introductions_seen_repository, ); } } diff --git a/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Constructor_Test.php b/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Constructor_Test.php index e63a0cc1700..71a92861221 100644 --- a/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Constructor_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Constructor_Test.php @@ -29,31 +29,31 @@ final class Constructor_Test extends Abstract_AI_Generator_Integration_Test { public function test_constructor() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $this->instance, 'asset_manager' ) + $this->getPropertyValue( $this->instance, 'asset_manager' ), ); $this->assertInstanceOf( WPSEO_Addon_Manager::class, - $this->getPropertyValue( $this->instance, 'addon_manager' ) + $this->getPropertyValue( $this->instance, 'addon_manager' ), ); $this->assertInstanceOf( API_Client::class, - $this->getPropertyValue( $this->instance, 'api_client' ) + $this->getPropertyValue( $this->instance, 'api_client' ), ); $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); $this->assertInstanceOf( Introductions_Seen_Repository::class, - $this->getPropertyValue( $this->instance, 'introductions_seen_repository' ) + $this->getPropertyValue( $this->instance, 'introductions_seen_repository' ), ); } } diff --git a/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Enqueue_Assets_Test.php b/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Enqueue_Assets_Test.php index af75e2c3d31..15652d2d4e4 100644 --- a/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Enqueue_Assets_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/AI_Generator_Integration/Enqueue_Assets_Test.php @@ -71,7 +71,7 @@ public function test_enqueue_assets() { 'hasSeenIntroduction' => true, 'requestTimeout' => 0, 'isFreeSparks' => true, - ] + ], ); $this->asset_manager->expects( 'enqueue_style' )->once()->with( 'ai-generator' ); diff --git a/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Constructor_Test.php b/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Constructor_Test.php index 9ace2a136a8..05dc9792656 100644 --- a/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Constructor_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Bust_Subscription_Cache_Route_Test public function test_constructor() { $this->assertInstanceOf( WPSEO_Addon_Manager::class, - $this->getPropertyValue( $this->instance, 'addon_manager' ) + $this->getPropertyValue( $this->instance, 'addon_manager' ), ); } } diff --git a/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Register_Routes_Test.php b/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Register_Routes_Test.php index 5f5b090b106..860cbc94491 100644 --- a/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Register_Routes_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Bust_Subscription_Cache_Route/Register_Routes_Test.php @@ -31,7 +31,7 @@ public function test_register_routes() { 'args' => [], 'callback' => [ $this->instance, 'bust_subscription_cache' ], 'permission_callback' => [ $this->instance, 'check_permissions' ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Constructor_Test.php b/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Constructor_Test.php index ddc12bfebef..7e3e30e2da8 100644 --- a/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Constructor_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Get_Suggestions_Route_Test { public function test_constructor() { $this->assertInstanceOf( Suggestions_Provider::class, - $this->getPropertyValue( $this->instance, 'suggestions_provider' ) + $this->getPropertyValue( $this->instance, 'suggestions_provider' ), ); } } diff --git a/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Get_Suggestions_Test.php b/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Get_Suggestions_Test.php index 3b947dc4a82..338cf085ca0 100644 --- a/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Get_Suggestions_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Get_Suggestions_Test.php @@ -61,7 +61,7 @@ public function test_get_suggestions() { $request['focus_keyphrase'], $request['language'], $request['platform'], - $request['editor'] + $request['editor'], ); $wp_rest_response @@ -115,7 +115,7 @@ public function test_get_suggestions_with_missing_license() { $request['focus_keyphrase'], $request['language'], $request['platform'], - $request['editor'] + $request['editor'], ) ->andThrow( $payment_required_exception ); @@ -140,7 +140,7 @@ public function test_get_suggestions_with_missing_license() { 'errorIdentifier' => 'test', 'missingLicenses' => 'test', ], - 0 + 0, ); $result = $this->instance->get_suggestions( $wp_rest_request ); @@ -189,7 +189,7 @@ public function test_get_suggestions_with_runtime_exception() { $request['focus_keyphrase'], $request['language'], $request['platform'], - $request['editor'] + $request['editor'], ) ->andThrow( $runtime_exception ); diff --git a/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Register_Routes_Test.php b/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Register_Routes_Test.php index d8425d153d2..70ba1cf85b1 100644 --- a/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Register_Routes_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Get_Suggestions_Route/Register_Routes_Test.php @@ -82,7 +82,7 @@ public function test_register_routes() { ], 'callback' => [ $this->instance, 'get_suggestions' ], 'permission_callback' => [ $this->instance, 'check_permissions' ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Abstract_Get_Usage_Route_Test.php b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Abstract_Get_Usage_Route_Test.php index 53a6db126cc..82e905a5b7b 100644 --- a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Abstract_Get_Usage_Route_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Abstract_Get_Usage_Route_Test.php @@ -61,7 +61,7 @@ protected function setUp(): void { $this->instance = new Get_Usage_Route( $this->token_manager, $this->request_handler, - $this->addon_manager + $this->addon_manager, ); } } diff --git a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Constructor_Test.php b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Constructor_Test.php index 8db9ba7fd31..ce7a8abe3d2 100644 --- a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Constructor_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Constructor_Test.php @@ -25,17 +25,17 @@ final class Constructor_Test extends Abstract_Get_Usage_Route_Test { public function test_constructor() { $this->assertInstanceOf( Token_Manager::class, - $this->getPropertyValue( $this->instance, 'token_manager' ) + $this->getPropertyValue( $this->instance, 'token_manager' ), ); $this->assertInstanceOf( Request_Handler::class, - $this->getPropertyValue( $this->instance, 'request_handler' ) + $this->getPropertyValue( $this->instance, 'request_handler' ), ); $this->assertInstanceOf( WPSEO_Addon_Manager::class, - $this->getPropertyValue( $this->instance, 'addon_manager' ) + $this->getPropertyValue( $this->instance, 'addon_manager' ), ); } } diff --git a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Get_Usage_Test.php b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Get_Usage_Test.php index cd0da211818..26656ec3900 100644 --- a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Get_Usage_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Get_Usage_Test.php @@ -122,7 +122,7 @@ public function test_get_usage_with_bad_http_request() { 'errorIdentifier' => 'test', 'errorCode' => 0, ], - 0 + 0, ); $result = $this->instance->get_usage( $wp_rest_request ); @@ -181,7 +181,7 @@ public function test_get_usage_with_too_many_requests_exception() { 'errorCode' => 0, 'missingLicenses' => 'test', ], - 0 + 0, ); $result = $this->instance->get_usage( $wp_rest_request ); diff --git a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Register_Routes_Test.php b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Register_Routes_Test.php index 097cbf2a1b4..2ce74bc3d90 100644 --- a/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Register_Routes_Test.php +++ b/tests/Unit/AI_Generator/User_Interface/Get_Usage_Route/Register_Routes_Test.php @@ -36,7 +36,7 @@ public function test_register_routes() { ], 'callback' => [ $this->instance, 'get_usage' ], 'permission_callback' => [ $this->instance, 'check_permissions' ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Abstract_Request_Handler_Test.php b/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Abstract_Request_Handler_Test.php index 58dca0d1fd2..41b05dc791d 100644 --- a/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Abstract_Request_Handler_Test.php +++ b/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Abstract_Request_Handler_Test.php @@ -51,7 +51,7 @@ protected function setUp(): void { $this->instance = new Request_Handler( $this->api_client, - $this->response_parser + $this->response_parser, ); } } diff --git a/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Constructor_Test.php b/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Constructor_Test.php index 0410fe682bd..d1da25d1982 100644 --- a/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Constructor_Test.php +++ b/tests/Unit/AI_HTTP_Request/Application/Request_Handler/Constructor_Test.php @@ -24,12 +24,12 @@ final class Constructor_Test extends Abstract_Request_Handler_Test { public function test_constructor() { $this->assertInstanceOf( API_Client::class, - $this->getPropertyValue( $this->instance, 'api_client' ) + $this->getPropertyValue( $this->instance, 'api_client' ), ); $this->assertInstanceOf( Response_Parser::class, - $this->getPropertyValue( $this->instance, 'response_parser' ) + $this->getPropertyValue( $this->instance, 'response_parser' ), ); } } diff --git a/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Get_Test.php b/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Get_Test.php index eaa62260e53..2aa7ee54792 100644 --- a/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Get_Test.php +++ b/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Get_Test.php @@ -51,7 +51,7 @@ public function test_perform_request_get() { [ 'body' => '{"status":"ok"}', 'response' => [ 'code' => 200 ], - ] + ], ); $result = $this->instance->perform_request( $action_path, $body, $headers, $is_post ); @@ -61,7 +61,7 @@ public function test_perform_request_get() { 'body' => '{"status":"ok"}', 'response' => [ 'code' => 200 ], ], - $result + $result, ); } } diff --git a/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Post_Test.php b/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Post_Test.php index 32fa98050c4..6587a2063a8 100644 --- a/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Post_Test.php +++ b/tests/Unit/AI_HTTP_Request/Infrastructure/API_Client/Perform_Request_Post_Test.php @@ -52,7 +52,7 @@ public function test_perform_request_post() { [ 'body' => '{"success":true}', 'response' => [ 'code' => 200 ], - ] + ], ); $result = $this->instance->perform_request( $action_path, $body, $headers, $is_post ); @@ -62,7 +62,7 @@ public function test_perform_request_post() { 'body' => '{"success":true}', 'response' => [ 'code' => 200 ], ], - $result + $result, ); } } diff --git a/tests/Unit/Actions/Alert_Dismissal_Action_Test.php b/tests/Unit/Actions/Alert_Dismissal_Action_Test.php index a217a09d8b0..5d0e29c4d72 100644 --- a/tests/Unit/Actions/Alert_Dismissal_Action_Test.php +++ b/tests/Unit/Actions/Alert_Dismissal_Action_Test.php @@ -54,7 +54,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user' ) + $this->getPropertyValue( $this->instance, 'user' ), ); } @@ -93,7 +93,7 @@ public function test_dismiss_alert() { [ 'other alert' => true, 'test' => true, - ] + ], ); $this->assertTrue( $this->instance->dismiss( 'test' ) ); @@ -289,7 +289,7 @@ public function test_reset_alert() { 'some alert' => true, 'test' => true, 'other alert' => true, - ] + ], ); $this->user @@ -304,14 +304,14 @@ public function test_reset_alert() { [ 'some alert' => true, 'other alert' => true, - ] + ], ) ->once() ->andReturn( [ 'some alert' => true, 'other alert' => true, - ] + ], ); $this->assertTrue( $this->instance->reset( 'test' ) ); @@ -603,7 +603,7 @@ public function test_reset_alert_update_failure() { 'some alert' => true, 'test' => true, 'other alert' => true, - ] + ], ); $this->user @@ -618,7 +618,7 @@ public function test_reset_alert_update_failure() { [ 'some alert' => true, 'other alert' => true, - ] + ], ) ->once() ->andReturn( false ); diff --git a/tests/Unit/Actions/Configuration/First_Time_Configuration_Action_Test.php b/tests/Unit/Actions/Configuration/First_Time_Configuration_Action_Test.php index 4b64a53f373..4cf1122e92b 100644 --- a/tests/Unit/Actions/Configuration/First_Time_Configuration_Action_Test.php +++ b/tests/Unit/Actions/Configuration/First_Time_Configuration_Action_Test.php @@ -64,11 +64,11 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Social_Profiles_Helper::class, - $this->getPropertyValue( $this->instance, 'social_profiles_helper' ) + $this->getPropertyValue( $this->instance, 'social_profiles_helper' ), ); } @@ -107,7 +107,7 @@ public function test_set_site_representation( $params, $times, $yoast_options_re $this->assertEquals( $expected, - $this->instance->set_site_representation( $params ) + $this->instance->set_site_representation( $params ), ); } @@ -211,7 +211,7 @@ public function test_set_social_profiles( $set_profiles_results, $get_profiles_r $this->assertEquals( $expected, - $this->instance->set_social_profiles( $params ) + $this->instance->set_social_profiles( $params ), ); } @@ -298,7 +298,7 @@ public function test_set_enable_tracking( $params, $old_value, $times, $option_r $this->assertEquals( $expected, - $this->instance->set_enable_tracking( $params ) + $this->instance->set_enable_tracking( $params ), ); } @@ -404,7 +404,7 @@ public function test_check_capability( $user_id, $can_edit, $expected ) { $this->assertEquals( $expected, - $this->instance->check_capability( $user_id ) + $this->instance->check_capability( $user_id ), ); } @@ -464,7 +464,7 @@ public function test_save_configuration_state( $params, $times, $yoast_options_r $this->assertEquals( $expected, - $this->instance->save_configuration_state( $params ) + $this->instance->save_configuration_state( $params ), ); } @@ -559,7 +559,7 @@ public function test_get_configuration_state() { 'finishedSteps' => [ 'step1', 'step2' ], ], ], - $this->instance->get_configuration_state() + $this->instance->get_configuration_state(), ); } @@ -583,7 +583,7 @@ public function test_get_configuration_state_failure() { 'status' => 500, 'error' => 'Could not get data from the database', ], - $this->instance->get_configuration_state() + $this->instance->get_configuration_state(), ); } } diff --git a/tests/Unit/Actions/Importing/Abstract_Aioseo_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Abstract_Aioseo_Importing_Action_Test.php index 50c139bb979..28e86c93b14 100644 --- a/tests/Unit/Actions/Importing/Abstract_Aioseo_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Abstract_Aioseo_Importing_Action_Test.php @@ -87,7 +87,7 @@ protected function set_up() { $this->robots_transformer = Mockery::mock( Aioseo_Robots_Transformer_Service::class ); $this->mock_instance = Mockery::mock( Abstract_Aioseo_Importing_Action::class, - [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ] + [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ], )->makePartial()->shouldAllowMockingProtectedMethods(); } diff --git a/tests/Unit/Actions/Importing/Abstract_Aioseo_Settings_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Abstract_Aioseo_Settings_Importing_Action_Test.php index c70fd1aaa41..5181bc34f4f 100644 --- a/tests/Unit/Actions/Importing/Abstract_Aioseo_Settings_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Abstract_Aioseo_Settings_Importing_Action_Test.php @@ -91,7 +91,7 @@ protected function set_up() { $this->robots_transformer = Mockery::mock( Aioseo_Robots_Transformer_Service::class ); $this->mock_instance = Mockery::mock( Abstract_Aioseo_Settings_Importing_Action::class, - [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ] + [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ], )->makePartial()->shouldAllowMockingProtectedMethods(); } @@ -323,7 +323,7 @@ public static function provider_get_limited_unindexed() { return [ [ [], true, 0 ], [ [ 0 ], false, 1 ], - [ [ 54321 ], false, 1 ], + [ [ 54_321 ], false, 1 ], ]; } diff --git a/tests/Unit/Actions/Importing/Aioseo_Cleanup_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_Cleanup_Action_Test.php index b5677bf38b0..11e3463181c 100644 --- a/tests/Unit/Actions/Importing/Aioseo_Cleanup_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_Cleanup_Action_Test.php @@ -154,12 +154,12 @@ public function test_index( $completed_option, $query_times, $set_complete_times '_aioseo_og_description', '_aioseo_twitter_title', '_aioseo_twitter_description', - ] + ], ) ->andReturn( " DELETE FROM wp_postmeta - WHERE meta_key IN ('_aioseo_title','_aioseo_description','_aioseo_og_title','_aioseo_og_description','_aioseo_twitter_title','_aioseo_twitter_description')" + WHERE meta_key IN ('_aioseo_title','_aioseo_description','_aioseo_og_title','_aioseo_og_description','_aioseo_twitter_title','_aioseo_twitter_description')", ); $this->wpdb->expects( 'query' ) @@ -167,10 +167,10 @@ public function test_index( $completed_option, $query_times, $set_complete_times ->with( " DELETE FROM wp_postmeta - WHERE meta_key IN ('_aioseo_title','_aioseo_description','_aioseo_og_title','_aioseo_og_description','_aioseo_twitter_title','_aioseo_twitter_description')" + WHERE meta_key IN ('_aioseo_title','_aioseo_description','_aioseo_og_title','_aioseo_og_description','_aioseo_twitter_title','_aioseo_twitter_description')", ) ->andReturn( - $postmeta_cleanup + $postmeta_cleanup, ); $this->aioseo_helper->expects( 'aioseo_exists' ) @@ -186,7 +186,7 @@ public function test_index( $completed_option, $query_times, $set_complete_times ->times( $query_times ) ->with( $expected_truncate_query ) ->andReturn( - $truncate_cleanup + $truncate_cleanup, ); $this->options->expects( 'get' ) diff --git a/tests/Unit/Actions/Importing/Aioseo_Custom_Archive_Settings_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_Custom_Archive_Settings_Importing_Action_Test.php index 214d53ca3bd..b6d5d7616b4 100644 --- a/tests/Unit/Actions/Importing/Aioseo_Custom_Archive_Settings_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_Custom_Archive_Settings_Importing_Action_Test.php @@ -159,7 +159,7 @@ protected function set_up() { $this->mock_instance = Mockery::mock( Aioseo_Custom_Archive_Settings_Importing_Action_Double::class, - [ $this->import_cursor, $this->options, $this->sanitization, $this->post_type, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ] + [ $this->import_cursor, $this->options, $this->sanitization, $this->post_type, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->mock_instance->set_import_helper( $this->import_helper ); } diff --git a/tests/Unit/Actions/Importing/Aioseo_Default_Archive_Settings_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_Default_Archive_Settings_Importing_Action_Test.php index 8fe47247e5e..2459fc85936 100644 --- a/tests/Unit/Actions/Importing/Aioseo_Default_Archive_Settings_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_Default_Archive_Settings_Importing_Action_Test.php @@ -162,7 +162,7 @@ protected function set_up() { $this->mock_instance = Mockery::mock( Aioseo_Default_Archive_Settings_Importing_Action_Double::class, - [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ] + [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->mock_instance->set_import_helper( $this->import_helper ); } diff --git a/tests/Unit/Actions/Importing/Aioseo_General_Settings_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_General_Settings_Importing_Action_Test.php index 4d46928138e..7fa4e24ee87 100644 --- a/tests/Unit/Actions/Importing/Aioseo_General_Settings_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_General_Settings_Importing_Action_Test.php @@ -151,7 +151,7 @@ protected function set_up() { $this->mock_instance = Mockery::mock( Aioseo_General_Settings_Importing_Action_Double::class, - [ $this->import_cursor, $this->options, $this->sanitization, $this->image, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ] + [ $this->import_cursor, $this->options, $this->sanitization, $this->image, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->mock_instance->set_import_helper( $this->import_helper ); } diff --git a/tests/Unit/Actions/Importing/Aioseo_Posts_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_Posts_Importing_Action_Test.php index 9c0b69b1665..b1047f57977 100644 --- a/tests/Unit/Actions/Importing/Aioseo_Posts_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_Posts_Importing_Action_Test.php @@ -180,7 +180,7 @@ protected function set_up() { $this->replacevar_handler, $this->robots_provider, $this->robots_transformer, - $this->social_images_provider + $this->social_images_provider, ); $this->mock_instance = Mockery::mock( Aioseo_Posts_Importing_Action_Double::class, @@ -197,7 +197,7 @@ protected function set_up() { $this->robots_provider, $this->robots_transformer, $this->social_images_provider, - ] + ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->mock_instance->set_aioseo_helper( $this->aioseo_helper ); @@ -230,7 +230,7 @@ public function test_get_total_unindexed() { ->once() ->with( $expected_query, - [ 1337, 25 ] + [ 1337, 25 ], ) ->andReturn( ' @@ -238,7 +238,7 @@ public function test_get_total_unindexed() { FROM wp_aioseo_posts WHERE id > 1337 ORDER BY id - LIMIT 25' + LIMIT 25', ); $this->aioseo_helper->expects( 'get_table' ) @@ -253,7 +253,7 @@ public function test_get_total_unindexed() { FROM wp_aioseo_posts WHERE id > 1337 ORDER BY id - LIMIT 25' + LIMIT 25', ) ->andReturn( [ '1338', '1339', '1340' ] ); @@ -298,7 +298,7 @@ public function test_donot_map( $aioseo_indexables, $is_default, $check_if_defau ->once() ->with( $expected_query, - [ 1337, 25 ] + [ 1337, 25 ], ) ->andReturn( ' @@ -306,7 +306,7 @@ public function test_donot_map( $aioseo_indexables, $is_default, $check_if_defau FROM wp_aioseo_posts WHERE id > 1337 ORDER BY id - LIMIT 25' + LIMIT 25', ); $this->aioseo_helper->expects( 'get_table' ) @@ -395,7 +395,7 @@ public function test_map_with_empty_yoast_indexable() { 'focus' => [ 'keyphrase' => 'key phrase', ], - ] + ], ), 'og_image_type' => 'default', 'twitter_image_type' => 'auto', @@ -577,7 +577,7 @@ public function test_map_with_existing_yoast_indexable() { 'focus' => [ 'not_keyphrase' => 'key phrase', ], - ] + ], ), 'og_image_type' => 'attach', 'twitter_image_type' => 'auto', diff --git a/tests/Unit/Actions/Importing/Aioseo_Posttype_Defaults_Settings_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_Posttype_Defaults_Settings_Importing_Action_Test.php index 2372b729a87..e6795c63839 100644 --- a/tests/Unit/Actions/Importing/Aioseo_Posttype_Defaults_Settings_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_Posttype_Defaults_Settings_Importing_Action_Test.php @@ -176,7 +176,7 @@ protected function set_up() { $this->mock_instance = Mockery::mock( Aioseo_Posttype_Defaults_Settings_Importing_Action_Double::class, - [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ] + [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->mock_instance->set_import_helper( $this->import_helper ); } diff --git a/tests/Unit/Actions/Importing/Aioseo_Taxonomy_Settings_Importing_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_Taxonomy_Settings_Importing_Action_Test.php index 3a8cfe49ef1..041f5e0c8fd 100644 --- a/tests/Unit/Actions/Importing/Aioseo_Taxonomy_Settings_Importing_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_Taxonomy_Settings_Importing_Action_Test.php @@ -162,7 +162,7 @@ protected function set_up() { $this->mock_instance = Mockery::mock( Aioseo_Taxonomy_Settings_Importing_Action_Double::class, - [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ] + [ $this->import_cursor, $this->options, $this->sanitization, $this->replacevar_handler, $this->robots_provider, $this->robots_transformer ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->mock_instance->set_import_helper( $this->import_helper ); } diff --git a/tests/Unit/Actions/Importing/Aioseo_Validate_Data_Action_Test.php b/tests/Unit/Actions/Importing/Aioseo_Validate_Data_Action_Test.php index 8e3133aac2f..5413db9e6e1 100644 --- a/tests/Unit/Actions/Importing/Aioseo_Validate_Data_Action_Test.php +++ b/tests/Unit/Actions/Importing/Aioseo_Validate_Data_Action_Test.php @@ -130,7 +130,7 @@ protected function set_up() { $this->general_settings_importing_action, $this->posttype_defaults_settings_importing_action, $this->taxonomy_settings_importing_action, - $this->post_importing_action + $this->post_importing_action, ); $this->instance->set_aioseo_helper( $this->aioseo_helper ); diff --git a/tests/Unit/Actions/Importing/Deactivate_Conflicting_Plugins_Action_Test.php b/tests/Unit/Actions/Importing/Deactivate_Conflicting_Plugins_Action_Test.php index 7848b33dd24..602dcf9e044 100644 --- a/tests/Unit/Actions/Importing/Deactivate_Conflicting_Plugins_Action_Test.php +++ b/tests/Unit/Actions/Importing/Deactivate_Conflicting_Plugins_Action_Test.php @@ -74,7 +74,7 @@ public function set_up() { $this->replacevar_handler, $this->robots_provider, $this->robots_transformer, - $this->conflicting_plugins_service + $this->conflicting_plugins_service, ); } diff --git a/tests/Unit/Actions/Indexables/Indexable_Head_Action_Test.php b/tests/Unit/Actions/Indexables/Indexable_Head_Action_Test.php index 591d7946933..0a91b570f06 100644 --- a/tests/Unit/Actions/Indexables/Indexable_Head_Action_Test.php +++ b/tests/Unit/Actions/Indexables/Indexable_Head_Action_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Meta_Surface::class, - $this->getPropertyValue( $this->instance, 'meta_surface' ) + $this->getPropertyValue( $this->instance, 'meta_surface' ), ); } @@ -100,7 +100,7 @@ public function test_retrieving_meta( $method, $input ) { 'json' => [ 'key' => 'value' ], 'status' => 200, ], - $output + $output, ); } @@ -127,7 +127,7 @@ public function test_retrieving_meta_for_posts_page() { 'json' => [ 'key' => 'value' ], 'status' => 200, ], - $this->instance->for_posts_page() + $this->instance->for_posts_page(), ); } @@ -156,7 +156,7 @@ public function test_retrieving_meta_with_meta_not_found( $method, $input ) { (object) [ 'html' => 'this is the 404 head', 'json' => [ 'key' => 'value' ], - ] + ], ); $this->meta_surface @@ -180,7 +180,7 @@ public function test_retrieving_meta_with_meta_not_found( $method, $input ) { 'json' => [ 'key' => 'value' ], 'status' => 404, ], - $this->instance->{$method}( $input ) + $this->instance->{$method}( $input ), ); } @@ -199,7 +199,7 @@ public function test_retrieving_meta_for_posts_page_with_meta_not_found() { (object) [ 'html' => 'this is the 404 head', 'json' => [ 'key' => 'value' ], - ] + ], ); $this->meta_surface @@ -216,7 +216,7 @@ public function test_retrieving_meta_for_posts_page_with_meta_not_found() { 'json' => [ 'key' => 'value' ], 'status' => 404, ], - $this->instance->for_posts_page() + $this->instance->for_posts_page(), ); } diff --git a/tests/Unit/Actions/Indexing/Abstract_Link_Indexing_Action_Test.php b/tests/Unit/Actions/Indexing/Abstract_Link_Indexing_Action_Test.php index dde441f14a9..58205c8a2bb 100644 --- a/tests/Unit/Actions/Indexing/Abstract_Link_Indexing_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Abstract_Link_Indexing_Action_Test.php @@ -89,7 +89,7 @@ protected function set_up() { $this->indexable_helper, $this->repository, $this->wpdb, - ] + ], )->makePartial(); } @@ -103,19 +103,19 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Indexable_Link_Builder::class, - $this->getPropertyValue( $this->instance, 'link_builder' ) + $this->getPropertyValue( $this->instance, 'link_builder' ), ); $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'repository' ) + $this->getPropertyValue( $this->instance, 'repository' ), ); $this->assertInstanceOf( 'wpdb', - $this->getPropertyValue( $this->instance, 'wpdb' ) + $this->getPropertyValue( $this->instance, 'wpdb' ), ); } diff --git a/tests/Unit/Actions/Indexing/Indexable_Indexing_Complete_Action_Test.php b/tests/Unit/Actions/Indexing/Indexable_Indexing_Complete_Action_Test.php index 2be268eb9b6..de5a17ebd56 100644 --- a/tests/Unit/Actions/Indexing/Indexable_Indexing_Complete_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Indexable_Indexing_Complete_Action_Test.php @@ -42,7 +42,7 @@ protected function set_up() { $this->indexable_helper = Mockery::mock( Indexable_Helper::class ); $this->instance = new Indexable_Indexing_Complete_Action( - $this->indexable_helper + $this->indexable_helper, ); } @@ -56,7 +56,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); } diff --git a/tests/Unit/Actions/Indexing/Indexable_Post_Indexation_Action_Test.php b/tests/Unit/Actions/Indexing/Indexable_Post_Indexation_Action_Test.php index d6349871fbf..c3036e8fc45 100644 --- a/tests/Unit/Actions/Indexing/Indexable_Post_Indexation_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Indexable_Post_Indexation_Action_Test.php @@ -93,7 +93,7 @@ protected function set_up() { $this->repository, $this->wpdb, $this->builder_versions, - $this->post_helper + $this->post_helper, ); } @@ -287,7 +287,7 @@ public function test_index() { ->once() ->with( $expected_query, - [ 'public_post_type', 'auto-draft', 2, 25 ] + [ 'public_post_type', 'auto-draft', 2, 25 ], ) ->andReturn( 'query' ); $this->wpdb @@ -371,7 +371,7 @@ public function test_index_with_excluded_post_types() { ->once() ->with( $expected_query, - [ 'public_post_type', 'auto-draft', 2, 25 ] + [ 'public_post_type', 'auto-draft', 2, 25 ], ) ->andReturn( 'query' ); $this->wpdb @@ -427,7 +427,7 @@ public function test_index_no_indexables_created() { ->once() ->with( $expected_query, - [ 'public_post_type', 'auto-draft', 2, 25 ] + [ 'public_post_type', 'auto-draft', 2, 25 ], ) ->andReturn( 'query' ); $this->wpdb diff --git a/tests/Unit/Actions/Indexing/Indexable_Post_Type_Archive_Indexation_Action_Test.php b/tests/Unit/Actions/Indexing/Indexable_Post_Type_Archive_Indexation_Action_Test.php index bd62b306c38..bc62c5bc0ee 100644 --- a/tests/Unit/Actions/Indexing/Indexable_Post_Type_Archive_Indexation_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Indexable_Post_Type_Archive_Indexation_Action_Test.php @@ -84,7 +84,7 @@ protected function set_up() { $this->repository, $this->builder, $this->post_type, - $this->versions + $this->versions, ); } diff --git a/tests/Unit/Actions/Indexing/Indexable_Term_Indexation_Action_Test.php b/tests/Unit/Actions/Indexing/Indexable_Term_Indexation_Action_Test.php index 1578689cb54..1e0226d664e 100644 --- a/tests/Unit/Actions/Indexing/Indexable_Term_Indexation_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Indexable_Term_Indexation_Action_Test.php @@ -83,7 +83,7 @@ protected function set_up() { $this->taxonomy, $this->repository, $this->wpdb, - $this->versions + $this->versions, ); } @@ -113,7 +113,7 @@ public function test_get_total_unindexed() { [ 'public_taxonomy', 'other_taxonomy', - ] + ], ); $this->wpdb->expects( 'prepare' ) ->once() @@ -158,7 +158,7 @@ public function test_get_limited_unindexed_count() { [ 'public_taxonomy', 'other_taxonomy', - ] + ], ); $this->wpdb->expects( 'prepare' ) @@ -247,7 +247,7 @@ public function test_index() { [ 'public_taxonomy', 'other_taxonomy', - ] + ], ); $this->wpdb->expects( 'prepare' ) ->once() @@ -317,7 +317,7 @@ public function test_index_no_indexables_created() { [ 'public_taxonomy', 'other_taxonomy', - ] + ], ); $this->wpdb->expects( 'prepare' ) ->once() diff --git a/tests/Unit/Actions/Indexing/Indexing_Complete_Action_Test.php b/tests/Unit/Actions/Indexing/Indexing_Complete_Action_Test.php index 721985d869d..3517f539ce5 100644 --- a/tests/Unit/Actions/Indexing/Indexing_Complete_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Indexing_Complete_Action_Test.php @@ -53,7 +53,7 @@ protected function set_up() { public function test_constructor() { self::assertInstanceOf( Indexing_Helper::class, - $this->getPropertyValue( $this->instance, 'indexing_helper' ) + $this->getPropertyValue( $this->instance, 'indexing_helper' ), ); } diff --git a/tests/Unit/Actions/Indexing/Post_Link_Indexing_Action_Test.php b/tests/Unit/Actions/Indexing/Post_Link_Indexing_Action_Test.php index b11d58b0e94..821dcc67f55 100644 --- a/tests/Unit/Actions/Indexing/Post_Link_Indexing_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Post_Link_Indexing_Action_Test.php @@ -89,7 +89,7 @@ protected function set_up() { $this->link_builder, $this->indexable_helper, $this->repository, - $this->wpdb + $this->wpdb, ); $this->instance->set_helper( $this->post_type_helper ); } @@ -106,7 +106,7 @@ public function test_set_helper() { $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); } @@ -357,7 +357,7 @@ public function test_index_without_link_count() { 'ID' => 8, 'post_content' => 'foo', ], - ] + ], ); $indexable = Mockery::mock( Indexable_Mock::class ); diff --git a/tests/Unit/Actions/Indexing/Term_Link_Indexing_Action_Test.php b/tests/Unit/Actions/Indexing/Term_Link_Indexing_Action_Test.php index be632fb931d..c4a3163f16b 100644 --- a/tests/Unit/Actions/Indexing/Term_Link_Indexing_Action_Test.php +++ b/tests/Unit/Actions/Indexing/Term_Link_Indexing_Action_Test.php @@ -89,7 +89,7 @@ protected function set_up() { $this->link_builder, $this->indexable_helper, $this->repository, - $this->wpdb + $this->wpdb, ); $this->instance->set_helper( $this->taxonomy_helper ); } @@ -106,7 +106,7 @@ public function test_set_helper() { $this->assertInstanceOf( Taxonomy_Helper::class, - $this->getPropertyValue( $this->instance, 'taxonomy_helper' ) + $this->getPropertyValue( $this->instance, 'taxonomy_helper' ), ); } @@ -396,7 +396,7 @@ public function test_index_without_link_count() { 'term_id' => 8, 'description' => 'foo', ], - ] + ], ); $indexable = Mockery::mock( Indexable_Mock::class ); diff --git a/tests/Unit/Actions/SEMrush/SEMrush_Login_Action_Test.php b/tests/Unit/Actions/SEMrush/SEMrush_Login_Action_Test.php index 5747721ecc0..01dbb0faad2 100644 --- a/tests/Unit/Actions/SEMrush/SEMrush_Login_Action_Test.php +++ b/tests/Unit/Actions/SEMrush/SEMrush_Login_Action_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( SEMrush_Client::class, - $this->getPropertyValue( $this->instance, 'client' ) + $this->getPropertyValue( $this->instance, 'client' ), ); } @@ -70,7 +70,7 @@ public function test_valid_authentication() { $token_data = [ 'access_token' => 'some valid token', 'refresh_token' => 'some valid refresh token', - 'expires' => 99999999, + 'expires' => 99_999_999, 'has_expired' => false, 'created_at' => 0, ]; @@ -81,9 +81,9 @@ public function test_valid_authentication() { [ 'getToken' => '000000', 'getRefreshToken' => '000001', - 'getExpires' => 604800, + 'getExpires' => 604_800, 'hasExpired' => false, - ] + ], ); $tokens_class = Mockery::mock( OAuth_Token::class ); @@ -101,7 +101,7 @@ public function test_valid_authentication() { 'tokens' => $token_data, 'status' => 200, ], - $this->instance->authenticate( '123456' ) + $this->instance->authenticate( '123456' ), ); } @@ -123,7 +123,7 @@ public function test_invalid_authentication() { 'tokens' => [], 'error' => 'Invalid token', 'status' => 500, - ] + ], ); $this->client_instance @@ -137,7 +137,7 @@ public function test_invalid_authentication() { 'error' => 'Invalid token', 'status' => 500, ], - $this->instance->authenticate( '123456' ) + $this->instance->authenticate( '123456' ), ); } } diff --git a/tests/Unit/Actions/SEMrush/SEMrush_Options_Action_Test.php b/tests/Unit/Actions/SEMrush/SEMrush_Options_Action_Test.php index 699ad246b9f..316abd773bf 100644 --- a/tests/Unit/Actions/SEMrush/SEMrush_Options_Action_Test.php +++ b/tests/Unit/Actions/SEMrush/SEMrush_Options_Action_Test.php @@ -52,7 +52,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } @@ -75,7 +75,7 @@ public function test_successful_set_country_code() { 'success' => true, 'status' => 200, ], - $this->instance->set_country_code( 'us' ) + $this->instance->set_country_code( 'us' ), ); } @@ -99,7 +99,7 @@ public function test_unsuccessful_set_country_code() { 'status' => 500, 'error' => 'Could not save option in the database', ], - $this->instance->set_country_code( 'us' ) + $this->instance->set_country_code( 'us' ), ); } } diff --git a/tests/Unit/Actions/SEMrush/SEMrush_Phrases_Action_Test.php b/tests/Unit/Actions/SEMrush/SEMrush_Phrases_Action_Test.php index e4be85ce41f..b4d8e4785fc 100644 --- a/tests/Unit/Actions/SEMrush/SEMrush_Phrases_Action_Test.php +++ b/tests/Unit/Actions/SEMrush/SEMrush_Phrases_Action_Test.php @@ -53,7 +53,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( SEMrush_Client::class, - $this->getPropertyValue( $this->instance, 'client' ) + $this->getPropertyValue( $this->instance, 'client' ), ); } @@ -110,7 +110,7 @@ public function test_get_related_keyphrases_from_api() { ], 'status' => 200, ], - $this->instance->get_related_keyphrases( $keyphrase, $country_code ) + $this->instance->get_related_keyphrases( $keyphrase, $country_code ), ); } @@ -135,7 +135,7 @@ public function test_get_related_keyphrases_from_cache() { 'rows' => [], ], 'status' => 200, - ] + ], ); $this->client_instance->expects( 'get' )->times( 0 ); @@ -150,7 +150,7 @@ public function test_get_related_keyphrases_from_cache() { ], 'status' => 200, ], - $this->instance->get_related_keyphrases( $keyphrase, $database ) + $this->instance->get_related_keyphrases( $keyphrase, $database ), ); } } diff --git a/tests/Unit/Actions/Wincher/Wincher_Account_Action_Test.php b/tests/Unit/Actions/Wincher/Wincher_Account_Action_Test.php index 06a9dc02cf1..129643bfd35 100644 --- a/tests/Unit/Actions/Wincher/Wincher_Account_Action_Test.php +++ b/tests/Unit/Actions/Wincher/Wincher_Account_Action_Test.php @@ -50,7 +50,7 @@ protected function set_up() { $this->options_helper = Mockery::mock( Options_Helper::class ); $this->instance = new Wincher_Account_Action( $this->client_instance, - $this->options_helper + $this->options_helper, ); } @@ -64,12 +64,12 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Wincher_Client::class, - $this->getPropertyValue( $this->instance, 'client' ) + $this->getPropertyValue( $this->instance, 'client' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } @@ -94,7 +94,7 @@ public function test_check_limit() { 'history_days' => 31, ], 'status' => 200, - ] + ], ); $this->assertEquals( @@ -105,7 +105,7 @@ public function test_check_limit() { 'status' => 200, 'historyDays' => 31, ], - $this->instance->check_limit() + $this->instance->check_limit(), ); } @@ -130,7 +130,7 @@ public function test_invalid_check_limit() { 'history_days' => 31, ], 'status' => 200, - ] + ], ); $this->assertEquals( @@ -141,7 +141,7 @@ public function test_invalid_check_limit() { 'status' => 200, 'historyDays' => 31, ], - $this->instance->check_limit() + $this->instance->check_limit(), ); } @@ -160,24 +160,24 @@ public function test_unlimited_check_limit() { [ 'limits' => [ 'keywords' => [ - 'usage' => 100000, + 'usage' => 100_000, 'limit' => null, ], 'history_days' => 31, ], 'status' => 200, - ] + ], ); $this->assertEquals( (object) [ 'canTrack' => true, 'limit' => null, - 'usage' => 100000, + 'usage' => 100_000, 'status' => 200, 'historyDays' => 31, ], - $this->instance->check_limit() + $this->instance->check_limit(), ); } @@ -198,7 +198,7 @@ public function test_invalid_get_upgrade_campaign_type() { 'value' => 0.9, 'months' => 10, 'status' => 200, - ] + ], ); $this->assertEquals( @@ -207,7 +207,7 @@ public function test_invalid_get_upgrade_campaign_type() { 'months' => null, 'status' => 200, ], - $this->instance->get_upgrade_campaign() + $this->instance->get_upgrade_campaign(), ); } @@ -228,7 +228,7 @@ public function test_invalid_get_upgrade_campaign_months() { 'value' => 0.9, 'months' => 0, 'status' => 200, - ] + ], ); $this->assertEquals( @@ -237,7 +237,7 @@ public function test_invalid_get_upgrade_campaign_months() { 'months' => null, 'status' => 200, ], - $this->instance->get_upgrade_campaign() + $this->instance->get_upgrade_campaign(), ); } @@ -258,7 +258,7 @@ public function test_valid_get_upgrade_campaign() { 'value' => 0.9, 'months' => 10, 'status' => 200, - ] + ], ); $this->assertEquals( @@ -267,7 +267,7 @@ public function test_valid_get_upgrade_campaign() { 'months' => 10, 'status' => 200, ], - $this->instance->get_upgrade_campaign() + $this->instance->get_upgrade_campaign(), ); } @@ -290,7 +290,7 @@ public function test_empty_get_upgrade_campaign() { 'months' => null, 'status' => 200, ], - $this->instance->get_upgrade_campaign() + $this->instance->get_upgrade_campaign(), ); } } diff --git a/tests/Unit/Actions/Wincher/Wincher_Keyphrases_Action_Test.php b/tests/Unit/Actions/Wincher/Wincher_Keyphrases_Action_Test.php index 1c1b3afeae2..8e9bbd7fa2e 100644 --- a/tests/Unit/Actions/Wincher/Wincher_Keyphrases_Action_Test.php +++ b/tests/Unit/Actions/Wincher/Wincher_Keyphrases_Action_Test.php @@ -62,7 +62,7 @@ protected function set_up() { $this->instance = new Wincher_Keyphrases_Action( $this->client_instance, $this->options_helper, - $this->indexable_repository + $this->indexable_repository, ); } @@ -76,17 +76,17 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Wincher_Client::class, - $this->getPropertyValue( $this->instance, 'client' ) + $this->getPropertyValue( $this->instance, 'client' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); } @@ -122,18 +122,18 @@ public function test_track_keyphrases() { 'keyword' => 'yoast seo', 'groups' => [], ], - ] - ) + ], + ), ) ->andReturns( [ 'data' => [ [ 'keyword' => 'yoast seo', - 'id' => 12345, + 'id' => 12_345, ], ], - ] + ], ); $this->assertEquals( @@ -141,11 +141,11 @@ public function test_track_keyphrases() { 'results' => (object) [ 'yoast seo' => [ 'keyword' => 'yoast seo', - 'id' => 12345, + 'id' => 12_345, ], ], ], - $this->instance->track_keyphrases( [ 'yoast seo' ], $limits ) + $this->instance->track_keyphrases( [ 'yoast seo' ], $limits ), ); } @@ -176,7 +176,7 @@ public function test_track_keyphrases_where_limit_is_reached() { 'error' => 'Account limit exceeded', 'status' => 400, ], - $this->instance->track_keyphrases( [ 'yoast seo' ], $limits ) + $this->instance->track_keyphrases( [ 'yoast seo' ], $limits ), ); } @@ -207,7 +207,7 @@ public function test_track_keyphrases_where_limit_will_be_exceeded() { 'error' => 'Account limit exceeded', 'status' => 400, ], - $this->instance->track_keyphrases( [ 'yoast seo', 'wincher' ], $limits ) + $this->instance->track_keyphrases( [ 'yoast seo', 'wincher' ], $limits ), ); } @@ -233,14 +233,14 @@ public function test_untrack_keyphrase() { [ 'data' => [], 'status' => 200, - ] + ], ); $this->assertEquals( (object) [ 'status' => 200, ], - $this->instance->untrack_keyphrase( 12345 ) + $this->instance->untrack_keyphrase( 12_345 ), ); } @@ -264,7 +264,7 @@ public function test_get_tracked_keyphrases() { [ [ 'primary_focus_keyword' => 'yoast seo' ], [ 'primary_focus_keyword' => 'wincher' ], - ] + ], ); Monkey\Filters\expectApplied( 'wpseo_wincher_all_keyphrases' ); @@ -279,25 +279,25 @@ public function test_get_tracked_keyphrases() { 'keywords' => [ 'yoast seo', 'wincher' ], 'url' => null, 'start_at' => null, - ] + ], ), [ 'timeout' => 60, - ] + ], ) ->andReturns( [ 'data' => [ [ 'keyword' => 'yoast seo', - 'id' => 12345, + 'id' => 12_345, ], [ 'keyword' => 'wincher', - 'id' => 12346, + 'id' => 12_346, ], ], - ] + ], ); $this->assertEquals( @@ -305,15 +305,15 @@ public function test_get_tracked_keyphrases() { 'results' => (object) [ 'yoast seo' => [ 'keyword' => 'yoast seo', - 'id' => 12345, + 'id' => 12_345, ], 'wincher' => [ 'keyword' => 'wincher', - 'id' => 12346, + 'id' => 12_346, ], ], ], - $this->instance->get_tracked_keyphrases() + $this->instance->get_tracked_keyphrases(), ); } @@ -341,23 +341,23 @@ public function test_get_tracked_keyphrases_no_data_key() { 'keywords' => [ 'yoast seo' ], 'url' => null, 'start_at' => null, - ] + ], ), [ 'timeout' => 60, - ] + ], ) ->andReturns( [ 'some_other_key' => [], - ] + ], ); $this->assertEquals( (object) [ 'some_other_key' => [], ], - $this->instance->get_tracked_keyphrases( [ 'yoast seo' ] ) + $this->instance->get_tracked_keyphrases( [ 'yoast seo' ] ), ); } @@ -378,7 +378,7 @@ public function test_get_tracked_keyphrases_does_not_call_api_when_no_keyphrases 'results' => (object) [], 'status' => 200, ], - $this->instance->get_tracked_keyphrases( [] ) + $this->instance->get_tracked_keyphrases( [] ), ); } @@ -406,25 +406,25 @@ public function test_get_tracked_keyphrases_filtered_by_used_keyphrases() { 'keywords' => [ 'yoast seo' ], 'url' => null, 'start_at' => null, - ] + ], ), [ 'timeout' => 60, - ] + ], ) ->andReturns( [ 'data' => [ [ 'keyword' => 'yoast seo', - 'id' => 12345, + 'id' => 12_345, ], [ 'keyword' => 'wincher', - 'id' => 12346, + 'id' => 12_346, ], ], - ] + ], ); $this->assertEquals( @@ -432,11 +432,11 @@ public function test_get_tracked_keyphrases_filtered_by_used_keyphrases() { 'results' => (object) [ 'yoast seo' => [ 'keyword' => 'yoast seo', - 'id' => 12345, + 'id' => 12_345, ], ], ], - $this->instance->get_tracked_keyphrases( [ 'yoast seo' ] ) + $this->instance->get_tracked_keyphrases( [ 'yoast seo' ] ), ); } @@ -464,27 +464,27 @@ public function test_get_tracked_keyphrases_with_permalink() { 'keywords' => [ 'yoast seo', 'blog seo' ], 'url' => 'https://yoast.com/blog/', 'start_at' => null, - ] + ], ), [ 'timeout' => 60, - ] + ], ) ->andReturns( [ 'data' => [ [ 'keyword' => 'yoast seo', - 'id' => 22345, + 'id' => 22_345, 'position' => 20, ], [ 'keyword' => 'blog seo', - 'id' => 22346, + 'id' => 22_346, 'position' => 22, ], ], - ] + ], ); $this->assertEquals( @@ -492,17 +492,17 @@ public function test_get_tracked_keyphrases_with_permalink() { 'results' => (object) [ 'yoast seo' => [ 'keyword' => 'yoast seo', - 'id' => 22345, + 'id' => 22_345, 'position' => 20, ], 'blog seo' => [ 'keyword' => 'blog seo', - 'id' => 22346, + 'id' => 22_346, 'position' => 22, ], ], ], - $this->instance->get_tracked_keyphrases( [ 'yoast seo', 'blog seo' ], 'https://yoast.com/blog/' ) + $this->instance->get_tracked_keyphrases( [ 'yoast seo', 'blog seo' ], 'https://yoast.com/blog/' ), ); } } diff --git a/tests/Unit/Actions/Wincher/Wincher_Login_Action_Test.php b/tests/Unit/Actions/Wincher/Wincher_Login_Action_Test.php index 36822170778..bbb4199dee2 100644 --- a/tests/Unit/Actions/Wincher/Wincher_Login_Action_Test.php +++ b/tests/Unit/Actions/Wincher/Wincher_Login_Action_Test.php @@ -53,7 +53,7 @@ protected function set_up() { $this->options_helper = Mockery::mock( Options_Helper::class ); $this->instance = new Wincher_Login_Action( $this->client_instance, - $this->options_helper + $this->options_helper, ); } @@ -67,12 +67,12 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Wincher_Client::class, - $this->getPropertyValue( $this->instance, 'client' ) + $this->getPropertyValue( $this->instance, 'client' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } @@ -87,7 +87,7 @@ public function test_valid_authentication() { $token_data = [ 'access_token' => 'some valid token', 'refresh_token' => 'some valid refresh token', - 'expires' => 99999999, + 'expires' => 99_999_999, 'has_expired' => false, 'created_at' => 0, ]; @@ -98,9 +98,9 @@ public function test_valid_authentication() { [ 'getToken' => '000000', 'getRefreshToken' => '000001', - 'getExpires' => 604800, + 'getExpires' => 604_800, 'hasExpired' => false, - ] + ], ); $tokens_class = Mockery::mock( OAuth_Token::class ); @@ -123,7 +123,7 @@ public function test_valid_authentication() { 'tokens' => $token_data, 'status' => 200, ], - $this->instance->authenticate( '123456', '12345' ) + $this->instance->authenticate( '123456', '12345' ), ); } @@ -145,7 +145,7 @@ public function test_invalid_authentication() { 'tokens' => [], 'error' => 'Invalid token', 'status' => 500, - ] + ], ); $this->options_helper @@ -163,7 +163,7 @@ public function test_invalid_authentication() { 'error' => 'Invalid token', 'status' => 500, ], - $this->instance->authenticate( '123456', '12345' ) + $this->instance->authenticate( '123456', '12345' ), ); } } diff --git a/tests/Unit/Admin/Admin_Features_Test.php b/tests/Unit/Admin/Admin_Features_Test.php index 6a94132a0c6..f496c4d7251 100644 --- a/tests/Unit/Admin/Admin_Features_Test.php +++ b/tests/Unit/Admin/Admin_Features_Test.php @@ -32,7 +32,7 @@ private function setup_yoastseo_with_expectations() { $container = $this->create_container_with( [ Url_Helper::class => $url_helper, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) diff --git a/tests/Unit/Admin/Capabilities/Capabilities_Utils_Test.php b/tests/Unit/Admin/Capabilities/Capabilities_Utils_Test.php index 10dd1e2b424..de1b79cb7da 100644 --- a/tests/Unit/Admin/Capabilities/Capabilities_Utils_Test.php +++ b/tests/Unit/Admin/Capabilities/Capabilities_Utils_Test.php @@ -40,7 +40,7 @@ protected function set_up() { ->andReturn( [ 'administrator' => 'Administrator', - ] + ], ); Monkey\Functions\expect( 'wp_roles' ) @@ -65,7 +65,7 @@ public function test_get_applicable_users() { 'capabilities' => [ 'wpseo_manage_options' => true, ], - ] + ], ); Monkey\Functions\expect( 'get_users' ) diff --git a/tests/Unit/Admin/Gutenberg_Compatibility_Notification_Test.php b/tests/Unit/Admin/Gutenberg_Compatibility_Notification_Test.php index 7770b36e930..dd16339ba57 100644 --- a/tests/Unit/Admin/Gutenberg_Compatibility_Notification_Test.php +++ b/tests/Unit/Admin/Gutenberg_Compatibility_Notification_Test.php @@ -95,7 +95,7 @@ public function test_manage_notification_remove_notification( $installed, $fully [ 'is_installed' => $installed, 'is_fully_compatible' => $fully_compatible, - ] + ], ); $this->notification_center_mock->expects( 'remove_notification_by_id' )->once()->with( 'wpseo-outdated-gutenberg-plugin' ); @@ -142,7 +142,7 @@ public function test_manage_notification_gutenberg_show_notification() { [ 'is_installed' => true, 'is_fully_compatible' => false, - ] + ], ); Monkey\Functions\expect( 'get_current_user_id' ) @@ -153,7 +153,7 @@ public function test_manage_notification_gutenberg_show_notification() { static function ( $arg ) { // Verify that the added notification is a Yoast_Notification object and has the correct id. return ( \is_a( $arg, Yoast_Notification::class ) && $arg->get_id() === 'wpseo-outdated-gutenberg-plugin' ); - } + }, ); $this->gutenberg_notification->manage_notification(); diff --git a/tests/Unit/Admin/Import/Plugins/Import_AIOSEO_V4_Test.php b/tests/Unit/Admin/Import/Plugins/Import_AIOSEO_V4_Test.php index 3c61ac7d25e..61eff01c12f 100644 --- a/tests/Unit/Admin/Import/Plugins/Import_AIOSEO_V4_Test.php +++ b/tests/Unit/Admin/Import/Plugins/Import_AIOSEO_V4_Test.php @@ -59,7 +59,7 @@ public function test_meta_key_clone_replace() { $wpdb->expects( 'prepare' ) ->with( 'SELECT meta_value FROM tmp_meta_table WHERE meta_value LIKE %s', - '%#custom_field-%' + '%#custom_field-%', ); $wpdb->expects( 'get_col' ) @@ -70,35 +70,35 @@ public function test_meta_key_clone_replace() { '#custom_field-veldje', '#custom_field-some_custom_field #separator_sa #site_title  #custom_field-some_custom_field', '#custom_field-some_custom_field %%hello%% some stuff#site_title  ', - ] + ], ); $wpdb->expects( 'prepare' ) ->with( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', '#custom_field-veldje', - '%%cf_veldje%%' + '%%cf_veldje%%', ); $wpdb->expects( 'prepare' ) ->with( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', '#custom_field-gras', - '%%cf_gras%%' + '%%cf_gras%%', ); $wpdb->expects( 'prepare' ) ->with( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', '#custom_field-groen', - '%%cf_groen%%' + '%%cf_groen%%', ); $wpdb->expects( 'prepare' ) ->with( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', '#custom_field-some_custom_field', - '%%cf_some_custom_field%%' + '%%cf_some_custom_field%%', ); // Custom taxonomies. @@ -106,7 +106,7 @@ public function test_meta_key_clone_replace() { $wpdb->expects( 'prepare' ) ->with( 'SELECT meta_value FROM tmp_meta_table WHERE meta_value LIKE %s', - '%#tax_name-%' + '%#tax_name-%', ); $wpdb->expects( 'get_col' ) @@ -115,21 +115,21 @@ public function test_meta_key_clone_replace() { '#post_title#tax_name-taxonomy', 'some text | #tax_name-taxonomy', '#tax_name-taxonomy#tax_name-category', - ] + ], ); $wpdb->expects( 'prepare' ) ->with( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', '#tax_name-taxonomy', - '%%ct_taxonomy%%' + '%%ct_taxonomy%%', ); $wpdb->expects( 'prepare' ) ->with( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', '#tax_name-category', - '%%ct_category%%' + '%%ct_category%%', ); // The `$replace_values` argument is not used by the class, so pass an empty array. @@ -163,7 +163,7 @@ public function test_meta_key_clone_replace_no_custom_field_replace_vars() { $wpdb->expects( 'prepare' ) ->with( 'SELECT meta_value FROM tmp_meta_table WHERE meta_value LIKE %s', - '%#custom_field-%' + '%#custom_field-%', ); $wpdb->expects( 'get_col' ) @@ -174,7 +174,7 @@ public function test_meta_key_clone_replace_no_custom_field_replace_vars() { $wpdb->expects( 'prepare' ) ->with( 'SELECT meta_value FROM tmp_meta_table WHERE meta_value LIKE %s', - '%#tax_name-%' + '%#tax_name-%', ); $wpdb->expects( 'get_col' ) @@ -221,7 +221,7 @@ private function set_replace_vars_prepare_expectations( $wpdb ) { ->with( 'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )', $aioseo_variable, - $yoast_variable + $yoast_variable, ); } } diff --git a/tests/Unit/Admin/Import/Plugins/Importers_Test.php b/tests/Unit/Admin/Import/Plugins/Importers_Test.php index e7238d27b9c..57505a87682 100644 --- a/tests/Unit/Admin/Import/Plugins/Importers_Test.php +++ b/tests/Unit/Admin/Import/Plugins/Importers_Test.php @@ -40,7 +40,7 @@ public function test_get_importers() { 'WPSEO_Import_WooThemes_SEO', 'WPSEO_Import_WPSEO', ], - WPSEO_Plugin_Importers::get() + WPSEO_Plugin_Importers::get(), ); } } diff --git a/tests/Unit/Admin/Input_Validation_Test.php b/tests/Unit/Admin/Input_Validation_Test.php index 14e17914df7..c401c20869d 100644 --- a/tests/Unit/Admin/Input_Validation_Test.php +++ b/tests/Unit/Admin/Input_Validation_Test.php @@ -48,7 +48,7 @@ public function test_document_title_updated_with_error() { 'message' => 'This is the error message', 'type' => 'error', ], - ] + ], ); $title_with_error_message = Yoast_Input_Validation::add_yoast_admin_document_title_errors( $admin_title ); @@ -83,7 +83,7 @@ public function test_document_title_updated_with_errors() { 'message' => 'This is the second error message', 'type' => 'error', ], - ] + ], ); $title_with_error_message = Yoast_Input_Validation::add_yoast_admin_document_title_errors( $admin_title ); @@ -112,7 +112,7 @@ public function test_document_title_not_updated_with_non_yoast_errors() { 'message' => 'This is the error message', 'type' => 'error', ], - ] + ], ); $title_with_error_message = Yoast_Input_Validation::add_yoast_admin_document_title_errors( $admin_title ); @@ -141,7 +141,7 @@ public function test_document_title_not_updated_with_settings_updated_error() { 'message' => 'This is the error message', 'type' => 'error', ], - ] + ], ); $title_with_error_message = Yoast_Input_Validation::add_yoast_admin_document_title_errors( $admin_title ); diff --git a/tests/Unit/Admin/Metabox/Metabox_Collapsibles_Sections_Test.php b/tests/Unit/Admin/Metabox/Metabox_Collapsibles_Sections_Test.php index 5c631f678ea..d7defd99db3 100644 --- a/tests/Unit/Admin/Metabox/Metabox_Collapsibles_Sections_Test.php +++ b/tests/Unit/Admin/Metabox/Metabox_Collapsibles_Sections_Test.php @@ -48,13 +48,13 @@ public function test_display_content_with_collapsible( $expected ) { $collapsibles[] = new WPSEO_Metabox_Collapsible( 'collapsible-1', 'Collapsible 1 content', - 'Collapsible 1 label' + 'Collapsible 1 label', ); $section = new WPSEO_Metabox_Collapsibles_Sections( 'collapsibles-tab', 'Metabox Tab Title', - $collapsibles + $collapsibles, ); $section->display_content(); @@ -95,13 +95,13 @@ public function test_display_link_with_collapsible() { $collapsibles[] = new WPSEO_Metabox_Collapsible( 'collapsible-1', 'Collapsible 1 content', - 'Collapsible 1 label' + 'Collapsible 1 label', ); $section = new WPSEO_Metabox_Collapsibles_Sections( 'collapsibles-tab', 'Metabox Tab Title', - $collapsibles + $collapsibles, ); $section->display_link(); diff --git a/tests/Unit/Admin/Metabox/Metabox_Editor_Test.php b/tests/Unit/Admin/Metabox/Metabox_Editor_Test.php index 4f33e97dc36..b9b945ee420 100644 --- a/tests/Unit/Admin/Metabox/Metabox_Editor_Test.php +++ b/tests/Unit/Admin/Metabox/Metabox_Editor_Test.php @@ -154,7 +154,7 @@ public function test_add_custom_element_other_properties() { [ 'custom_elements' => '', 'other_property' => 'hello world', - ] + ], ); \ksort( $actual ); diff --git a/tests/Unit/Admin/Metabox/Metabox_Section_Additional_Test.php b/tests/Unit/Admin/Metabox/Metabox_Section_Additional_Test.php index 342fa146a9c..861b6ee1402 100644 --- a/tests/Unit/Admin/Metabox/Metabox_Section_Additional_Test.php +++ b/tests/Unit/Admin/Metabox/Metabox_Section_Additional_Test.php @@ -77,7 +77,7 @@ public function test_display_link( $expected ) { [ 'link_class' => 'additional-class', 'link_aria_label' => 'additional-aria', - ] + ], ); $section->display_link(); @@ -114,7 +114,7 @@ public function test_display_link_no_aria_label() { 'additional-tab', 'Additional Tab', 'Additional Content', - [ 'link_class' => 'additional-class' ] + [ 'link_class' => 'additional-class' ], ); $section->display_link(); diff --git a/tests/Unit/Admin/Metabox/Metabox_Test.php b/tests/Unit/Admin/Metabox/Metabox_Test.php index 16cff0e539b..b1d5a020ae1 100644 --- a/tests/Unit/Admin/Metabox/Metabox_Test.php +++ b/tests/Unit/Admin/Metabox/Metabox_Test.php @@ -79,7 +79,7 @@ public function test_get_additional_meta_sections() { 'link_aria_label' => 'this-is-a-tab', ], ], - ] + ], ); $actual = $this->instance->get_additional_tabs(); @@ -112,7 +112,7 @@ public function test_get_additional_meta_sections_ignores_non_arrays() { 'content' => 'Testing 1 2 3', ], 123, - ] + ], ); $actual = $this->instance->get_additional_tabs(); @@ -142,7 +142,7 @@ public function test_get_additional_meta_sections_ignores_invalid_sections() { 'link_content' => 'Testing Tab', 'content' => 'Testing 1 2 3', ], - ] + ], ); $actual = $this->instance->get_additional_tabs(); diff --git a/tests/Unit/Admin/MyYoast_Proxy_Test.php b/tests/Unit/Admin/MyYoast_Proxy_Test.php index a7c6e74ea4e..bd9adcaf176 100644 --- a/tests/Unit/Admin/MyYoast_Proxy_Test.php +++ b/tests/Unit/Admin/MyYoast_Proxy_Test.php @@ -221,7 +221,7 @@ public function test_render_proxy_page_for_the_research_webworker_file() { ->method( 'set_header' ) ->withConsecutive( [ 'Content-Type: text/javascript; charset=UTF-8' ], - [ 'Cache-Control: max-age=' . WPSEO_MyYoast_Proxy::CACHE_CONTROL_MAX_AGE ] + [ 'Cache-Control: max-age=' . WPSEO_MyYoast_Proxy::CACHE_CONTROL_MAX_AGE ], ); $instance @@ -280,7 +280,7 @@ public function test_render_proxy_page_for_the_research_webworker_file_errored_a [ 'Cache-Control: max-age=' . WPSEO_MyYoast_Proxy::CACHE_CONTROL_MAX_AGE ], [ 'Content-Type: text/plain' ], [ 'Cache-Control: max-age=0' ], - [ 'HTTP/1.0 500 Received unexpected response from MyYoast' ] + [ 'HTTP/1.0 500 Received unexpected response from MyYoast' ], ); $instance->render_proxy_page(); diff --git a/tests/Unit/Admin/Plugin_Availability_Test.php b/tests/Unit/Admin/Plugin_Availability_Test.php index bb2d82f357e..71637e9840e 100644 --- a/tests/Unit/Admin/Plugin_Availability_Test.php +++ b/tests/Unit/Admin/Plugin_Availability_Test.php @@ -53,7 +53,7 @@ public function test_get_plugins_with_dependencies() { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -78,7 +78,7 @@ public function test_get_plugins_with_dependencies() { 'premium' => true, ], ], - $this->instance->get_plugins_with_dependencies() + $this->instance->get_plugins_with_dependencies(), ); } @@ -97,7 +97,7 @@ public function test_get_dependencies() { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -138,7 +138,7 @@ public function test_dependencies_are_satisfied() { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) diff --git a/tests/Unit/Admin/Suggested_Plugins_Construct_Test.php b/tests/Unit/Admin/Suggested_Plugins_Construct_Test.php index 2a86509deb7..071cd320d18 100644 --- a/tests/Unit/Admin/Suggested_Plugins_Construct_Test.php +++ b/tests/Unit/Admin/Suggested_Plugins_Construct_Test.php @@ -22,12 +22,12 @@ final class Suggested_Plugins_Construct_Test extends Suggested_Plugins_TestCase public function test_construct() { $this->assertInstanceOf( WPSEO_Plugin_Availability::class, - $this->getPropertyValue( $this->instance, 'availability_checker' ) + $this->getPropertyValue( $this->instance, 'availability_checker' ), ); $this->assertInstanceOf( Yoast_Notification_Center::class, - $this->getPropertyValue( $this->instance, 'notification_center' ) + $this->getPropertyValue( $this->instance, 'notification_center' ), ); } } diff --git a/tests/Unit/Admin/Suggested_Plugins_Register_Hooks_Test.php b/tests/Unit/Admin/Suggested_Plugins_Register_Hooks_Test.php index e34fca92371..4482b665efd 100644 --- a/tests/Unit/Admin/Suggested_Plugins_Register_Hooks_Test.php +++ b/tests/Unit/Admin/Suggested_Plugins_Register_Hooks_Test.php @@ -23,16 +23,16 @@ public function test_register_hooks() { 10, \has_action( 'admin_init', - [ $this->availability_checker, 'register' ] - ) + [ $this->availability_checker, 'register' ], + ), ); $this->assertEquals( 10, \has_action( 'admin_init', - [ $this->instance, 'add_notifications' ] - ) + [ $this->instance, 'add_notifications' ], + ), ); } } diff --git a/tests/Unit/Admin/Tracking/Tracking_Test.php b/tests/Unit/Admin/Tracking/Tracking_Test.php index 2708fff9105..568be2013fc 100644 --- a/tests/Unit/Admin/Tracking/Tracking_Test.php +++ b/tests/Unit/Admin/Tracking/Tracking_Test.php @@ -29,7 +29,7 @@ public function test_constructor_empty_if_not_in_production() { Monkey\Functions\stubs( [ 'wp_get_environment_type' => 'development', - ] + ], ); WPSEO_Options::set( 'tracking', true ); @@ -62,7 +62,7 @@ public function test_constructor_not_empty_if_in_production() { Monkey\Functions\stubs( [ 'wp_get_environment_type' => 'production', - ] + ], ); WPSEO_Options::set( 'tracking', true ); @@ -96,7 +96,7 @@ public function test_get_collector() { [ Missing_Indexables_Collector::class => Mockery::mock( Missing_Indexables_Collector::class ), To_Be_Cleaned_Indexables_Collector::class => Mockery::mock( To_Be_Cleaned_Indexables_Collector::class ), - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) diff --git a/tests/Unit/Admin/Views/Feature_Toggles_Test.php b/tests/Unit/Admin/Views/Feature_Toggles_Test.php index 9f7684bf028..c4cbd7a6a78 100644 --- a/tests/Unit/Admin/Views/Feature_Toggles_Test.php +++ b/tests/Unit/Admin/Views/Feature_Toggles_Test.php @@ -122,7 +122,7 @@ public function test_feature_toggles() { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link_mock, - ] + ], ); Functions\expect( 'YoastSEO' ) @@ -197,7 +197,7 @@ public function test_toggle_sorting() { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link_mock, - ] + ], ); Functions\expect( 'YoastSEO' ) diff --git a/tests/Unit/Alerts/Application/Default_SEO_Data/Abstract_Default_SEO_Data_Alert_Test.php b/tests/Unit/Alerts/Application/Default_SEO_Data/Abstract_Default_SEO_Data_Alert_Test.php index b6645ceb48a..45611b6a835 100644 --- a/tests/Unit/Alerts/Application/Default_SEO_Data/Abstract_Default_SEO_Data_Alert_Test.php +++ b/tests/Unit/Alerts/Application/Default_SEO_Data/Abstract_Default_SEO_Data_Alert_Test.php @@ -93,7 +93,7 @@ protected function set_up() { $this->short_link_helper, $this->product_helper, $this->indexable_helper, - $this->post_type_helper + $this->post_type_helper, ); } } diff --git a/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Add_Notifications_Test.php b/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Add_Notifications_Test.php index cc0252cf173..82e4d6bc24d 100644 --- a/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Add_Notifications_Test.php +++ b/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Add_Notifications_Test.php @@ -118,7 +118,7 @@ public function test_add_notifications( static function ( $notification ) use ( $expected_message ) { $notification_array = $notification->to_array(); return $notification_array['message'] === $expected_message; - } + }, ); $this->instance->add_notifications(); diff --git a/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php b/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php index a22b89e403d..0dd7aaedf88 100644 --- a/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php +++ b/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php @@ -29,27 +29,27 @@ final class Default_SEO_Data_Alert_Constructor_Test extends Abstract_Default_SEO public function test_constructor() { $this->assertInstanceOf( Yoast_Notification_Center::class, - $this->getPropertyValue( $this->instance, 'notification_center' ) + $this->getPropertyValue( $this->instance, 'notification_center' ), ); $this->assertInstanceOf( Default_SEO_Data_Collector::class, - $this->getPropertyValue( $this->instance, 'default_seo_data_collector' ) + $this->getPropertyValue( $this->instance, 'default_seo_data_collector' ), ); $this->assertInstanceOf( Short_Link_Helper::class, - $this->getPropertyValue( $this->instance, 'short_link_helper' ) + $this->getPropertyValue( $this->instance, 'short_link_helper' ), ); $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); } } diff --git a/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Register_Hooks_Test.php b/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Register_Hooks_Test.php index 9246c783016..ae0310aaaad 100644 --- a/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Register_Hooks_Test.php +++ b/tests/Unit/Alerts/Application/Default_SEO_Data/Default_SEO_Data_Alert_Register_Hooks_Test.php @@ -26,8 +26,8 @@ public function test_register_hooks() { 10, \has_action( 'admin_init', - [ $this->instance, 'add_notifications' ] - ) + [ $this->instance, 'add_notifications' ], + ), ); } } diff --git a/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Abstract_Default_SEO_Data_Collector_Test.php b/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Abstract_Default_SEO_Data_Collector_Test.php index db861aac8e7..1a6ff654076 100644 --- a/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Abstract_Default_SEO_Data_Collector_Test.php +++ b/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Abstract_Default_SEO_Data_Collector_Test.php @@ -40,7 +40,7 @@ protected function set_up() { $this->options_helper = Mockery::mock( Options_Helper::class ); $this->instance = new Default_SEO_Data_Collector( - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php b/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php index 098272231d3..7e07eafd65c 100644 --- a/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php +++ b/tests/Unit/Alerts/Infrastructure/Default_SEO_Data/Default_SEO_Data_Alert_Constructor_Test.php @@ -24,7 +24,7 @@ final class Default_SEO_Data_Alert_Constructor_Test extends Abstract_Default_SEO public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Abstract_Default_SEO_Data_Cron_Callback_Integration_Test.php b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Abstract_Default_SEO_Data_Cron_Callback_Integration_Test.php index 32f9103771b..ef88ac25254 100644 --- a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Abstract_Default_SEO_Data_Cron_Callback_Integration_Test.php +++ b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Abstract_Default_SEO_Data_Cron_Callback_Integration_Test.php @@ -63,7 +63,7 @@ protected function set_up() { $this->instance = new Default_SEO_Data_Cron_Callback_Integration( $this->options_helper, $this->scheduler, - $this->indexable_repository + $this->indexable_repository, ); } } diff --git a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Default_SEO_Data_Cron_Callback_Integration_Constructor_Test.php b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Default_SEO_Data_Cron_Callback_Integration_Constructor_Test.php index 59fbf588ee2..399884ee994 100644 --- a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Default_SEO_Data_Cron_Callback_Integration_Constructor_Test.php +++ b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Callback/Default_SEO_Data_Cron_Callback_Integration_Constructor_Test.php @@ -27,15 +27,15 @@ final class Default_SEO_Data_Cron_Callback_Integration_Constructor_Test extends public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Default_SEO_Data_Cron_Scheduler::class, - $this->getPropertyValue( $this->instance, 'scheduler' ) + $this->getPropertyValue( $this->instance, 'scheduler' ), ); $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); } } diff --git a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Schedule_Default_SEO_Data_Detection_Test.php b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Schedule_Default_SEO_Data_Detection_Test.php index 41f9399ddd2..85f2b7b9d1a 100644 --- a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Schedule_Default_SEO_Data_Detection_Test.php +++ b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Schedule_Default_SEO_Data_Detection_Test.php @@ -50,7 +50,7 @@ public function test_schedule_default_seo_data_detection( */ public static function schedule_default_seo_data_detection_provider() { yield 'Cron already scheduled - do not schedule again' => [ - 'wp_next_scheduled_result' => 1234567890, + 'wp_next_scheduled_result' => 1_234_567_890, 'wp_schedule_event_times' => 0, ]; diff --git a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Unschedule_Default_SEO_Data_Detection_Test.php b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Unschedule_Default_SEO_Data_Detection_Test.php index 6c0b6ae9d8d..47f306b6b3e 100644 --- a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Unschedule_Default_SEO_Data_Detection_Test.php +++ b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Cron_Scheduler/Default_SEO_Data_Cron_Scheduler_Unschedule_Default_SEO_Data_Detection_Test.php @@ -56,7 +56,7 @@ public static function unschedule_default_seo_data_detection_provider() { ]; yield 'Cron scheduled - unschedule it' => [ - 'wp_next_scheduled_result' => 1234567890, + 'wp_next_scheduled_result' => 1_234_567_890, 'wp_unschedule_event_times' => 1, ]; } diff --git a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Abstract_Default_SEO_Data_Watcher_Test.php b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Abstract_Default_SEO_Data_Watcher_Test.php index 41216cb243a..c6d7ab7c358 100644 --- a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Abstract_Default_SEO_Data_Watcher_Test.php +++ b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Abstract_Default_SEO_Data_Watcher_Test.php @@ -53,7 +53,7 @@ protected function set_up() { $this->instance = new Default_SEO_Data_Watcher( $this->indexable_repository, - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Default_SEO_Data_Watcher_Constructor_Test.php b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Default_SEO_Data_Watcher_Constructor_Test.php index b75cd2fccf0..f52c44dcb7a 100644 --- a/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Default_SEO_Data_Watcher_Constructor_Test.php +++ b/tests/Unit/Alerts/User_Interface/Default_SEO_Data/Watcher/Default_SEO_Data_Watcher_Constructor_Test.php @@ -26,11 +26,11 @@ final class Default_SEO_Data_Watcher_Constructor_Test extends Abstract_Default_S public function test_constructor() { $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Analytics/Application/Missing_Indexables_Collector_Test.php b/tests/Unit/Analytics/Application/Missing_Indexables_Collector_Test.php index e0730a5cab5..e657f7f9b22 100644 --- a/tests/Unit/Analytics/Application/Missing_Indexables_Collector_Test.php +++ b/tests/Unit/Analytics/Application/Missing_Indexables_Collector_Test.php @@ -36,7 +36,7 @@ public function test_collector_get( $additional_indexation_actions, $initial_ind $sut = new Missing_Indexables_Collector( $initial_indexation_actions ); $this->assertEquals( $expected_result, - $sut->get() + $sut->get(), ); } diff --git a/tests/Unit/Analytics/Application/To_Be_Cleaned_Indexables_Collector_Test.php b/tests/Unit/Analytics/Application/To_Be_Cleaned_Indexables_Collector_Test.php index bbbfb8372be..a5801be7113 100644 --- a/tests/Unit/Analytics/Application/To_Be_Cleaned_Indexables_Collector_Test.php +++ b/tests/Unit/Analytics/Application/To_Be_Cleaned_Indexables_Collector_Test.php @@ -122,7 +122,7 @@ public function test_collector_get(): void { ], ], ], - $this->sut->get() + $this->sut->get(), ); } } diff --git a/tests/Unit/Analytics/Domain/Missing_Indexable_Bucket_Test.php b/tests/Unit/Analytics/Domain/Missing_Indexable_Bucket_Test.php index 1ca08094516..ba5ca076408 100644 --- a/tests/Unit/Analytics/Domain/Missing_Indexable_Bucket_Test.php +++ b/tests/Unit/Analytics/Domain/Missing_Indexable_Bucket_Test.php @@ -53,7 +53,7 @@ public function test_missing_indexable_bucket(): void { 'count' => 0, ], ], - $this->sut->to_array() + $this->sut->to_array(), ); } } diff --git a/tests/Unit/Analytics/Domain/Missing_Indexable_Count_Test.php b/tests/Unit/Analytics/Domain/Missing_Indexable_Count_Test.php index b83f2769756..7f8885c3741 100644 --- a/tests/Unit/Analytics/Domain/Missing_Indexable_Count_Test.php +++ b/tests/Unit/Analytics/Domain/Missing_Indexable_Count_Test.php @@ -44,7 +44,7 @@ public function test_missing_indexable_count_to_array(): void { 'indexable_type' => 'indexable_type', 'count' => 0, ], - $this->sut->to_array() + $this->sut->to_array(), ); } diff --git a/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Bucket_Test.php b/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Bucket_Test.php index 1e64251cf46..f947146eb5c 100644 --- a/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Bucket_Test.php +++ b/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Bucket_Test.php @@ -53,7 +53,7 @@ public function test_missing_indexable_bucket(): void { 'cleanup_name' => 'cleanup_name', ], ], - $this->sut->to_array() + $this->sut->to_array(), ); } } diff --git a/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Count_Test.php b/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Count_Test.php index 096144984f6..9026f4f4f0a 100644 --- a/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Count_Test.php +++ b/tests/Unit/Analytics/Domain/To_Be_Cleaned_Indexable_Count_Test.php @@ -44,7 +44,7 @@ public function test_to_be_cleaned_count_to_array(): void { 'count' => 0, 'cleanup_name' => 'cleanup_name', ], - $this->sut->to_array() + $this->sut->to_array(), ); } diff --git a/tests/Unit/Analytics/User_Interface/Last_Completed_Indexation_Integration_Test.php b/tests/Unit/Analytics/User_Interface/Last_Completed_Indexation_Integration_Test.php index 54058f66c49..6ddd095aaed 100644 --- a/tests/Unit/Analytics/User_Interface/Last_Completed_Indexation_Integration_Test.php +++ b/tests/Unit/Analytics/User_Interface/Last_Completed_Indexation_Integration_Test.php @@ -97,6 +97,6 @@ public function test_maybe_set_indexables_unindexed_calculated_with_many_indexab ->with( 'update_option_wpseo', [ 'WPSEO_Utils', 'clear_cache' ] ) ->never(); - $this->sut->maybe_set_indexables_unindexed_calculated( 'name', 100000 ); + $this->sut->maybe_set_indexables_unindexed_calculated( 'name', 100_000 ); } } diff --git a/tests/Unit/Builders/Indexable_Author_Builder_Test.php b/tests/Unit/Builders/Indexable_Author_Builder_Test.php index df0f97b91d9..130fbcf16a9 100644 --- a/tests/Unit/Builders/Indexable_Author_Builder_Test.php +++ b/tests/Unit/Builders/Indexable_Author_Builder_Test.php @@ -207,14 +207,14 @@ public function test_build() { AND p.%i = '' AND p.%i = %d ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $this->indexable_mock->orm->expects( 'set' )->with( 'object_published_at', '1234-12-12 00:00:00' ); @@ -293,14 +293,14 @@ public function test_build_when_user_is_explicitly_included_by_filter() { AND p.%i = '' AND p.%i = %d ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $this->indexable_mock->orm->expects( 'set' )->with( 'object_published_at', '1234-12-12 00:00:00' ); @@ -372,14 +372,14 @@ public function test_build_without_alternative_image() { AND p.%i = '' AND p.%i = %d ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $this->indexable_mock->orm->expects( 'set' )->with( 'object_published_at', '1234-12-12 00:00:00' ); @@ -392,7 +392,7 @@ public function test_build_without_alternative_image() { [ 'size' => 500, 'scheme' => 'https', - ] + ], ) ->andReturn( '' ); @@ -463,14 +463,14 @@ public function test_build_with_undefined_author_meta() { AND p.%i = '' AND p.%i = %d ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_author', 1 ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $this->indexable_mock->orm->expects( 'set' )->with( 'object_published_at', '1234-12-12 00:00:00' ); diff --git a/tests/Unit/Builders/Indexable_Builder/Abstract_Indexable_Builder_TestCase.php b/tests/Unit/Builders/Indexable_Builder/Abstract_Indexable_Builder_TestCase.php index c96849448d8..910fdc0a592 100644 --- a/tests/Unit/Builders/Indexable_Builder/Abstract_Indexable_Builder_TestCase.php +++ b/tests/Unit/Builders/Indexable_Builder/Abstract_Indexable_Builder_TestCase.php @@ -177,7 +177,7 @@ protected function set_up() { $this->primary_term_builder, $this->indexable_helper, $this->version_manager, - $this->link_builder + $this->link_builder, ); $this->instance->set_indexable_repository( $this->indexable_repository ); diff --git a/tests/Unit/Builders/Indexable_Builder/Build_Test.php b/tests/Unit/Builders/Indexable_Builder/Build_Test.php index 91e5ee6b4a3..7c266764396 100644 --- a/tests/Unit/Builders/Indexable_Builder/Build_Test.php +++ b/tests/Unit/Builders/Indexable_Builder/Build_Test.php @@ -166,7 +166,7 @@ static function ( $indexable ) { $indexable->version = 2; return $indexable; - } + }, ); $this->expect_save_indexable( $this->indexable ); @@ -254,7 +254,7 @@ static function ( $indexable ) { $indexable->version = 2; return $indexable; - } + }, ); $expected_indexable = clone $empty_indexable; @@ -301,7 +301,7 @@ static function ( $indexable ) { $indexable->version = 2; return $indexable; - } + }, ); $expected_indexable = clone $this->indexable; diff --git a/tests/Unit/Builders/Indexable_Builder/Ensure_Indexable_Test.php b/tests/Unit/Builders/Indexable_Builder/Ensure_Indexable_Test.php index b7956215b9a..58d84fc03ae 100644 --- a/tests/Unit/Builders/Indexable_Builder/Ensure_Indexable_Test.php +++ b/tests/Unit/Builders/Indexable_Builder/Ensure_Indexable_Test.php @@ -41,7 +41,7 @@ protected function set_up() { $this->primary_term_builder, $this->indexable_helper, $this->version_manager, - $this->link_builder + $this->link_builder, ); $this->instance->set_indexable_repository( $this->indexable_repository ); diff --git a/tests/Unit/Builders/Indexable_Builder/Is_Type_With_No_Id_Test.php b/tests/Unit/Builders/Indexable_Builder/Is_Type_With_No_Id_Test.php index a3e140f9c97..abf399748a6 100644 --- a/tests/Unit/Builders/Indexable_Builder/Is_Type_With_No_Id_Test.php +++ b/tests/Unit/Builders/Indexable_Builder/Is_Type_With_No_Id_Test.php @@ -34,7 +34,7 @@ protected function set_up() { $this->primary_term_builder, $this->indexable_helper, $this->version_manager, - $this->link_builder + $this->link_builder, ); $this->instance->set_indexable_repository( $this->indexable_repository ); diff --git a/tests/Unit/Builders/Indexable_Builder/Maybe_Build_Author_Indexable_Test.php b/tests/Unit/Builders/Indexable_Builder/Maybe_Build_Author_Indexable_Test.php index 9e329f37219..2c03814459e 100644 --- a/tests/Unit/Builders/Indexable_Builder/Maybe_Build_Author_Indexable_Test.php +++ b/tests/Unit/Builders/Indexable_Builder/Maybe_Build_Author_Indexable_Test.php @@ -37,7 +37,7 @@ protected function set_up() { $this->primary_term_builder, $this->indexable_helper, $this->version_manager, - $this->link_builder + $this->link_builder, ); $this->instance->set_indexable_repository( $this->indexable_repository ); diff --git a/tests/Unit/Builders/Indexable_Builder/Save_Indexable_Test.php b/tests/Unit/Builders/Indexable_Builder/Save_Indexable_Test.php index aff8a1f6c5c..77d6c4dfdc0 100644 --- a/tests/Unit/Builders/Indexable_Builder/Save_Indexable_Test.php +++ b/tests/Unit/Builders/Indexable_Builder/Save_Indexable_Test.php @@ -35,7 +35,7 @@ protected function set_up() { $this->primary_term_builder, $this->indexable_helper, $this->version_manager, - $this->link_builder + $this->link_builder, ); $this->instance->set_indexable_repository( $this->indexable_repository ); diff --git a/tests/Unit/Builders/Indexable_Builder/Set_Indexable_Repository_Test.php b/tests/Unit/Builders/Indexable_Builder/Set_Indexable_Repository_Test.php index fb2ea3a1f25..648f8c3d02c 100644 --- a/tests/Unit/Builders/Indexable_Builder/Set_Indexable_Repository_Test.php +++ b/tests/Unit/Builders/Indexable_Builder/Set_Indexable_Repository_Test.php @@ -37,62 +37,62 @@ public function test_construct() { $this->assertInstanceOf( Indexable_Author_Builder::class, $this->getPropertyValue( $this->instance, 'author_builder' ), - 'Author builder should be of class Indexable_Author_Builder.' + 'Author builder should be of class Indexable_Author_Builder.', ); $this->assertInstanceOf( Indexable_Post_Builder::class, $this->getPropertyValue( $this->instance, 'post_builder' ), - 'Post builder should be of class Indexable_Post_Builder.' + 'Post builder should be of class Indexable_Post_Builder.', ); $this->assertInstanceOf( Indexable_Term_Builder::class, $this->getPropertyValue( $this->instance, 'term_builder' ), - 'Term builder should be of class Indexable_Term_Builder.' + 'Term builder should be of class Indexable_Term_Builder.', ); $this->assertInstanceOf( Indexable_Home_Page_Builder::class, $this->getPropertyValue( $this->instance, 'home_page_builder' ), - 'Home page builder should be of class Indexable_Home_Page_Builder.' + 'Home page builder should be of class Indexable_Home_Page_Builder.', ); $this->assertInstanceOf( Indexable_Post_Type_Archive_Builder::class, $this->getPropertyValue( $this->instance, 'post_type_archive_builder' ), - 'Post type archive builder should be of class Indexable_Post_Type_Archive_Builder.' + 'Post type archive builder should be of class Indexable_Post_Type_Archive_Builder.', ); $this->assertInstanceOf( Indexable_Date_Archive_Builder::class, $this->getPropertyValue( $this->instance, 'date_archive_builder' ), - 'Date archive builder should be of class Indexable_Date_Archive_Builder.' + 'Date archive builder should be of class Indexable_Date_Archive_Builder.', ); $this->assertInstanceOf( Indexable_System_Page_Builder::class, $this->getPropertyValue( $this->instance, 'system_page_builder' ), - 'System page builder should be of class Indexable_System_Page_Builder.' + 'System page builder should be of class Indexable_System_Page_Builder.', ); $this->assertInstanceOf( Indexable_Hierarchy_Builder::class, $this->getPropertyValue( $this->instance, 'hierarchy_builder' ), - 'Hierarchy builder should be of class Indexable_Hierarchy_Builder.' + 'Hierarchy builder should be of class Indexable_Hierarchy_Builder.', ); $this->assertInstanceOf( Primary_Term_Builder::class, $this->getPropertyValue( $this->instance, 'primary_term_builder' ), - 'Primary term builder should be of class Primary_Term_Builder.' + 'Primary term builder should be of class Primary_Term_Builder.', ); $this->assertInstanceOf( Indexable_Helper::class, $this->getPropertyValue( $this->instance, 'indexable_helper' ), - 'Indexable helper should be of class Indexable_Helper.' + 'Indexable helper should be of class Indexable_Helper.', ); $this->assertInstanceOf( Indexable_Version_Manager::class, $this->getPropertyValue( $this->instance, 'version_manager' ), - 'Version manager should be of class Indexable_Version_Manager.' + 'Version manager should be of class Indexable_Version_Manager.', ); $this->assertInstanceOf( Indexable_Link_Builder::class, $this->getPropertyValue( $this->instance, 'link_builder' ), - 'Link builder should be of class Indexable_Link_Builder.' + 'Link builder should be of class Indexable_Link_Builder.', ); } @@ -109,7 +109,7 @@ public function test_set_indexable_repository() { $this->assertSame( $indexable_repository, $this->getPropertyValue( $this->instance, 'indexable_repository' ), - 'Indexable repository should be set.' + 'Indexable repository should be set.', ); } } diff --git a/tests/Unit/Builders/Indexable_Hierarchy_Builder_Test.php b/tests/Unit/Builders/Indexable_Hierarchy_Builder_Test.php index 3e838e9bac4..f244e7b3bf7 100644 --- a/tests/Unit/Builders/Indexable_Hierarchy_Builder_Test.php +++ b/tests/Unit/Builders/Indexable_Hierarchy_Builder_Test.php @@ -98,7 +98,7 @@ protected function set_up() { $this->primary_term_repository, $this->options, $this->post, - $this->indexable_helper + $this->indexable_helper, ); $this->instance->set_indexable_repository( $this->indexable_repository ); } @@ -131,7 +131,7 @@ public function test_no_parents() { (object) [ 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->indexable_hierarchy_repository->expects( 'add_ancestor' )->with( 1, 0, 0 ); @@ -172,7 +172,7 @@ public function test_no_parents_and_has_ancestors_set_to_false() { (object) [ 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->indexable_hierarchy_repository->expects( 'add_ancestor' )->with( 1, 0, 0 ); @@ -247,7 +247,7 @@ public function test_post_parents() { (object) [ 'post_parent' => 2, 'post_type' => 'post', - ] + ], ); $this->post->expects( 'get_post' ) ->twice() @@ -256,7 +256,7 @@ public function test_post_parents() { (object) [ 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $actual = $this->instance->build( $indexable ); @@ -309,7 +309,7 @@ public function test_post_parent_with_no_indexable_id_set() { (object) [ 'post_parent' => 2, 'post_type' => 'post', - ] + ], ); $this->post ->expects( 'get_post' ) @@ -319,7 +319,7 @@ public function test_post_parent_with_no_indexable_id_set() { (object) [ 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $actual = $this->instance->build( $indexable ); @@ -363,7 +363,7 @@ public function test_post_parents_with_an_unindexed_ancestor() { (object) [ 'post_parent' => 2, 'post_type' => 'post', - ] + ], ); $this->post @@ -374,7 +374,7 @@ public function test_post_parents_with_an_unindexed_ancestor() { (object) [ 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->indexable_hierarchy_repository->expects( 'add_ancestor' )->with( 1, 0, 0 ); @@ -423,7 +423,7 @@ public function test_post_parents_with_parent_already_added() { (object) [ 'post_parent' => 2, 'post_type' => 'post', - ] + ], ); $this->post @@ -434,7 +434,7 @@ public function test_post_parents_with_parent_already_added() { (object) [ 'post_parent' => 2, 'post_type' => 'post', - ] + ], ); $actual = $this->instance->build( $indexable ); @@ -475,7 +475,7 @@ public function test_post_parents_having_the_parent_is_the_main_object() { (object) [ 'post_parent' => 2, 'post_type' => 'post', - ] + ], ); $this->post @@ -486,7 +486,7 @@ public function test_post_parents_having_the_parent_is_the_main_object() { (object) [ 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->indexable_hierarchy_repository->expects( 'add_ancestor' )->with( 1, 0, 0 ); @@ -536,7 +536,7 @@ public function test_primary_term_parents() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); $this->indexable_hierarchy_repository->expects( 'clear_ancestors' )->with( 1 )->andReturnTrue(); @@ -556,7 +556,7 @@ public function test_primary_term_parents() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $actual = $this->instance->build( $indexable ); @@ -595,7 +595,7 @@ public function test_primary_term_parents_and_term_is_unindexed() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); $this->indexable_hierarchy_repository @@ -627,7 +627,7 @@ public function test_primary_term_parents_and_term_is_unindexed() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->indexable_hierarchy_repository->expects( 'add_ancestor' )->with( 1, 0, 0 ); @@ -688,7 +688,7 @@ public function test_many_primary_term_parents() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 3, - ] + ], ); Monkey\Functions\expect( 'get_term' ) ->once() @@ -698,7 +698,7 @@ public function test_many_primary_term_parents() { 'term_id' => 3, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); $this->indexable_helper->expects( 'should_index_indexable' )->with( $indexable )->andReturnTrue(); $this->indexable_hierarchy_repository->expects( 'clear_ancestors' )->with( 1 )->andReturnTrue(); @@ -720,7 +720,7 @@ public function test_many_primary_term_parents() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $actual = $this->instance->build( $indexable ); @@ -767,7 +767,7 @@ public function test_term_parent() { 'taxonomy' => 'tag', 'parent' => 0, ], - ] + ], ); Monkey\Functions\expect( 'get_term' ) ->with( 2 ) @@ -776,7 +776,7 @@ public function test_term_parent() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); Monkey\Functions\expect( 'get_post_meta' )->with( 1, WPSEO_Meta::$meta_prefix . 'primary_term', true )->andReturn( '' ); @@ -796,7 +796,7 @@ public function test_term_parent() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $actual = $this->instance->build( $indexable ); @@ -832,7 +832,7 @@ public function test_term_parent_where_terms_not_array() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); Monkey\Functions\expect( 'get_post_meta' )->with( 1, WPSEO_Meta::$meta_prefix . 'primary_term', true )->andReturn( '' ); $this->indexable_helper->expects( 'should_index_indexable' )->with( $indexable )->andReturnTrue(); @@ -849,7 +849,7 @@ public function test_term_parent_where_terms_not_array() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->indexable_hierarchy_repository->expects( 'add_ancestor' )->with( 1, 0, 0 ); @@ -887,7 +887,7 @@ public function test_term_parent_where_terms_empty() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); Monkey\Functions\expect( 'get_post_meta' )->with( 1, WPSEO_Meta::$meta_prefix . 'primary_term', true )->andReturn( '' ); @@ -904,7 +904,7 @@ public function test_term_parent_where_terms_empty() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->indexable_hierarchy_repository->expects( 'add_ancestor' )->with( 1, 0, 0 ); @@ -965,7 +965,7 @@ public function test_deepest_term_parent() { 'taxonomy' => 'tag', 'parent' => 4, ], - ] + ], ); Monkey\Functions\expect( 'get_term' ) ->once() @@ -975,7 +975,7 @@ public function test_deepest_term_parent() { 'term_id' => 3, 'taxonomy' => 'tag', 'parent' => 4, - ] + ], ); Monkey\Functions\expect( 'get_term' ) ->twice() @@ -985,7 +985,7 @@ public function test_deepest_term_parent() { 'term_id' => 4, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); Monkey\Functions\expect( 'get_post_meta' )->with( 1, WPSEO_Meta::$meta_prefix . 'primary_term', true )->andReturn( '' ); $this->indexable_helper->expects( 'should_index_indexable' )->with( $indexable )->andReturnTrue(); @@ -1008,7 +1008,7 @@ public function test_deepest_term_parent() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $actual = $this->instance->build( $indexable ); @@ -1050,7 +1050,7 @@ public function test_term() { 'term_id' => 1, 'taxonomy' => 'tag', 'parent' => 2, - ] + ], ); Monkey\Functions\expect( 'get_term' ) ->once() @@ -1060,7 +1060,7 @@ public function test_term() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); $this->indexable_hierarchy_repository->expects( 'clear_ancestors' )->with( 1 )->andReturnTrue(); @@ -1099,7 +1099,7 @@ public function test_term_with_ancestor_not_indexed() { 'term_id' => 1, 'taxonomy' => 'tag', 'parent' => 2, - ] + ], ); Monkey\Functions\expect( 'get_term' ) @@ -1110,7 +1110,7 @@ public function test_term_with_ancestor_not_indexed() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); $this->indexable_hierarchy_repository @@ -1154,7 +1154,7 @@ public function test_term_with_ancestor_is_the_main_object() { 'term_id' => 1, 'taxonomy' => 'tag', 'parent' => 2, - ] + ], ); Monkey\Functions\expect( 'get_term' ) @@ -1165,7 +1165,7 @@ public function test_term_with_ancestor_is_the_main_object() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); $this->indexable_hierarchy_repository @@ -1211,7 +1211,7 @@ public function test_term_with_ancestor_is_already_added() { 'term_id' => 1, 'taxonomy' => 'tag', 'parent' => 2, - ] + ], ); Monkey\Functions\expect( 'get_term' ) @@ -1222,7 +1222,7 @@ public function test_term_with_ancestor_is_already_added() { 'term_id' => 2, 'taxonomy' => 'tag', 'parent' => 3, - ] + ], ); Monkey\Functions\expect( 'get_term' ) @@ -1233,7 +1233,7 @@ public function test_term_with_ancestor_is_already_added() { 'term_id' => 3, 'taxonomy' => 'tag', 'parent' => 0, - ] + ], ); $this->indexable_hierarchy_repository @@ -1305,7 +1305,7 @@ public function test_primary_term_parents_with_no_primary_term_set() { 'ID' => 1, 'post_parent' => 0, 'post_type' => 'post', - ] + ], ); $this->options @@ -1334,7 +1334,7 @@ public function test_primary_term_parents_with_no_primary_term_set() { 'parent' => 0, 'term_order' => 1, ], - ] + ], ); Monkey\Functions\expect( 'get_term' ) @@ -1345,7 +1345,7 @@ public function test_primary_term_parents_with_no_primary_term_set() { 'taxonomy' => 'tag', 'parent' => 0, 'term_order' => 1, - ] + ], ); Monkey\Functions\expect( 'get_post_meta' )->with( 1, WPSEO_Meta::$meta_prefix . 'primary_term', true )->andReturn( '' ); diff --git a/tests/Unit/Builders/Indexable_Home_Page_Builder_Test.php b/tests/Unit/Builders/Indexable_Home_Page_Builder_Test.php index 4cb83eb2b0f..4f0f3e867b7 100644 --- a/tests/Unit/Builders/Indexable_Home_Page_Builder_Test.php +++ b/tests/Unit/Builders/Indexable_Home_Page_Builder_Test.php @@ -56,7 +56,7 @@ final class Indexable_Home_Page_Builder_Test extends TestCase { 'size' => 'full', 'id' => 6, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image\/jpeg', ]; @@ -188,7 +188,7 @@ protected function set_up() { $this->options_mock, $this->url_mock, $this->versions, - $this->post_helper + $this->post_helper, ); $this->instance->set_social_image_helpers( $this->image_mock, $this->open_graph_image_mock, $this->twitter_image_mock ); } @@ -225,13 +225,13 @@ public function test_build() { AND p.%i = '' AND p.%i = 'post' ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type' ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type' ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $this->indexable_mock->orm->expects( 'set' )->with( 'object_published_at', '1234-12-12 00:00:00' ); @@ -273,13 +273,13 @@ public function test_build_with_fallback_description() { AND p.%i = '' AND p.%i = 'post' ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type' ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type' ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $this->indexable_mock->orm->expects( 'set' )->with( 'object_published_at', '1234-12-12 00:00:00' ); @@ -320,13 +320,13 @@ public function test_build_open_graph_image_meta_data() { AND p.%i = '' AND p.%i = 'post' ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type' ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type' ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $this->indexable_mock->orm->expects( 'set' )->with( 'object_published_at', '1234-12-12 00:00:00' ); diff --git a/tests/Unit/Builders/Indexable_Link_Builder/Abstract_Indexable_Link_Builder_TestCase.php b/tests/Unit/Builders/Indexable_Link_Builder/Abstract_Indexable_Link_Builder_TestCase.php index 09ea9828d44..21e07833c85 100644 --- a/tests/Unit/Builders/Indexable_Link_Builder/Abstract_Indexable_Link_Builder_TestCase.php +++ b/tests/Unit/Builders/Indexable_Link_Builder/Abstract_Indexable_Link_Builder_TestCase.php @@ -115,7 +115,7 @@ protected function set_up() { $this->post_helper, $this->options_helper, $this->indexable_helper, - $this->image_content_extractor + $this->image_content_extractor, ); $this->instance->set_dependencies( $this->indexable_repository, $this->image_helper ); @@ -125,9 +125,9 @@ static function ( $haystack, $prop ) { static function ( $e ) use ( $prop ) { return $e->{$prop}; }, - $haystack + $haystack, ); - } + }, ); $this->image_url = 'http://basic.wordpress.test/wp-content/uploads/2022/11/WordPress8.jpg?quality=90&grain=0.5'; @@ -200,7 +200,7 @@ public function expect_seo_links_repository_query_create( $indexable, $seo_link 'type' => SEO_Links::TYPE_INTERNAL_IMAGE, 'indexable_id' => $indexable->id, 'post_id' => $indexable->object_id, - ] + ], )->andReturn( $seo_link ); } } diff --git a/tests/Unit/Builders/Indexable_Link_Builder/Build_Test.php b/tests/Unit/Builders/Indexable_Link_Builder/Build_Test.php index cb653e42dde..cab197c3c73 100644 --- a/tests/Unit/Builders/Indexable_Link_Builder/Build_Test.php +++ b/tests/Unit/Builders/Indexable_Link_Builder/Build_Test.php @@ -181,7 +181,7 @@ public function test_build( $content, $link_type, $is_image, $images ) { 'type' => $link_type, 'indexable_id' => $indexable->id, 'post_id' => $indexable->object_id, - ] + ], )->andReturn( $new_seo_link ); $query_mock->expects( 'create' )->once()->with( [ @@ -189,7 +189,7 @@ public function test_build( $content, $link_type, $is_image, $images ) { 'type' => $link_type, 'indexable_id' => $indexable->id, 'post_id' => $indexable->object_id, - ] + ], )->andReturn( $existing_seo_link ); $old_seo_link = new SEO_Links_Mock(); @@ -210,7 +210,7 @@ public function test_build( $content, $link_type, $is_image, $images ) { 'target_indexable_id' => 3, 'incoming' => 0, ], - ] + ], ); $this->indexable_repository->expects( 'update_incoming_link_count' )->once()->with( 3, 0 ); @@ -301,7 +301,7 @@ public function test_build_target_indexable_does_not_exist() { 'type' => $link_type, 'indexable_id' => $indexable->id, 'post_id' => $indexable->object_id, - ] + ], )->andReturn( $seo_link ); $old_seo_link = new SEO_Links_Mock(); @@ -324,7 +324,7 @@ public function test_build_target_indexable_does_not_exist() { 'target_indexable_id' => 3, 'incoming' => 0, ], - ] + ], ); $this->indexable_repository->expects( 'update_incoming_link_count' )->once()->with( 2, 0 ); $this->indexable_repository->expects( 'update_incoming_link_count' )->once()->with( 3, 0 ); diff --git a/tests/Unit/Builders/Indexable_Link_Builder/Create_Internal_Link_Test.php b/tests/Unit/Builders/Indexable_Link_Builder/Create_Internal_Link_Test.php index 50b3c21d9a2..6b502f39308 100644 --- a/tests/Unit/Builders/Indexable_Link_Builder/Create_Internal_Link_Test.php +++ b/tests/Unit/Builders/Indexable_Link_Builder/Create_Internal_Link_Test.php @@ -56,7 +56,7 @@ public function test_build_create_internal_link() { 'scheme' => 'http', 'host' => 'basic.wordpress.test', ], - ] + ], ); // Executed in build->create_links->create_internal_link. @@ -134,7 +134,7 @@ public function test_build_create_internal_link_disable_attachment_true_file_doe 'host' => 'basic.wordpress.test', ], 'get_attached_file' => 'http://basic.wordpress.test/wp-content/uploads/2022/11/WordPress8.jpg', - ] + ], ); // Executed in build->create_links->create_internal_link. @@ -212,7 +212,7 @@ public function test_build_create_internal_link_disable_attachment_true_file_exi ], 'get_attached_file' => 'http://basic.wordpress.test/wp-content/uploads/2022/11/WordPress8.jpg', 'wp_get_attachment_image_src' => [ '55', '200', '300' ], - ] + ], ); // Executed in build->create_links->create_internal_link. @@ -280,7 +280,7 @@ public function test_build_create_internal_link_disable_attachment_true_file_not // Executed in build->create_links->create_internal_link. 'wp_get_attachment_image_src' => [ '55', '200', '300' ], - ] + ], ); // Executed in build->create_links->create_internal_link. @@ -366,7 +366,7 @@ public function test_build_create_internal_link_disable_attachment_true_get_atta // Executed in build->create_links->create_internal_link->WPSEO_Image_Utils::get_attachment_by_url->attachment_url_to_postid. 'wp_cache_get' => 108, - ] + ], ); // Executed in build->create_links->create_internal_link. diff --git a/tests/Unit/Builders/Indexable_Link_Builder/Delete_Test.php b/tests/Unit/Builders/Indexable_Link_Builder/Delete_Test.php index bf7f5b86238..4785e1c3efc 100644 --- a/tests/Unit/Builders/Indexable_Link_Builder/Delete_Test.php +++ b/tests/Unit/Builders/Indexable_Link_Builder/Delete_Test.php @@ -77,7 +77,7 @@ public function test_delete_and_update_incoming_links_for_related_indexables() { 'target_indexable_id' => 3, 'incoming' => 7, ], - ] + ], ); $this->indexable_repository diff --git a/tests/Unit/Builders/Indexable_Link_Builder/Get_Permalink_Test.php b/tests/Unit/Builders/Indexable_Link_Builder/Get_Permalink_Test.php index a20f83f92ce..37af6958b4f 100644 --- a/tests/Unit/Builders/Indexable_Link_Builder/Get_Permalink_Test.php +++ b/tests/Unit/Builders/Indexable_Link_Builder/Get_Permalink_Test.php @@ -27,7 +27,7 @@ protected function set_up() { $this->post_helper, $this->options_helper, $this->indexable_helper, - $this->image_content_extractor + $this->image_content_extractor, ); $this->instance->set_dependencies( $this->indexable_repository, $this->image_helper ); diff --git a/tests/Unit/Builders/Indexable_Link_Builder/Update_Incoming_Links_For_Related_Test.php b/tests/Unit/Builders/Indexable_Link_Builder/Update_Incoming_Links_For_Related_Test.php index 1958d477cf3..bf0eb7c1f57 100644 --- a/tests/Unit/Builders/Indexable_Link_Builder/Update_Incoming_Links_For_Related_Test.php +++ b/tests/Unit/Builders/Indexable_Link_Builder/Update_Incoming_Links_For_Related_Test.php @@ -29,7 +29,7 @@ protected function set_up() { $this->post_helper, $this->options_helper, $this->indexable_helper, - $this->image_content_extractor + $this->image_content_extractor, ); $this->instance->set_dependencies( $this->indexable_repository, $this->image_helper ); diff --git a/tests/Unit/Builders/Indexable_Post_Builder_Test.php b/tests/Unit/Builders/Indexable_Post_Builder_Test.php index 3432faeff31..285b2406234 100644 --- a/tests/Unit/Builders/Indexable_Post_Builder_Test.php +++ b/tests/Unit/Builders/Indexable_Post_Builder_Test.php @@ -120,14 +120,14 @@ protected function set_up() { $this->post_type_helper, new Indexable_Builder_Versions(), new Meta_Helper(), - $this->permalink_helper + $this->permalink_helper, ); $this->instance->set_indexable_repository( $this->indexable_repository ); $this->instance->set_social_image_helpers( $this->image, $this->open_graph_image, - $this->twitter_image + $this->twitter_image, ); } @@ -212,11 +212,11 @@ protected function open_graph_image_set_by_user( $image_meta ) { public function test_constructor() { $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); $this->assertInstanceOf( Post_Helper::class, - $this->getPropertyValue( $this->instance, 'post_helper' ) + $this->getPropertyValue( $this->instance, 'post_helper' ), ); } @@ -232,7 +232,7 @@ public function test_set_indexable_repository() { $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); } @@ -270,7 +270,7 @@ public function test_build( $postmeta, $expected_result ) { 'post_parent' => '0', 'post_date_gmt' => '1234-12-12 00:00:00', 'post_modified_gmt' => '1234-12-12 00:00:00', - ] + ], ); $this->post_type_helper @@ -319,7 +319,7 @@ public function test_build( $postmeta, $expected_result ) { 'twitter_image' => null, 'twitter_image_id' => null, 'twitter_image_source' => null, - ] + ], ); $image_meta = [ @@ -330,7 +330,7 @@ public function test_build( $postmeta, $expected_result ) { 'size' => 'full', 'id' => 13, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; @@ -571,7 +571,7 @@ public function test_find_alternative_image_from_gallery() { 'size' => 'full', 'id' => 13, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; @@ -625,7 +625,7 @@ public function test_find_alternative_image_from_post_content() { 'size' => 'full', 'id' => 13, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; @@ -1016,7 +1016,7 @@ public function test_build_post_type_excluded() { ->andReturn( (object) [ 'post_type' => 'excluded_post_type', - ] + ], ); $this->post_type_helper->expects( 'is_excluded' ) diff --git a/tests/Unit/Builders/Indexable_Post_Type_Archive_Builder_Test.php b/tests/Unit/Builders/Indexable_Post_Type_Archive_Builder_Test.php index 2552a0449dc..a1920cb73f3 100644 --- a/tests/Unit/Builders/Indexable_Post_Type_Archive_Builder_Test.php +++ b/tests/Unit/Builders/Indexable_Post_Type_Archive_Builder_Test.php @@ -79,13 +79,13 @@ public function test_build() { AND p.%i = '' AND p.%i = %s ", - [ 'post_modified_gmt', 'post_date_gmt', $wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type', 'my-post-type' ] + [ 'post_modified_gmt', 'post_date_gmt', $wpdb->posts, 'post_status', 'publish', 'post_password', 'post_type', 'my-post-type' ], )->andReturn( 'PREPARED_QUERY' ); $wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $indexable_mock = Mockery::mock( Indexable::class ); diff --git a/tests/Unit/Builders/Indexable_Social_Image_Trait_Test.php b/tests/Unit/Builders/Indexable_Social_Image_Trait_Test.php index 20ed3784768..ee43d8b5746 100644 --- a/tests/Unit/Builders/Indexable_Social_Image_Trait_Test.php +++ b/tests/Unit/Builders/Indexable_Social_Image_Trait_Test.php @@ -86,15 +86,15 @@ public function test_set_social_image_helpers() { self::assertInstanceOf( Twitter\Image_Helper::class, - $this->getPropertyValue( $this->instance, 'twitter_image' ) + $this->getPropertyValue( $this->instance, 'twitter_image' ), ); self::assertInstanceOf( Open_Graph\Image_Helper::class, - $this->getPropertyValue( $this->instance, 'open_graph_image' ) + $this->getPropertyValue( $this->instance, 'open_graph_image' ), ); self::assertInstanceOf( Image_Helper::class, - $this->getPropertyValue( $this->instance, 'image' ) + $this->getPropertyValue( $this->instance, 'image' ), ); } @@ -142,7 +142,7 @@ public function test_handle_social_images_when_images_are_set_by_user() { 'size' => 'full', 'id' => 13, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; @@ -194,7 +194,7 @@ public function test_handle_social_images_when_twitter_image_is_not_set_by_user( 'size' => 'full', 'id' => 13, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; @@ -313,7 +313,7 @@ public function test_handle_social_images_when_twitter_image_id_is_not_set_by_us 'size' => 'full', 'id' => 13, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; diff --git a/tests/Unit/Builders/Indexable_Term_Builder_Test.php b/tests/Unit/Builders/Indexable_Term_Builder_Test.php index 49550b15b00..faaf8b9e0e1 100644 --- a/tests/Unit/Builders/Indexable_Term_Builder_Test.php +++ b/tests/Unit/Builders/Indexable_Term_Builder_Test.php @@ -120,7 +120,7 @@ protected function set_up() { $this->instance = new Indexable_Term_Builder_Double( $this->taxonomy, $this->versions, - $this->post_helper + $this->post_helper, ); $this->image = Mockery::mock( Image_Helper::class ); @@ -130,7 +130,7 @@ protected function set_up() { $this->instance->set_social_image_helpers( $this->image, $this->open_graph_image, - $this->twitter_image + $this->twitter_image, ); } @@ -210,7 +210,7 @@ protected function open_graph_image_set_by_user( $indexable_mock, $image_meta ) public function test_constructor() { $this->assertInstanceOf( Indexable_Term_Builder::class, - $this->instance + $this->instance, ); } @@ -260,7 +260,7 @@ public function test_build() { 'wpseo_twitter-image' => 'twitter_image', 'wpseo_twitter-image-id' => 'twitter_image_id', 'wpseo_twitter-description' => 'twitter_description', - ] + ], ); $this->post_helper->expects( 'get_public_post_statuses' )->once()->andReturn( [ 'publish' ] ); @@ -279,14 +279,14 @@ public function test_build() { WHERE p.%i IN (%s) AND p.%i = '' ", - [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, $this->wpdb->term_relationships, 'object_id', 'ID', $this->wpdb->term_taxonomy, 'term_taxonomy_id', 'term_taxonomy_id', 'taxonomy', 'category', 'term_id', 1, 'post_status', 'publish', 'post_password' ] + [ 'post_modified_gmt', 'post_date_gmt', $this->wpdb->posts, $this->wpdb->term_relationships, 'object_id', 'ID', $this->wpdb->term_taxonomy, 'term_taxonomy_id', 'term_taxonomy_id', 'taxonomy', 'category', 'term_id', 1, 'post_status', 'publish', 'post_password' ], )->andReturn( 'PREPARED_QUERY' ); $this->wpdb->expects( 'get_row' )->once()->with( 'PREPARED_QUERY' )->andReturn( (object) [ 'last_modified' => '1234-12-12 00:00:00', 'published_at' => '1234-12-12 00:00:00', - ] + ], ); $indexable_mock = Mockery::mock( Indexable::class ); @@ -335,7 +335,7 @@ public function test_build() { 'twitter_image' => null, 'twitter_image_id' => null, 'twitter_image_source' => null, - ] + ], ); $image_meta = [ @@ -346,7 +346,7 @@ public function test_build() { 'size' => 'full', 'id' => 13, 'alt' => '', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; diff --git a/tests/Unit/Builders/Primary_Term_Builder_Test.php b/tests/Unit/Builders/Primary_Term_Builder_Test.php index fb11f359791..b5764e48816 100644 --- a/tests/Unit/Builders/Primary_Term_Builder_Test.php +++ b/tests/Unit/Builders/Primary_Term_Builder_Test.php @@ -78,7 +78,7 @@ protected function set_up() { $this->indexable_helper, $this->primary_term, $this->meta, - ] + ], ) ->shouldAllowMockingProtectedMethods() ->makePartial(); @@ -96,27 +96,27 @@ public function test_successfully_creates_primary_term_builder() { $this->repository, $this->indexable_helper, $this->primary_term, - $this->meta + $this->meta, ); $this->assertInstanceOf( Primary_Term_Repository::class, - $this->getPropertyValue( $primary_term_builder, 'repository' ) + $this->getPropertyValue( $primary_term_builder, 'repository' ), ); $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $primary_term_builder, 'indexable_helper' ) + $this->getPropertyValue( $primary_term_builder, 'indexable_helper' ), ); $this->assertInstanceOf( Primary_Term_Helper::class, - $this->getPropertyValue( $primary_term_builder, 'primary_term' ) + $this->getPropertyValue( $primary_term_builder, 'primary_term' ), ); $this->assertInstanceOf( Meta_Helper::class, - $this->getPropertyValue( $primary_term_builder, 'meta' ) + $this->getPropertyValue( $primary_term_builder, 'meta' ), ); } @@ -143,7 +143,7 @@ public function test_build() { 'name' => 'tag', 'hierarchical' => true, ], - ] + ], ); $this->instance diff --git a/tests/Unit/Commands/Index_Command_Test.php b/tests/Unit/Commands/Index_Command_Test.php index 55389176df2..87b7ae4b501 100644 --- a/tests/Unit/Commands/Index_Command_Test.php +++ b/tests/Unit/Commands/Index_Command_Test.php @@ -127,7 +127,7 @@ protected function set_up() { $this->prepare_indexing_action, $this->post_link_indexation_action, $this->term_link_indexation_action, - $this->indexable_helper + $this->indexable_helper, ); $this->stubTranslationFunctions(); @@ -143,23 +143,23 @@ protected function set_up() { public function test_construct() { self::assertInstanceOf( Indexable_Post_Indexation_Action::class, - self::getPropertyValue( $this->instance, 'post_indexation_action' ) + self::getPropertyValue( $this->instance, 'post_indexation_action' ), ); self::assertInstanceOf( Indexable_Term_Indexation_Action::class, - self::getPropertyValue( $this->instance, 'term_indexation_action' ) + self::getPropertyValue( $this->instance, 'term_indexation_action' ), ); self::assertInstanceOf( Indexable_Post_Type_Archive_Indexation_Action::class, - self::getPropertyValue( $this->instance, 'post_type_archive_indexation_action' ) + self::getPropertyValue( $this->instance, 'post_type_archive_indexation_action' ), ); self::assertInstanceOf( Indexable_General_Indexation_Action::class, - self::getPropertyValue( $this->instance, 'general_indexation_action' ) + self::getPropertyValue( $this->instance, 'general_indexation_action' ), ); self::assertInstanceOf( Indexing_Prepare_Action::class, - self::getPropertyValue( $this->instance, 'prepare_indexing_action' ) + self::getPropertyValue( $this->instance, 'prepare_indexing_action' ), ); } @@ -345,7 +345,7 @@ public function test_execute_with_reindexing() { [ 'reindex' => true, 'interval' => 500, - ] + ], ); } @@ -366,7 +366,7 @@ public function test_execute_multisite() { 'spam' => 0, 'deleted' => 0, 'archived' => 0, - ] + ], ) ->andReturn( [ 1, 2 ] ); @@ -393,7 +393,7 @@ public function test_execute_multisite() { \array_fill( 0, 25, true ), \array_fill( 0, 5, true ), \array_fill( 0, 25, true ), - \array_fill( 0, 5, true ) + \array_fill( 0, 5, true ), ); } @@ -419,7 +419,7 @@ public function test_execute_multisite() { [ 'network' => true, 'interval' => 500, - ] + ], ); } diff --git a/tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php b/tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php index 8ff0b3683cb..5352d28868d 100644 --- a/tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php +++ b/tests/Unit/Conditionals/Admin/Estimated_Reading_Time_Conditional_Test.php @@ -43,7 +43,7 @@ public function set_up() { $this->post_conditional = Mockery::mock( Post_Conditional::class ); $this->instance = new Estimated_Reading_Time_Conditional( - $this->post_conditional + $this->post_conditional, ); } diff --git a/tests/Unit/Conditionals/Admin/Yoast_Admin_Conditional_Test.php b/tests/Unit/Conditionals/Admin/Yoast_Admin_Conditional_Test.php index 4a1c4902403..420f5c856d3 100644 --- a/tests/Unit/Conditionals/Admin/Yoast_Admin_Conditional_Test.php +++ b/tests/Unit/Conditionals/Admin/Yoast_Admin_Conditional_Test.php @@ -53,7 +53,7 @@ public function set_up() { public function test_constructor() { $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); } diff --git a/tests/Unit/Conditionals/Attachment_Redirections_Enabled_Conditional_Test.php b/tests/Unit/Conditionals/Attachment_Redirections_Enabled_Conditional_Test.php index 59432b45bcf..c328b7fad46 100644 --- a/tests/Unit/Conditionals/Attachment_Redirections_Enabled_Conditional_Test.php +++ b/tests/Unit/Conditionals/Attachment_Redirections_Enabled_Conditional_Test.php @@ -52,7 +52,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options' ) + $this->getPropertyValue( $this->instance, 'options' ), ); } diff --git a/tests/Unit/Conditionals/Headless_Rest_Endpoints_Enabled_Conditional_Test.php b/tests/Unit/Conditionals/Headless_Rest_Endpoints_Enabled_Conditional_Test.php index a13a734955d..83ccfc11a66 100644 --- a/tests/Unit/Conditionals/Headless_Rest_Endpoints_Enabled_Conditional_Test.php +++ b/tests/Unit/Conditionals/Headless_Rest_Endpoints_Enabled_Conditional_Test.php @@ -52,7 +52,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options' ) + $this->getPropertyValue( $this->instance, 'options' ), ); } diff --git a/tests/Unit/Conditionals/Non_Multisite_Conditional_Test.php b/tests/Unit/Conditionals/Non_Multisite_Conditional_Test.php index ea2e91b1d83..943b76d34ed 100644 --- a/tests/Unit/Conditionals/Non_Multisite_Conditional_Test.php +++ b/tests/Unit/Conditionals/Non_Multisite_Conditional_Test.php @@ -43,7 +43,7 @@ public function test_is_not_met() { Monkey\Functions\stubs( [ 'is_multisite' => true, - ] + ], ); self::assertFalse( $this->instance->is_met() ); } @@ -59,7 +59,7 @@ public function test_is_met() { Monkey\Functions\stubs( [ 'is_multisite' => false, - ] + ], ); self::assertTrue( $this->instance->is_met() ); diff --git a/tests/Unit/Conditionals/Robots_Txt_Conditional_Test.php b/tests/Unit/Conditionals/Robots_Txt_Conditional_Test.php index 3dc5a389acb..56dec8b4283 100644 --- a/tests/Unit/Conditionals/Robots_Txt_Conditional_Test.php +++ b/tests/Unit/Conditionals/Robots_Txt_Conditional_Test.php @@ -55,7 +55,7 @@ public function test_construct() { $this->assertInstanceOf( Robots_Txt_Conditional::class, $this->instance ); $this->assertInstanceOf( Front_End_Conditional::class, - $this->getPropertyValue( $this->instance, 'front_end_conditional' ) + $this->getPropertyValue( $this->instance, 'front_end_conditional' ), ); } @@ -120,7 +120,7 @@ public function test_is_met_subdomain_network_admin() { Monkey\Functions\stubs( [ 'is_multisite' => true, - ] + ], ); Monkey\Functions\expect( 'is_network_admin' ) @@ -218,7 +218,7 @@ public function test_is_not_met_subdomain_non_network_admin() { Monkey\Functions\stubs( [ 'is_multisite' => true, - ] + ], ); Monkey\Functions\expect( 'is_network_admin' ) diff --git a/tests/Unit/Conditionals/Should_Index_Links_Conditional_Test.php b/tests/Unit/Conditionals/Should_Index_Links_Conditional_Test.php index 84d578bb591..e17817071d3 100644 --- a/tests/Unit/Conditionals/Should_Index_Links_Conditional_Test.php +++ b/tests/Unit/Conditionals/Should_Index_Links_Conditional_Test.php @@ -53,7 +53,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } diff --git a/tests/Unit/Conditionals/Wincher_Automatically_Track_Conditional_Test.php b/tests/Unit/Conditionals/Wincher_Automatically_Track_Conditional_Test.php index 13a29e8da46..d06da6607f9 100644 --- a/tests/Unit/Conditionals/Wincher_Automatically_Track_Conditional_Test.php +++ b/tests/Unit/Conditionals/Wincher_Automatically_Track_Conditional_Test.php @@ -52,7 +52,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options' ) + $this->getPropertyValue( $this->instance, 'options' ), ); } diff --git a/tests/Unit/Conditionals/Wincher_Conditional_Test.php b/tests/Unit/Conditionals/Wincher_Conditional_Test.php index 661d6bf19e0..ed68cfe10a5 100644 --- a/tests/Unit/Conditionals/Wincher_Conditional_Test.php +++ b/tests/Unit/Conditionals/Wincher_Conditional_Test.php @@ -43,7 +43,7 @@ public function test_is_not_met() { Monkey\Functions\stubs( [ 'is_multisite' => true, - ] + ], ); self::assertFalse( $this->instance->is_met() ); } @@ -59,7 +59,7 @@ public function test_is_met() { Monkey\Functions\stubs( [ 'is_multisite' => false, - ] + ], ); self::assertTrue( $this->instance->is_met() ); diff --git a/tests/Unit/Conditionals/Wincher_Enabled_Conditional_Test.php b/tests/Unit/Conditionals/Wincher_Enabled_Conditional_Test.php index 59e2fa39baf..11ac4d4a2b1 100644 --- a/tests/Unit/Conditionals/Wincher_Enabled_Conditional_Test.php +++ b/tests/Unit/Conditionals/Wincher_Enabled_Conditional_Test.php @@ -52,7 +52,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options' ) + $this->getPropertyValue( $this->instance, 'options' ), ); } diff --git a/tests/Unit/Conditionals/Wincher_Token_Conditional_Test.php b/tests/Unit/Conditionals/Wincher_Token_Conditional_Test.php index a4c9635e433..d725a21955a 100644 --- a/tests/Unit/Conditionals/Wincher_Token_Conditional_Test.php +++ b/tests/Unit/Conditionals/Wincher_Token_Conditional_Test.php @@ -52,7 +52,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Wincher_Client::class, - $this->getPropertyValue( $this->instance, 'client' ) + $this->getPropertyValue( $this->instance, 'client' ), ); } diff --git a/tests/Unit/Config/Badge_Group_Names_Test.php b/tests/Unit/Config/Badge_Group_Names_Test.php index cd1fa4aa67d..a5623185409 100644 --- a/tests/Unit/Config/Badge_Group_Names_Test.php +++ b/tests/Unit/Config/Badge_Group_Names_Test.php @@ -60,7 +60,7 @@ public function test_unknown_group_is_eligible_for_new_badge() { self::assertFalse( $this->instance->is_still_eligible_for_new_badge( $unknown_group ), - 'Group "' . $unknown_group . '" should not exist and should not be considered "new"' + 'Group "' . $unknown_group . '" should not exist and should not be considered "new"', ); } @@ -76,7 +76,7 @@ public function test_global_templates_group_is_eligible_for_new_badge() { self::assertFalse( $this->instance->is_still_eligible_for_new_badge( self::TESTING_GROUP, $expiry_version ), - \sprintf( 'Group should not be "new" on version %s', $expiry_version ) + \sprintf( 'Group should not be "new" on version %s', $expiry_version ), ); } @@ -92,7 +92,7 @@ public function test_global_templates_group_is_eligible_for_new_badge_release_ca self::assertFalse( $this->instance->is_still_eligible_for_new_badge( self::TESTING_GROUP, $expiry_version ), - \sprintf( 'Group should not be "new" on version %s', $expiry_version ) + \sprintf( 'Group should not be "new" on version %s', $expiry_version ), ); } @@ -108,7 +108,7 @@ public function test_global_templates_group_no_longer_eligible_for_new_badge_on_ self::assertFalse( $this->instance->is_still_eligible_for_new_badge( self::TESTING_GROUP, $expiry_version ), - \sprintf( 'Group should not be "new" on version %s', $expiry_version ) + \sprintf( 'Group should not be "new" on version %s', $expiry_version ), ); } @@ -124,7 +124,7 @@ public function test_global_templates_group_no_longer_eligible_for_new_badge_on_ self::assertFalse( $this->instance->is_still_eligible_for_new_badge( self::TESTING_GROUP, $expiry_version ), - \sprintf( 'Group should not be "new" on version %s', $expiry_version ) + \sprintf( 'Group should not be "new" on version %s', $expiry_version ), ); } @@ -140,7 +140,7 @@ public function test_global_templates_group_no_longer_eligible_for_new_badge_on_ self::assertTrue( $this->instance->is_still_eligible_for_new_badge( self::TESTING_GROUP, $expiry_version ), - \sprintf( 'Group should be "new" on version %s', $expiry_version ) + \sprintf( 'Group should be "new" on version %s', $expiry_version ), ); } } diff --git a/tests/Unit/Config/OAuth_Client_Test.php b/tests/Unit/Config/OAuth_Client_Test.php index c5fda5bc58a..d4428533025 100644 --- a/tests/Unit/Config/OAuth_Client_Test.php +++ b/tests/Unit/Config/OAuth_Client_Test.php @@ -104,22 +104,22 @@ public function test_construct() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ); $this->assertEquals( 'oauth_token', - $this->getPropertyValue( $instance, 'token_option' ) + $this->getPropertyValue( $instance, 'token_option' ), ); $this->assertInstanceOf( GenericProvider::class, - $this->getPropertyValue( $instance, 'provider' ) + $this->getPropertyValue( $instance, 'provider' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $instance, 'options_helper' ) + $this->getPropertyValue( $instance, 'options_helper' ), ); $this->assertNull( $this->getPropertyValue( $instance, 'token' ) ); @@ -143,11 +143,11 @@ public function test_construct_with_existing_token() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $instance = Mockery::mock( @@ -156,27 +156,27 @@ public function test_construct_with_existing_token() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ); $this->assertEquals( 'oauth_token', - $this->getPropertyValue( $instance, 'token_option' ) + $this->getPropertyValue( $instance, 'token_option' ), ); $this->assertInstanceOf( GenericProvider::class, - $this->getPropertyValue( $instance, 'provider' ) + $this->getPropertyValue( $instance, 'provider' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $instance, 'options_helper' ) + $this->getPropertyValue( $instance, 'options_helper' ), ); $this->assertInstanceOf( OAuth_Token::class, - $this->getPropertyValue( $instance, 'token' ) + $this->getPropertyValue( $instance, 'token' ), ); } @@ -192,9 +192,9 @@ public function test_valid_request_tokens_when_no_token_is_available() { [ 'getToken' => '000000', 'getRefreshToken' => '000001', - 'getExpires' => 604800, + 'getExpires' => 604_800, 'hasExpired' => false, - ] + ], ); $this->options_helper @@ -219,11 +219,11 @@ public function test_valid_request_tokens_when_no_token_is_available() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ) ->andReturns( $this->token ); @@ -233,7 +233,7 @@ public function test_valid_request_tokens_when_no_token_is_available() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], )->makePartial(); $requested_tokens = $instance->request_tokens( '123456' ); @@ -259,11 +259,11 @@ public function test_invalid_request_tokens_when_no_code_is_set() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $this->provider @@ -278,7 +278,7 @@ public function test_invalid_request_tokens_when_no_code_is_set() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], )->makePartial(); $instance->request_tokens( '' ); @@ -304,11 +304,11 @@ public function test_storing_token_success() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $this->options_helper @@ -318,11 +318,11 @@ public function test_storing_token_success() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ) ->once() ->andReturnTrue(); @@ -333,7 +333,7 @@ public function test_storing_token_success() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], )->makePartial(); $stored_token = $instance->store_token( $this->token ); @@ -363,11 +363,11 @@ public function test_storing_token_failure() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $this->options_helper @@ -377,11 +377,11 @@ public function test_storing_token_failure() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ) ->once() ->andReturnFalse(); @@ -392,7 +392,7 @@ public function test_storing_token_failure() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], )->makePartial(); $instance->store_token( $this->token ); @@ -431,11 +431,11 @@ public function test_get_request() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => ( $this->time + 604800 ), + 'expires' => ( $this->time + 604_800 ), 'has_expired' => false, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $instance = Mockery::mock( @@ -444,7 +444,7 @@ public function test_get_request() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial() ->shouldAllowMockingProtectedMethods(); @@ -474,7 +474,7 @@ public function test_post_request() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial() ->shouldAllowMockingProtectedMethods(); @@ -486,7 +486,7 @@ public function test_post_request() { 'https://google.com', [ 'body' => 'request body', - ] + ], ) ->andReturn( [] ); @@ -513,7 +513,7 @@ public function test_delete_request() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial() ->shouldAllowMockingProtectedMethods(); @@ -544,11 +544,11 @@ public function test_has_no_valid_token_set() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $instance = Mockery::mock( @@ -557,7 +557,7 @@ public function test_has_no_valid_token_set() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial(); @@ -584,7 +584,7 @@ public function test_has_no_token_set() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial(); @@ -608,11 +608,11 @@ public function test_has_token_set() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => ( $this->time + 604800 ), + 'expires' => ( $this->time + 604_800 ), 'has_expired' => false, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $instance = Mockery::mock( @@ -621,12 +621,12 @@ public function test_has_token_set() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial(); $this->assertNotEmpty( - $this->getPropertyValue( $instance, 'token' ) + $this->getPropertyValue( $instance, 'token' ), ); $this->assertTrue( $instance->has_valid_tokens() ); @@ -654,7 +654,7 @@ public function test_get_tokens_when_not_set() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial(); @@ -673,9 +673,9 @@ public function test_get_tokens_with_expired_token() { [ 'getToken' => '000000', 'getRefreshToken' => '000001', - 'getExpires' => 604800, + 'getExpires' => 604_800, 'hasExpired' => false, - ] + ], ); $this->time = \time(); @@ -688,11 +688,11 @@ public function test_get_tokens_with_expired_token() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $this->options_helper @@ -705,7 +705,7 @@ public function test_get_tokens_with_expired_token() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], )->makePartial() ->shouldAllowMockingProtectedMethods(); @@ -742,11 +742,11 @@ public function test_get_tokens() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => ( $this->time + 604800 ), + 'expires' => ( $this->time + 604_800 ), 'has_expired' => false, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $instance = Mockery::mock( @@ -755,7 +755,7 @@ public function test_get_tokens() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], )->makePartial(); $this->assertInstanceOf( OAuth_Token::class, $instance->get_tokens() ); @@ -779,20 +779,20 @@ public function test_refresh_tokens() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $this->response->allows( [ 'getToken' => '000000', 'getRefreshToken' => '000001', - 'getExpires' => ( $this->time + 604800 ), + 'getExpires' => ( $this->time + 604_800 ), 'hasExpired' => false, - ] + ], ); $this->provider @@ -807,7 +807,7 @@ public function test_refresh_tokens() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], )->makePartial() ->shouldAllowMockingProtectedMethods(); @@ -825,7 +825,7 @@ public function test_refresh_tokens() { $this->assertInstanceOf( OAuth_Token::class, - $this->getPropertyValue( $instance, 'token' ) + $this->getPropertyValue( $instance, 'token' ), ); } @@ -849,11 +849,11 @@ public function test_refresh_tokens_fails() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $this->provider @@ -868,7 +868,7 @@ public function test_refresh_tokens_fails() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial() ->shouldAllowMockingProtectedMethods(); @@ -915,11 +915,11 @@ public function test_refresh_tokens_fails_with_invalid_grant() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, 'created_at' => $this->time, 'error_count' => 0, - ] + ], ); $this->provider @@ -934,7 +934,7 @@ public function test_refresh_tokens_fails_with_invalid_grant() { 'oauth_token', $this->provider, $this->options_helper, - ] + ], ) ->makePartial() ->shouldAllowMockingProtectedMethods(); diff --git a/tests/Unit/Config/SEMrush_Client_Test.php b/tests/Unit/Config/SEMrush_Client_Test.php index a56254fd7bd..8361174e049 100644 --- a/tests/Unit/Config/SEMrush_Client_Test.php +++ b/tests/Unit/Config/SEMrush_Client_Test.php @@ -97,16 +97,16 @@ public function test_construct() { [ $this->options_helper, Mockery::mock( WP_Remote_Handler::class ), - ] + ], )->makePartial(); $this->assertInstanceOf( GenericProvider::class, - $this->getPropertyValue( $instance, 'provider' ) + $this->getPropertyValue( $instance, 'provider' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $instance, 'options_helper' ) + $this->getPropertyValue( $instance, 'options_helper' ), ); } @@ -125,10 +125,10 @@ public function test_construct_with_pre_existing_token() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => 604800, + 'expires' => 604_800, 'has_expired' => true, - 'created_at' => 1234890, - ] + 'created_at' => 1_234_890, + ], ); $instance = Mockery::mock( @@ -136,20 +136,20 @@ public function test_construct_with_pre_existing_token() { [ $this->options_helper, Mockery::mock( WP_Remote_Handler::class ), - ] + ], )->makePartial(); $this->assertInstanceOf( GenericProvider::class, - $this->getPropertyValue( $instance, 'provider' ) + $this->getPropertyValue( $instance, 'provider' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $instance, 'options_helper' ) + $this->getPropertyValue( $instance, 'options_helper' ), ); $this->assertInstanceOf( OAuth_Token::class, - $this->getPropertyValue( $instance, 'token' ) + $this->getPropertyValue( $instance, 'token' ), ); } } diff --git a/tests/Unit/Config/Wincher_Client_Test.php b/tests/Unit/Config/Wincher_Client_Test.php index ac8225468bd..84a2d7f8a74 100644 --- a/tests/Unit/Config/Wincher_Client_Test.php +++ b/tests/Unit/Config/Wincher_Client_Test.php @@ -67,10 +67,10 @@ public function test_construct() { [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => ( $this->time + 604800 ), + 'expires' => ( $this->time + 604_800 ), 'has_expired' => false, - 'created_at' => 1234890, - ] + 'created_at' => 1_234_890, + ], ); $instance = Mockery::mock( @@ -78,17 +78,17 @@ public function test_construct() { [ $this->options_helper, Mockery::mock( WP_Remote_Handler::class ), - ] + ], )->makePartial(); $this->assertInstanceOf( Wincher_PKCE_Provider::class, - $this->getPropertyValue( $instance, 'provider' ) + $this->getPropertyValue( $instance, 'provider' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $instance, 'options_helper' ) + $this->getPropertyValue( $instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Dismiss_Notifications_Test.php b/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Dismiss_Notifications_Test.php index 2152afb6367..ce22a9da3d2 100644 --- a/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Dismiss_Notifications_Test.php +++ b/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Dismiss_Notifications_Test.php @@ -56,7 +56,7 @@ public function test_construct() { $this->assertInstanceOf( Options_Helper::class, $this->getPropertyValue( $this->instance, 'options' ), - 'Options helper is not set correctly.' + 'Options helper is not set correctly.', ); } diff --git a/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Watcher_Actions_Test.php b/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Watcher_Actions_Test.php index 6decf0dbad6..7c7e9964857 100644 --- a/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Watcher_Actions_Test.php +++ b/tests/Unit/Content_Type_Visibility/Application/Content_Type_Visibility_Watcher_Actions_Test.php @@ -76,7 +76,7 @@ protected function set_up() { $this->instance = new Content_Type_Visibility_Watcher_Actions( $this->options, $this->notification_center, - $this->content_type_dismiss_notifications + $this->content_type_dismiss_notifications, ); } @@ -91,19 +91,19 @@ public function test_construct() { $this->assertInstanceOf( Options_Helper::class, $this->getPropertyValue( $this->instance, 'options' ), - 'Options helper is set correctly.' + 'Options helper is set correctly.', ); $this->assertInstanceOf( Yoast_Notification_Center::class, $this->getPropertyValue( $this->instance, 'notification_center' ), - 'Notification center is set correctly.' + 'Notification center is set correctly.', ); $this->assertInstanceOf( Content_Type_Visibility_Dismiss_Notifications::class, $this->getPropertyValue( $this->instance, 'content_type_dismiss_notifications' ), - 'Content type dismiss notifications is set correctly.' + 'Content type dismiss notifications is set correctly.', ); } @@ -338,7 +338,7 @@ public function test_maybe_add_notification() { [ 'esc_url' => 'https://yoa.st/3.0-content-types', 'admin_url' => 'admin.php?page=wpseo_page_settings', - ] + ], ); Monkey\Functions\expect( 'get_current_user_id' ) diff --git a/tests/Unit/Content_Type_Visibility/User_Interface/Content_Type_Visibility_Dismiss_New_Route_Test.php b/tests/Unit/Content_Type_Visibility/User_Interface/Content_Type_Visibility_Dismiss_New_Route_Test.php index ec604002811..c4c7c7f9bbe 100644 --- a/tests/Unit/Content_Type_Visibility/User_Interface/Content_Type_Visibility_Dismiss_New_Route_Test.php +++ b/tests/Unit/Content_Type_Visibility/User_Interface/Content_Type_Visibility_Dismiss_New_Route_Test.php @@ -58,7 +58,7 @@ public function test_construct() { $this->assertInstanceOf( Content_Type_Visibility_Dismiss_Notifications::class, $this->getPropertyValue( $this->instance, 'dismiss_notifications' ), - 'Content_Type_Visibility_Dismiss_Notifications is set correctly.' + 'Content_Type_Visibility_Dismiss_Notifications is set correctly.', ); } @@ -85,7 +85,7 @@ public function test_register_routes() { }, ], ], - ] + ], ) ->once(); @@ -104,7 +104,7 @@ public function test_register_routes() { }, ], ], - ] + ], ) ->once(); @@ -187,7 +187,7 @@ public function test_post_type_dismiss_callback() { 'message' => 'Post type is no longer new.', 'success' => true, 'status' => 200, - ] + ], ); Mockery::mock( 'overload:' . WP_REST_Response::class ); @@ -221,7 +221,7 @@ public function test_taxonomy_dismiss_callback() { 'message' => 'Taxonomy is no longer new.', 'success' => true, 'status' => 200, - ] + ], ); Mockery::mock( 'overload:' . WP_REST_Response::class ); diff --git a/tests/Unit/Context/Meta_Tags_Context_Test.php b/tests/Unit/Context/Meta_Tags_Context_Test.php index ac6e0ab27a1..e256755edca 100644 --- a/tests/Unit/Context/Meta_Tags_Context_Test.php +++ b/tests/Unit/Context/Meta_Tags_Context_Test.php @@ -134,7 +134,7 @@ protected function set_up() { $this->user, $this->permalink_helper, $this->indexable_helper, - $this->indexable_repository + $this->indexable_repository, ); } @@ -512,7 +512,7 @@ public function test_generate_site_represents_company_with_name_and_logo() { 'size' => 'full', 'id' => 12, 'alt' => 'Alt. Text', - 'pixels' => 307200, + 'pixels' => 307_200, 'type' => 'image/jpeg', ]; diff --git a/tests/Unit/Dashboard/Application/Configuration/Abstract_Dashboard_Configuration_Test.php b/tests/Unit/Dashboard/Application/Configuration/Abstract_Dashboard_Configuration_Test.php index 9794ac25d35..27578d91d1a 100644 --- a/tests/Unit/Dashboard/Application/Configuration/Abstract_Dashboard_Configuration_Test.php +++ b/tests/Unit/Dashboard/Application/Configuration/Abstract_Dashboard_Configuration_Test.php @@ -120,7 +120,7 @@ protected function set_up() { $this->nonce_repository, $this->site_kit_integration_data, $this->setup_steps_tracking, - $this->browser_cache_configuration + $this->browser_cache_configuration, ); } } diff --git a/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Constructor_Test.php b/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Constructor_Test.php index 411e17e1f1a..0eb7c573c68 100644 --- a/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Constructor_Test.php +++ b/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Constructor_Test.php @@ -32,40 +32,40 @@ final class Dashboard_Configuration_Constructor_Test extends Abstract_Dashboard_ public function test_constructor() { $this->assertInstanceOf( Content_Types_Repository::class, - $this->getPropertyValue( $this->instance, 'content_types_repository' ) + $this->getPropertyValue( $this->instance, 'content_types_repository' ), ); $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); $this->assertInstanceOf( Enabled_Analysis_Features_Repository::class, - $this->getPropertyValue( $this->instance, 'enabled_analysis_features_repository' ) + $this->getPropertyValue( $this->instance, 'enabled_analysis_features_repository' ), ); $this->assertInstanceOf( Endpoints_Repository::class, - $this->getPropertyValue( $this->instance, 'endpoints_repository' ) + $this->getPropertyValue( $this->instance, 'endpoints_repository' ), ); $this->assertInstanceOf( Nonce_Repository::class, - $this->getPropertyValue( $this->instance, 'nonce_repository' ) + $this->getPropertyValue( $this->instance, 'nonce_repository' ), ); $this->assertInstanceOf( Site_Kit::class, - $this->getPropertyValue( $this->instance, 'site_kit_integration_data' ) + $this->getPropertyValue( $this->instance, 'site_kit_integration_data' ), ); $this->assertInstanceOf( Setup_Steps_Tracking::class, - $this->getPropertyValue( $this->instance, 'setup_steps_tracking' ) + $this->getPropertyValue( $this->instance, 'setup_steps_tracking' ), ); $this->assertInstanceOf( Browser_Cache_Configuration::class, - $this->getPropertyValue( $this->instance, 'browser_cache_configuration' ) + $this->getPropertyValue( $this->instance, 'browser_cache_configuration' ), ); } } diff --git a/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Get_Configuration_Test.php b/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Get_Configuration_Test.php index d943af34507..7837bc52bc8 100644 --- a/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Get_Configuration_Test.php +++ b/tests/Unit/Dashboard/Application/Configuration/Dashboard_Configuration_Get_Configuration_Test.php @@ -62,7 +62,7 @@ public function test_get_configuration( $content_types, $indexables_enabled, $di 'setupStepsTracking' => $setup_steps_tracking, 'browserCache' => $cache_configuration, ], - $this->instance->get_configuration() + $this->instance->get_configuration(), ); } diff --git a/tests/Unit/Dashboard/Application/Tracking/Abstract_Setup_Steps_Tracking_Test.php b/tests/Unit/Dashboard/Application/Tracking/Abstract_Setup_Steps_Tracking_Test.php index 24345b18270..197fb043578 100644 --- a/tests/Unit/Dashboard/Application/Tracking/Abstract_Setup_Steps_Tracking_Test.php +++ b/tests/Unit/Dashboard/Application/Tracking/Abstract_Setup_Steps_Tracking_Test.php @@ -34,7 +34,7 @@ protected function set_up() { Mockery::mock( WP_Error::class ); $this->instance = new Setup_Steps_Tracking( - new Setup_Steps_Tracking_Repository_Fake() + new Setup_Steps_Tracking_Repository_Fake(), ); } } diff --git a/tests/Unit/Dashboard/Application/Tracking/Setup_Steps_Tracking_Constructor_Test.php b/tests/Unit/Dashboard/Application/Tracking/Setup_Steps_Tracking_Constructor_Test.php index 24a50cbfc1f..86f8d415208 100644 --- a/tests/Unit/Dashboard/Application/Tracking/Setup_Steps_Tracking_Constructor_Test.php +++ b/tests/Unit/Dashboard/Application/Tracking/Setup_Steps_Tracking_Constructor_Test.php @@ -24,7 +24,7 @@ final class Setup_Steps_Tracking_Constructor_Test extends Abstract_Setup_Steps_T public function test_construct() { $this->assertInstanceOf( Setup_Steps_Tracking_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'setup_steps_tracking_repository' ) + $this->getPropertyValue( $this->instance, 'setup_steps_tracking_repository' ), ); } } diff --git a/tests/Unit/Dashboard/Infrastructure/Browser_Cache/Browser_Cache_Configuration_Get_Configuration_Test.php b/tests/Unit/Dashboard/Infrastructure/Browser_Cache/Browser_Cache_Configuration_Get_Configuration_Test.php index 82bd6bd986d..3a233ba3b6d 100644 --- a/tests/Unit/Dashboard/Infrastructure/Browser_Cache/Browser_Cache_Configuration_Get_Configuration_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Browser_Cache/Browser_Cache_Configuration_Get_Configuration_Test.php @@ -60,7 +60,7 @@ public function test_get_configuration( Functions\expect( 'wp_hash' ) ->once() - ->with( $to_hash, ) + ->with( $to_hash ) ->andReturn( $hash ); $this->assertEquals( $expected, $this->instance->get_configuration() ); diff --git a/tests/Unit/Dashboard/Infrastructure/Configuration/Permanently_Dismissed_Site_Kit_Configuration_Repository_Constructor_Test.php b/tests/Unit/Dashboard/Infrastructure/Configuration/Permanently_Dismissed_Site_Kit_Configuration_Repository_Constructor_Test.php index 131f879162f..459ee7b014c 100644 --- a/tests/Unit/Dashboard/Infrastructure/Configuration/Permanently_Dismissed_Site_Kit_Configuration_Repository_Constructor_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Configuration/Permanently_Dismissed_Site_Kit_Configuration_Repository_Constructor_Test.php @@ -24,7 +24,7 @@ final class Permanently_Dismissed_Site_Kit_Configuration_Repository_Constructor_ public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Dashboard/Infrastructure/Configuration/Site_Kit_Consent_Repository_Constructor_Test.php b/tests/Unit/Dashboard/Infrastructure/Configuration/Site_Kit_Consent_Repository_Constructor_Test.php index 20201e30d00..11f5ba843ec 100644 --- a/tests/Unit/Dashboard/Infrastructure/Configuration/Site_Kit_Consent_Repository_Constructor_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Configuration/Site_Kit_Consent_Repository_Constructor_Test.php @@ -24,7 +24,7 @@ final class Site_Kit_Consent_Repository_Constructor_Test extends Abstract_Site_K public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Dashboard/Infrastructure/Endpoints/Readability_Scores_Endpoint_Test.php b/tests/Unit/Dashboard/Infrastructure/Endpoints/Readability_Scores_Endpoint_Test.php index 74ab7dca24f..e792a635831 100644 --- a/tests/Unit/Dashboard/Infrastructure/Endpoints/Readability_Scores_Endpoint_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Endpoints/Readability_Scores_Endpoint_Test.php @@ -74,7 +74,7 @@ public function test_get_url() { Functions\expect( 'rest_url' ) ->once() ->with( - 'yoast/v1/readability_scores' + 'yoast/v1/readability_scores', )->andReturnFirstArg(); $this->assertSame( 'yoast/v1/readability_scores', $this->instance->get_url() ); } diff --git a/tests/Unit/Dashboard/Infrastructure/Endpoints/SEO_Scores_Endpoint_Test.php b/tests/Unit/Dashboard/Infrastructure/Endpoints/SEO_Scores_Endpoint_Test.php index 64421c30fee..24e3b4dec4f 100644 --- a/tests/Unit/Dashboard/Infrastructure/Endpoints/SEO_Scores_Endpoint_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Endpoints/SEO_Scores_Endpoint_Test.php @@ -74,7 +74,7 @@ public function test_get_url() { Functions\expect( 'rest_url' ) ->once() ->with( - 'yoast/v1/seo_scores' + 'yoast/v1/seo_scores', )->andReturnFirstArg(); $this->assertSame( 'yoast/v1/seo_scores', $this->instance->get_url() ); } diff --git a/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Configuration_Dismissal_Endpoint_Test.php b/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Configuration_Dismissal_Endpoint_Test.php index 17708ac59c5..403d58254e6 100644 --- a/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Configuration_Dismissal_Endpoint_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Configuration_Dismissal_Endpoint_Test.php @@ -74,7 +74,7 @@ public function test_get_url() { Functions\expect( 'rest_url' ) ->once() ->with( - 'yoast/v1/site_kit_configuration_permanent_dismissal' + 'yoast/v1/site_kit_configuration_permanent_dismissal', )->andReturnFirstArg(); $this->assertSame( 'yoast/v1/site_kit_configuration_permanent_dismissal', $this->instance->get_url() ); } diff --git a/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Consent_Management_Endpoint_Test.php b/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Consent_Management_Endpoint_Test.php index 9d58b8c181f..4fd2f222c70 100644 --- a/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Consent_Management_Endpoint_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Endpoints/Site_Kit_Consent_Management_Endpoint_Test.php @@ -74,7 +74,7 @@ public function test_get_url() { Functions\expect( 'rest_url' ) ->once() ->with( - 'yoast/v1/site_kit_manage_consent' + 'yoast/v1/site_kit_manage_consent', )->andReturnFirstArg(); $this->assertSame( 'yoast/v1/site_kit_manage_consent', $this->instance->get_url() ); } diff --git a/tests/Unit/Dashboard/Infrastructure/Endpoints/Time_Based_SEO_Metrics_Endpoint_Test.php b/tests/Unit/Dashboard/Infrastructure/Endpoints/Time_Based_SEO_Metrics_Endpoint_Test.php index 610a3ad9e59..73ab5697bd1 100644 --- a/tests/Unit/Dashboard/Infrastructure/Endpoints/Time_Based_SEO_Metrics_Endpoint_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Endpoints/Time_Based_SEO_Metrics_Endpoint_Test.php @@ -74,7 +74,7 @@ public function test_get_url() { Functions\expect( 'rest_url' ) ->once() ->with( - 'yoast/v1/time_based_seo_metrics' + 'yoast/v1/time_based_seo_metrics', )->andReturnFirstArg(); $this->assertSame( 'yoast/v1/time_based_seo_metrics', $this->instance->get_url() ); } diff --git a/tests/Unit/Dashboard/Infrastructure/Integrations/Site_Kit_To_Array_Test.php b/tests/Unit/Dashboard/Infrastructure/Integrations/Site_Kit_To_Array_Test.php index b481af53e25..5ff3a58da75 100644 --- a/tests/Unit/Dashboard/Infrastructure/Integrations/Site_Kit_To_Array_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Integrations/Site_Kit_To_Array_Test.php @@ -81,7 +81,7 @@ public function test_to_array( '//core/modules/data/list', '//core/user/data/permissions', '//core/site/data/connection', - ] + ], ); Functions\expect( 'rest_preload_api_request' )->andReturn( [ @@ -91,7 +91,7 @@ public function test_to_array( '//core/modules/data/list' => [ 'body' => $data_list, ], - ] + ], ); } diff --git a/tests/Unit/Dashboard/Infrastructure/Score_Groups/Get_View_Link_Score_Group_Link_Collector_Test.php b/tests/Unit/Dashboard/Infrastructure/Score_Groups/Get_View_Link_Score_Group_Link_Collector_Test.php index 6ee97844fca..323d94a3d2e 100644 --- a/tests/Unit/Dashboard/Infrastructure/Score_Groups/Get_View_Link_Score_Group_Link_Collector_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Score_Groups/Get_View_Link_Score_Group_Link_Collector_Test.php @@ -61,7 +61,7 @@ public function test_get_view_link_without_taxonomy() { 'post_status' => 'publish', 'post_type' => $content_type->get_name(), $score_group->get_filter_key() => $score_group->get_filter_value(), - ] + ], ) ->andReturn( 'edit.php?post_status=publish&page_type=' . $content_type->get_name() . '&' . $score_group->get_filter_key() . '=' . $score_group->get_filter_value() ); @@ -102,7 +102,7 @@ public function test_get_view_link_with_taxonomy() { 'post_status' => 'publish', 'post_type' => $content_type->get_name(), $score_group->get_filter_key() => $score_group->get_filter_value(), - ] + ], ) ->andReturn( 'edit.php?post_status=publish&page_type=' . $content_type->get_name() . '&' . $score_group->get_filter_key() . '=' . $score_group->get_filter_value() . '&query=slug' ); @@ -178,7 +178,7 @@ public function test_get_view_link_with_taxonomy_but_no_query_var( 'post_status' => 'publish', 'post_type' => $content_type->get_name(), $score_group->get_filter_key() => $score_group->get_filter_value(), - ] + ], ) ->andReturn( 'edit.php?post_status=publish&page_type=' . $content_type->get_name() . '&' . $score_group->get_filter_key() . '=' . $score_group->get_filter_value() . '&' . $taxonomy_query_var . '=slug' ); diff --git a/tests/Unit/Dashboard/Infrastructure/Tracking/Setup_Steps_Tracking_Repository_Constructor_Test.php b/tests/Unit/Dashboard/Infrastructure/Tracking/Setup_Steps_Tracking_Repository_Constructor_Test.php index dcd7f3d37b4..147015841bd 100644 --- a/tests/Unit/Dashboard/Infrastructure/Tracking/Setup_Steps_Tracking_Repository_Constructor_Test.php +++ b/tests/Unit/Dashboard/Infrastructure/Tracking/Setup_Steps_Tracking_Repository_Constructor_Test.php @@ -24,7 +24,7 @@ final class Setup_Steps_Tracking_Repository_Constructor_Test extends Abstract_Se public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Configuration_Permanent_Dismissal_Route_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Configuration_Permanent_Dismissal_Route_Test.php index af39a9c26f8..5c997600b35 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Configuration_Permanent_Dismissal_Route_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Configuration_Permanent_Dismissal_Route_Test.php @@ -46,7 +46,7 @@ protected function set_up() { $this->instance = new Site_Kit_Configuration_Dismissal_Route( new Permanently_Dismissed_Site_Kit_Configuration_Repository_Fake(), - $this->capability_helper + $this->capability_helper, ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Consent_Management_Route_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Consent_Management_Route_Test.php index f0ee36cbedf..abf4e2be4e0 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Consent_Management_Route_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Abstract_Site_Kit_Consent_Management_Route_Test.php @@ -46,7 +46,7 @@ protected function set_up() { $this->instance = new Site_Kit_Consent_Management_Route( new Site_Kit_Consent_Repository_Fake(), - $this->capability_helper + $this->capability_helper, ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Consent_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Consent_Test.php index 83ee149d41f..fafac9a9a05 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Consent_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Consent_Test.php @@ -37,7 +37,7 @@ public function test_set_site_kit_consent( $consent, $expected_status ) { [ 'success' => $consent, ], - $expected_status + $expected_status, ) ->once(); @@ -49,7 +49,7 @@ public function test_set_site_kit_consent( $consent, $expected_status ) { $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->set_site_kit_consent( $wp_rest_request ) + $this->instance->set_site_kit_consent( $wp_rest_request ), ); } diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Permanent_Dismissal_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Permanent_Dismissal_Test.php index 0e216450b0d..bf1397b70a4 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Permanent_Dismissal_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Set_Site_Kit_Permanent_Dismissal_Test.php @@ -37,7 +37,7 @@ public function test_set_site_kit_configuration_permanent_dismissal( $is_dismiss [ 'success' => $is_dismissed, ], - $expected_status + $expected_status, ) ->once(); @@ -49,7 +49,7 @@ public function test_set_site_kit_configuration_permanent_dismissal( $is_dismiss $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->set_site_kit_configuration_permanent_dismissal( $wp_rest_request ) + $this->instance->set_site_kit_configuration_permanent_dismissal( $wp_rest_request ), ); } diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Constructor_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Constructor_Test.php index 171be301903..cc9ea0b974f 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Constructor_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Constructor_Test.php @@ -24,7 +24,7 @@ final class Site_Kit_Configuration_Permanent_Dismissal_Route_Constructor_Test ex public function test_construct() { $this->assertInstanceOf( Permanently_Dismissed_Site_Kit_Configuration_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'permanently_dismissed_site_kit_configuration_repository' ) + $this->getPropertyValue( $this->instance, 'permanently_dismissed_site_kit_configuration_repository' ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Register_Routes_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Register_Routes_Test.php index e9b62e93131..675b4ef29c3 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Register_Routes_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Configuration_Permanent_Dismissal_Route_Register_Routes_Test.php @@ -40,7 +40,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Constructor_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Constructor_Test.php index 2a62404c013..54de5a472a7 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Constructor_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Constructor_Test.php @@ -24,7 +24,7 @@ final class Site_Kit_Consent_Management_Route_Constructor_Test extends Abstract_ public function test_construct() { $this->assertInstanceOf( Site_Kit_Consent_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'site_kit_consent_repository' ) + $this->getPropertyValue( $this->instance, 'site_kit_consent_repository' ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Register_Routes_Test.php b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Register_Routes_Test.php index 1a9a3345965..374d1478c87 100644 --- a/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Register_Routes_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Configuration/Site_Kit_Consent_Management_Route_Register_Routes_Test.php @@ -40,7 +40,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Dashboard/User_Interface/Setup/Abstract_Setup_Url_Interceptor_Test.php b/tests/Unit/Dashboard/User_Interface/Setup/Abstract_Setup_Url_Interceptor_Test.php index b9cdc0621bd..376cab6b2c4 100644 --- a/tests/Unit/Dashboard/User_Interface/Setup/Abstract_Setup_Url_Interceptor_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Setup/Abstract_Setup_Url_Interceptor_Test.php @@ -64,7 +64,7 @@ protected function set_up() { $this->instance = new Setup_Url_Interceptor( $this->current_page_helper, $this->site_kit, - $this->redirect_helper + $this->redirect_helper, ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Constructor_Test.php b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Constructor_Test.php index de361e858f6..ef08d9154d6 100644 --- a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Constructor_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Constructor_Test.php @@ -25,11 +25,11 @@ final class Setup_Flow_Interceptor_Constructor_Test extends Abstract_Setup_Flow_ public function test_construct() { $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); $this->assertInstanceOf( Redirect_Helper::class, - $this->getPropertyValue( $this->instance, 'redirect_helper' ) + $this->getPropertyValue( $this->instance, 'redirect_helper' ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Register_Hooks_Test.php b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Register_Hooks_Test.php index 9f36e5350a0..fc39e9b00c3 100644 --- a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Register_Hooks_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Flow_Interceptor_Register_Hooks_Test.php @@ -26,8 +26,8 @@ public function test_register_hooks() { 999, \has_action( 'admin_init', - [ $this->instance, 'intercept_site_kit_setup_flow' ] - ) + [ $this->instance, 'intercept_site_kit_setup_flow' ], + ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Add_Redirect_Page_Test.php b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Add_Redirect_Page_Test.php index caef44a8ad3..c0847803ecd 100644 --- a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Add_Redirect_Page_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Add_Redirect_Page_Test.php @@ -29,7 +29,7 @@ public function test_add_redirect_page() { '', '', 'wpseo_manage_options', - 'wpseo_page_site_kit_set_up' + 'wpseo_page_site_kit_set_up', ); $this->assertEquals( [], $this->instance->add_redirect_page( [] ) ); diff --git a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Constructor_Test.php b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Constructor_Test.php index 37a6c5863f2..67f92e62094 100644 --- a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Constructor_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Constructor_Test.php @@ -26,15 +26,15 @@ final class Setup_Url_Interceptor_Constructor_Test extends Abstract_Setup_Url_In public function test_construct() { $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); $this->assertInstanceOf( Site_Kit::class, - $this->getPropertyValue( $this->instance, 'site_kit_configuration' ) + $this->getPropertyValue( $this->instance, 'site_kit_configuration' ), ); $this->assertInstanceOf( Redirect_Helper::class, - $this->getPropertyValue( $this->instance, 'redirect_helper' ) + $this->getPropertyValue( $this->instance, 'redirect_helper' ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Register_Hooks_Test.php b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Register_Hooks_Test.php index b484990ba20..f363e68e296 100644 --- a/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Register_Hooks_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Setup/Setup_Url_Interceptor_Register_Hooks_Test.php @@ -26,15 +26,15 @@ public function test_register_hooks() { 10, \has_filter( 'admin_menu', - [ $this->instance, 'add_redirect_page' ] - ) + [ $this->instance, 'add_redirect_page' ], + ), ); $this->assertEquals( 1, \has_action( 'admin_init', - [ $this->instance, 'intercept_site_kit_setup_url_redirect' ] - ) + [ $this->instance, 'intercept_site_kit_setup_url_redirect' ], + ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Abstract_Time_Based_SEO_Metrics_Route_Test.php b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Abstract_Time_Based_SEO_Metrics_Route_Test.php index 9c752ab48d9..21a6e2aee52 100644 --- a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Abstract_Time_Based_SEO_Metrics_Route_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Abstract_Time_Based_SEO_Metrics_Route_Test.php @@ -92,7 +92,7 @@ protected function set_up() { $this->organic_sessions_compare_repository, $this->organic_sessions_daily_repository, $this->search_ranking_compare_repository, - $this->capability_helper + $this->capability_helper, ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Constructor_Test.php b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Constructor_Test.php index 7f5f4f9bb65..3ad93a02fa8 100644 --- a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Constructor_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Constructor_Test.php @@ -28,27 +28,27 @@ final class Time_Based_SEO_Metrics_Route_Constructor_Test extends Abstract_Time_ public function test_construct() { $this->assertInstanceOf( Top_Page_Repository::class, - $this->getPropertyValue( $this->instance, 'top_page_repository' ) + $this->getPropertyValue( $this->instance, 'top_page_repository' ), ); $this->assertInstanceOf( Top_Query_Repository::class, - $this->getPropertyValue( $this->instance, 'top_query_repository' ) + $this->getPropertyValue( $this->instance, 'top_query_repository' ), ); $this->assertInstanceOf( Organic_Sessions_Compare_Repository::class, - $this->getPropertyValue( $this->instance, 'organic_sessions_compare_repository' ) + $this->getPropertyValue( $this->instance, 'organic_sessions_compare_repository' ), ); $this->assertInstanceOf( Organic_Sessions_Daily_Repository::class, - $this->getPropertyValue( $this->instance, 'organic_sessions_daily_repository' ) + $this->getPropertyValue( $this->instance, 'organic_sessions_daily_repository' ), ); $this->assertInstanceOf( Search_Ranking_Compare_Repository::class, - $this->getPropertyValue( $this->instance, 'search_ranking_compare_repository' ) + $this->getPropertyValue( $this->instance, 'search_ranking_compare_repository' ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Get_Metrics_Test.php b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Get_Metrics_Test.php index 04104b69f49..ca7b45c336e 100644 --- a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Get_Metrics_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Get_Metrics_Test.php @@ -66,7 +66,7 @@ public function test_get_time_based_seo_metrics( ->expects( '__construct' ) ->with( [], - 200 + 200, ) ->once(); @@ -87,8 +87,8 @@ static function ( $request_parameters ) { && $request_parameters->get_limit() === 5 && $request_parameters->get_dimensions() === [ 'page' ] && self::has_27_days_interval( $request_parameters ); - } - ) + }, + ), ) ->times( $top_pages_count ) ->andReturn( $data_container_mock ); @@ -103,8 +103,8 @@ static function ( $request_parameters ) { && $request_parameters->get_limit() === 5 && $request_parameters->get_dimensions() === [ 'query' ] && self::has_27_days_interval( $request_parameters ); - } - ) + }, + ), ) ->times( $top_queries_count ) ->andReturn( $data_container_mock ); @@ -120,8 +120,8 @@ static function ( $request_parameters ) { && $request_parameters->get_dimension_filters() === [ 'sessionDefaultChannelGrouping' => [ 'Organic Search' ] ] && self::has_27_days_interval( $request_parameters ) && self::has_27_days_compare_interval( $request_parameters ); - } - ) + }, + ), ) ->times( $organic_sessions_compare_count ) ->andReturn( $data_container_mock ); @@ -141,8 +141,8 @@ static function ( $request_parameters ) { && $request_parameters->get_dimension_filters() === [ 'sessionDefaultChannelGrouping' => [ 'Organic Search' ] ] && $request_parameters->get_order_by() === $order_by && self::has_27_days_interval( $request_parameters ); - } - ) + }, + ), ) ->times( $organic_sessions_daily_count ) ->andReturn( $data_container_mock ); @@ -157,8 +157,8 @@ static function ( $request_parameters ) { && $request_parameters->get_dimensions() === [ 'date' ] && self::has_27_days_interval( $request_parameters ) && self::has_27_days_compare_interval( $request_parameters ); - } - ) + }, + ), ) ->times( $search_ranking_compare_count ) ->andReturn( $data_container_mock ); @@ -176,7 +176,7 @@ static function ( $request_parameters ) { $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->get_time_based_seo_metrics( $wp_rest_request ) + $this->instance->get_time_based_seo_metrics( $wp_rest_request ), ); } diff --git a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Register_Routes_Test.php b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Register_Routes_Test.php index 3868165b0a9..28fec4944f4 100644 --- a/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Register_Routes_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Time_Based_SEO_Metrics/Time_Based_SEO_Metrics_Route_Register_Routes_Test.php @@ -51,7 +51,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Dashboard/User_Interface/Tracking/Abstract_Setup_Steps_Tracking_Route_Test.php b/tests/Unit/Dashboard/User_Interface/Tracking/Abstract_Setup_Steps_Tracking_Route_Test.php index ea1c0c32fad..e502e7c755a 100644 --- a/tests/Unit/Dashboard/User_Interface/Tracking/Abstract_Setup_Steps_Tracking_Route_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Tracking/Abstract_Setup_Steps_Tracking_Route_Test.php @@ -48,7 +48,7 @@ protected function set_up() { $this->instance = new Setup_Steps_Tracking_Route( new Setup_Steps_Tracking_Repository_Fake(), - $this->capability_helper + $this->capability_helper, ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Constructor_Test.php b/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Constructor_Test.php index ecba9bd6998..9811cf24df5 100644 --- a/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Constructor_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Constructor_Test.php @@ -24,7 +24,7 @@ final class Setup_Steps_Tracking_Route_Constructor_Test extends Abstract_Setup_S public function test_construct() { $this->assertInstanceOf( Setup_Steps_Tracking_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'setup_steps_tracking_repository' ) + $this->getPropertyValue( $this->instance, 'setup_steps_tracking_repository' ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Register_Routes_Test.php b/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Register_Routes_Test.php index d302bafd5f4..923638c2031 100644 --- a/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Register_Routes_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Tracking/Setup_Steps_Tracking_Route_Register_Routes_Test.php @@ -60,7 +60,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_No_Valid_Params_Test.php b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_No_Valid_Params_Test.php index 9ecd6e0f598..c51475eb51e 100644 --- a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_No_Valid_Params_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_No_Valid_Params_Test.php @@ -52,7 +52,7 @@ public function test_track_setup_steps() { $this->assertInstanceOf( 'WP_Error', - $this->instance->track_setup_steps( $wp_rest_request ) + $this->instance->track_setup_steps( $wp_rest_request ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Fails_Test.php b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Fails_Test.php index 99629674f52..74e3e45396e 100644 --- a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Fails_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Fails_Test.php @@ -52,7 +52,7 @@ protected function set_up() { $this->instance = new Setup_Steps_Tracking_Route( new Setup_Steps_Tracking_Repository_Fake( true, false ), - $this->capability_helper + $this->capability_helper, ); } @@ -70,7 +70,7 @@ public function test_track_setup_steps() { [ 'success' => false, ], - 400 + 400, ) ->once(); @@ -102,7 +102,7 @@ public function test_track_setup_steps() { $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->track_setup_steps( $wp_rest_request ) + $this->instance->track_setup_steps( $wp_rest_request ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Throws_Exception_Test.php b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Throws_Exception_Test.php index ccac93808b4..7703da57fa4 100644 --- a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Throws_Exception_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Set_Data_Throws_Exception_Test.php @@ -51,7 +51,7 @@ protected function set_up() { $this->instance = new Setup_Steps_Tracking_Route( new Setup_Steps_Tracking_Repository_Fake( false, true ), - $this->capability_helper + $this->capability_helper, ); } @@ -89,7 +89,7 @@ public function test_track_setup_steps() { $this->assertInstanceOf( 'WP_Error', - $this->instance->track_setup_steps( $wp_rest_request ) + $this->instance->track_setup_steps( $wp_rest_request ), ); } } diff --git a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Test.php b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Test.php index 0c9298a4ae0..84f4aa3140a 100644 --- a/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Test.php +++ b/tests/Unit/Dashboard/User_Interface/Tracking/Track_Setup_Steps_Test.php @@ -42,7 +42,7 @@ public function test_track_setup_steps( $expected_success, $expected_status, $se [ 'success' => $expected_success, ], - $expected_status + $expected_status, ) ->once(); @@ -74,7 +74,7 @@ public function test_track_setup_steps( $expected_success, $expected_status, $se $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->track_setup_steps( $wp_rest_request ) + $this->instance->track_setup_steps( $wp_rest_request ), ); } diff --git a/tests/Unit/Database/Migration_Runner_Test.php b/tests/Unit/Database/Migration_Runner_Test.php index d2097f1c136..8edfa92fa6c 100644 --- a/tests/Unit/Database/Migration_Runner_Test.php +++ b/tests/Unit/Database/Migration_Runner_Test.php @@ -44,7 +44,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [], - Migration_Runner::get_conditionals() + Migration_Runner::get_conditionals(), ); } diff --git a/tests/Unit/Database/Migration_Status_Test.php b/tests/Unit/Database/Migration_Status_Test.php index c8036bf9f28..daad9a533b2 100644 --- a/tests/Unit/Database/Migration_Status_Test.php +++ b/tests/Unit/Database/Migration_Status_Test.php @@ -86,7 +86,7 @@ public function test_should_run_migration_with_old_lock() { [ 'version' => '1.0', 'lock' => \strtotime( '-20 minutes' ), - ] + ], ); $instance = new Migration_Status(); @@ -129,7 +129,7 @@ public function test_should_not_run_migration_with_lock() { [ 'version' => '1.0', 'lock' => \strtotime( 'now' ), - ] + ], ); $instance = new Migration_Status(); @@ -254,7 +254,7 @@ public function test_get_error() { [ 'version' => '1.0', 'error' => $error, - ] + ], ); $instance = new Migration_Status(); diff --git a/tests/Unit/Editors/Domain/Analysis_Features/Analysis_Features_List_Test.php b/tests/Unit/Editors/Domain/Analysis_Features/Analysis_Features_List_Test.php index 6d4c599ba9a..7fd1c7bf98b 100644 --- a/tests/Unit/Editors/Domain/Analysis_Features/Analysis_Features_List_Test.php +++ b/tests/Unit/Editors/Domain/Analysis_Features/Analysis_Features_List_Test.php @@ -39,7 +39,7 @@ public function test_parse_to_legacy_array(): void { 'legacy-key-false' => false, 'legacy-key-true' => true, ], - $this->instance->parse_to_legacy_array() + $this->instance->parse_to_legacy_array(), ); } @@ -59,7 +59,7 @@ public function test_parse_to_array(): void { 'name-false' => false, 'name-true' => true, ], - $this->instance->to_array() + $this->instance->to_array(), ); } diff --git a/tests/Unit/Editors/Domain/Seo/Description_Test.php b/tests/Unit/Editors/Domain/Seo/Description_Test.php index 718e7df7ae4..bdf459596aa 100644 --- a/tests/Unit/Editors/Domain/Seo/Description_Test.php +++ b/tests/Unit/Editors/Domain/Seo/Description_Test.php @@ -45,7 +45,7 @@ public function test_to_array(): void { 'description_template' => 'a-template', 'description_date' => '01-01-1970', ], - $this->instance->to_array() + $this->instance->to_array(), ); } @@ -62,7 +62,7 @@ public function test_to_legacy_array(): void { 'metadesc_template' => 'a-template', 'metaDescriptionDate' => '01-01-1970', ], - $this->instance->to_legacy_array() + $this->instance->to_legacy_array(), ); } } diff --git a/tests/Unit/Editors/Domain/Seo/Keyphrase_Test.php b/tests/Unit/Editors/Domain/Seo/Keyphrase_Test.php index 396fe1d85f7..1baaaceb20c 100644 --- a/tests/Unit/Editors/Domain/Seo/Keyphrase_Test.php +++ b/tests/Unit/Editors/Domain/Seo/Keyphrase_Test.php @@ -45,7 +45,7 @@ public function test_to_array(): void { 'keyphrase_usage' => [ 'post' => 1 ], 'keyphrase_usage_per_type' => [ 'post' => 2 ], ], - $this->instance->to_array() + $this->instance->to_array(), ); } @@ -62,7 +62,7 @@ public function test_to_legacy_array(): void { 'keyword_usage' => [ 'post' => 1 ], 'keyword_usage_post_types' => [ 'post' => 2 ], ], - $this->instance->to_legacy_array() + $this->instance->to_legacy_array(), ); } } diff --git a/tests/Unit/Editors/Domain/Seo/Social_Test.php b/tests/Unit/Editors/Domain/Seo/Social_Test.php index c2bf3d3a3cd..93c765934b2 100644 --- a/tests/Unit/Editors/Domain/Seo/Social_Test.php +++ b/tests/Unit/Editors/Domain/Seo/Social_Test.php @@ -47,7 +47,7 @@ public function test_to_array(): void { 'social_image_template' => 'social-image-template', 'first_content_image_social_preview' => 'https://wordpress.test/image.png', ], - $this->instance->to_array() + $this->instance->to_array(), ); } @@ -66,7 +66,7 @@ public function test_to_legacy_array(): void { 'social_image_template' => 'social-image-template', 'first_content_image' => 'https://wordpress.test/image.png', ], - $this->instance->to_legacy_array() + $this->instance->to_legacy_array(), ); } } diff --git a/tests/Unit/Editors/Domain/Seo/Title_Test.php b/tests/Unit/Editors/Domain/Seo/Title_Test.php index 2d3f6e4c2ae..432f8e47f26 100644 --- a/tests/Unit/Editors/Domain/Seo/Title_Test.php +++ b/tests/Unit/Editors/Domain/Seo/Title_Test.php @@ -45,7 +45,7 @@ public function test_to_array(): void { 'title_template' => 'a-title', 'title_template_no_fallback' => 'a-fb-title', ], - $this->instance->to_array() + $this->instance->to_array(), ); } @@ -62,7 +62,7 @@ public function test_to_legacy_array(): void { 'title_template' => 'a-title', 'title_template_no_fallback' => 'a-fb-title', ], - $this->instance->to_legacy_array() + $this->instance->to_legacy_array(), ); } } diff --git a/tests/Unit/Editors/Framework/Integrations/Semrush_Test.php b/tests/Unit/Editors/Framework/Integrations/Semrush_Test.php index dbae19ecc30..8bcccd31b4b 100644 --- a/tests/Unit/Editors/Framework/Integrations/Semrush_Test.php +++ b/tests/Unit/Editors/Framework/Integrations/Semrush_Test.php @@ -89,7 +89,7 @@ public function test_to_legacy_array() { ->andReturn( (object) [ 'classes' => $this->classes, - ] + ], ); $this->options ->expects( 'get' ) @@ -108,7 +108,7 @@ public function test_to_legacy_array() { 'countryCode' => true, 'SEMrushLoginStatus' => true, ], - $this->instance->to_legacy_array() + $this->instance->to_legacy_array(), ); } diff --git a/tests/Unit/Editors/Framework/Integrations/Wincher_Test.php b/tests/Unit/Editors/Framework/Integrations/Wincher_Test.php index 34cfafc6c09..4984c5b7629 100644 --- a/tests/Unit/Editors/Framework/Integrations/Wincher_Test.php +++ b/tests/Unit/Editors/Framework/Integrations/Wincher_Test.php @@ -102,7 +102,7 @@ public function test_to_legacy_array() { 'wincherWebsiteId' => 'some-id', 'wincherAutoAddKeyphrases' => true, ], - $this->instance->to_legacy_array() + $this->instance->to_legacy_array(), ); } diff --git a/tests/Unit/Elementor/Infrastructure/Request_Post_Test.php b/tests/Unit/Elementor/Infrastructure/Request_Post_Test.php index 5bc7961c693..4217197604b 100644 --- a/tests/Unit/Elementor/Infrastructure/Request_Post_Test.php +++ b/tests/Unit/Elementor/Infrastructure/Request_Post_Test.php @@ -249,7 +249,7 @@ public static function get_post_id_data_provider(): array { 'id' => 123, ], ], - ] + ], ), 'return_value' => 123, ], @@ -298,7 +298,7 @@ public static function get_post_id_data_provider(): array { 'id' => 123, ], ], - ] + ], ), 'return_value' => null, ], @@ -317,7 +317,7 @@ public static function get_post_id_data_provider(): array { 'id' => '123', ], ], - ] + ], ), 'return_value' => 123, ], @@ -336,7 +336,7 @@ public static function get_post_id_data_provider(): array { 'id' => '2e2', ], ], - ] + ], ), 'return_value' => 200, ], @@ -355,7 +355,7 @@ public static function get_post_id_data_provider(): array { 'id' => '123.456', ], ], - ] + ], ), 'return_value' => 123, ], @@ -372,7 +372,7 @@ public static function get_post_id_data_provider(): array { 'action' => 'get_document_config', 'data' => [], ], - ] + ], ), 'return_value' => null, ], @@ -388,7 +388,7 @@ public static function get_post_id_data_provider(): array { 'document-1' => [ 'action' => 'get_document_config', ], - ] + ], ), 'return_value' => null, ], @@ -407,7 +407,7 @@ public static function get_post_id_data_provider(): array { 'id' => 123, ], ], - ] + ], ), 'return_value' => null, ], @@ -426,7 +426,7 @@ public static function get_post_id_data_provider(): array { 'id' => 123, ], ], - ] + ], ), 'return_value' => null, ], @@ -445,7 +445,7 @@ public static function get_post_id_data_provider(): array { 'id' => 123, ], ], - ] + ], ), 'return_value' => null, ], diff --git a/tests/Unit/Exceptions/Importing/Aioseo_Validation_Exception_Test.php b/tests/Unit/Exceptions/Importing/Aioseo_Validation_Exception_Test.php index b33b6024945..dd043f4e71f 100644 --- a/tests/Unit/Exceptions/Importing/Aioseo_Validation_Exception_Test.php +++ b/tests/Unit/Exceptions/Importing/Aioseo_Validation_Exception_Test.php @@ -28,7 +28,7 @@ public function test_constructor() { self::assertEquals( 'The validation of the AIOSEO data structure has failed.', - $instance->getMessage() + $instance->getMessage(), ); } } diff --git a/tests/Unit/Exceptions/Indexable/Invalid_Term_Exception_Test.php b/tests/Unit/Exceptions/Indexable/Invalid_Term_Exception_Test.php index cd3acb2fa17..8c40b840b78 100644 --- a/tests/Unit/Exceptions/Indexable/Invalid_Term_Exception_Test.php +++ b/tests/Unit/Exceptions/Indexable/Invalid_Term_Exception_Test.php @@ -28,7 +28,7 @@ public function test_constructor() { self::assertEquals( 'The term is considered invalid. The following reason was given by WordPress: A WordPress reason.', - $instance->getMessage() + $instance->getMessage(), ); } } diff --git a/tests/Unit/Exceptions/Indexable/Post_Not_Found_Exception_Test.php b/tests/Unit/Exceptions/Indexable/Post_Not_Found_Exception_Test.php index 42cad1b3496..673d8007e94 100644 --- a/tests/Unit/Exceptions/Indexable/Post_Not_Found_Exception_Test.php +++ b/tests/Unit/Exceptions/Indexable/Post_Not_Found_Exception_Test.php @@ -28,7 +28,7 @@ public function test_constructor() { self::assertEquals( 'The post could not be found.', - $instance->getMessage() + $instance->getMessage(), ); } } diff --git a/tests/Unit/Exceptions/Indexable/Term_Not_Found_Exception_Test.php b/tests/Unit/Exceptions/Indexable/Term_Not_Found_Exception_Test.php index 3b1a39a216a..cddee4bdcdc 100644 --- a/tests/Unit/Exceptions/Indexable/Term_Not_Found_Exception_Test.php +++ b/tests/Unit/Exceptions/Indexable/Term_Not_Found_Exception_Test.php @@ -28,7 +28,7 @@ public function test_constructor() { self::assertEquals( 'The term could not be found.', - $instance->getMessage() + $instance->getMessage(), ); } } diff --git a/tests/Unit/General/User_Interface/General_Page_Integration_Test.php b/tests/Unit/General/User_Interface/General_Page_Integration_Test.php index da40fbe2d43..c2b9aeaa4b9 100644 --- a/tests/Unit/General/User_Interface/General_Page_Integration_Test.php +++ b/tests/Unit/General/User_Interface/General_Page_Integration_Test.php @@ -164,7 +164,7 @@ public function set_up() { $this->options_helper, $this->woocommerce_conditional, $this->addon_manager, - $this->task_list_configuration + $this->task_list_configuration, ); } @@ -191,8 +191,8 @@ public function test_construct() { $this->options_helper, $this->woocommerce_conditional, $this->addon_manager, - $this->task_list_configuration - ) + $this->task_list_configuration, + ), ); } @@ -209,7 +209,7 @@ public function test_get_conditionals() { Admin_Conditional::class, Non_Network_Admin_Conditional::class, ], - General_Page_Integration::get_conditionals() + General_Page_Integration::get_conditionals(), ); } @@ -274,7 +274,7 @@ public function test_add_page() { [ 'page1', '', 'Page 1', 'manage_options', 'page1', [ 'custom_display_page' ] ], [ 'page2', '', 'Page 2', 'manage_options', 'page2', [ 'custom_display_page' ] ], [ 'page3', '', 'Page 3', 'manage_options', 'page3', [ 'custom_display_page' ] ], - ] + ], ); // Assert that the new page was added at index 0. @@ -374,7 +374,7 @@ public function test_enqueue_assets() { [ 'enabled' => true, 'tasksConfiguration' => [], - ] + ], ); $this->expect_get_script_data(); diff --git a/tests/Unit/General/User_Interface/Opt_In_Route/Constructor_Test.php b/tests/Unit/General/User_Interface/Opt_In_Route/Constructor_Test.php index bc64bf88b31..abbd834bb0b 100644 --- a/tests/Unit/General/User_Interface/Opt_In_Route/Constructor_Test.php +++ b/tests/Unit/General/User_Interface/Opt_In_Route/Constructor_Test.php @@ -24,12 +24,12 @@ final class Constructor_Test extends Abstract_Opt_In_Route_Test { public function test_constructor() { $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); $this->assertInstanceOf( Capability_Helper::class, - $this->getPropertyValue( $this->instance, 'capability_helper' ) + $this->getPropertyValue( $this->instance, 'capability_helper' ), ); } } diff --git a/tests/Unit/General/User_Interface/Opt_In_Route/Get_Conditional_Test.php b/tests/Unit/General/User_Interface/Opt_In_Route/Get_Conditional_Test.php index ece9fdcd79e..541ebf640dd 100644 --- a/tests/Unit/General/User_Interface/Opt_In_Route/Get_Conditional_Test.php +++ b/tests/Unit/General/User_Interface/Opt_In_Route/Get_Conditional_Test.php @@ -23,7 +23,7 @@ final class Get_Conditional_Test extends Abstract_Opt_In_Route_Test { public function test_get_conditionals() { $this->assertEquals( [ User_Can_Manage_Wpseo_Options_Conditional::class ], - $this->instance::get_conditionals() + $this->instance::get_conditionals(), ); } } diff --git a/tests/Unit/General/User_Interface/Opt_In_Route/Register_Routes_Test.php b/tests/Unit/General/User_Interface/Opt_In_Route/Register_Routes_Test.php index 0b5cd44a266..b426c9599dc 100644 --- a/tests/Unit/General/User_Interface/Opt_In_Route/Register_Routes_Test.php +++ b/tests/Unit/General/User_Interface/Opt_In_Route/Register_Routes_Test.php @@ -38,7 +38,7 @@ public function test_register_routes() { 'validate_callback' => [ $this->instance, 'validate_key' ], ], ], - ] + ], ) ->once(); diff --git a/tests/Unit/Generators/Breadcrumbs_Generator_Test.php b/tests/Unit/Generators/Breadcrumbs_Generator_Test.php index c3d7d1b6ca9..f327c38e990 100644 --- a/tests/Unit/Generators/Breadcrumbs_Generator_Test.php +++ b/tests/Unit/Generators/Breadcrumbs_Generator_Test.php @@ -244,7 +244,7 @@ public function test_generate( $scenario, $page_for_posts, $breadcrumb_home, $fr $this->assertEquals( $expected, \array_slice( $this->instance->generate( $this->context ), -2 ), - $message + $message, ); } @@ -344,7 +344,7 @@ public function test_with_date_archive( $scenario, $is_paged, $current_page, $ex $this->assertEquals( $expected, - \array_slice( $this->instance->generate( $this->context ), -2 ) + \array_slice( $this->instance->generate( $this->context ), -2 ), ); } diff --git a/tests/Unit/Generators/Open_Graph_Image_Generator_Test.php b/tests/Unit/Generators/Open_Graph_Image_Generator_Test.php index a55d60c646a..7f7e647db0e 100644 --- a/tests/Unit/Generators/Open_Graph_Image_Generator_Test.php +++ b/tests/Unit/Generators/Open_Graph_Image_Generator_Test.php @@ -104,13 +104,13 @@ protected function set_up() { $this->options = Mockery::mock( Options_Helper::class ); $this->open_graph_image = Mockery::mock( Open_Graph_Image_Helper::class, - [ $this->url, $this->image ] + [ $this->url, $this->image ], ); $this->image_container = Mockery::mock( Images::class, [ $this->image, $this->url ] )->makePartial(); $this->instance = Mockery::mock( Open_Graph_Image_Generator::class, - [ $this->open_graph_image, $this->image, $this->options, $this->url ] + [ $this->open_graph_image, $this->image, $this->options, $this->url ], )->shouldAllowMockingProtectedMethods()->makePartial(); $this->instance @@ -235,7 +235,7 @@ public function test_generate_with_image_url_from_indexable_with_open_graph_imag 'height' => 1024, 'width' => 2048, 'url' => 'image.jpg', - ] + ], ); $this->instance->expects( 'add_from_templates' )->andReturnNull(); diff --git a/tests/Unit/Generators/Schema/Article_Test.php b/tests/Unit/Generators/Schema/Article_Test.php index 6eb53063e0e..6d04e681abd 100644 --- a/tests/Unit/Generators/Schema/Article_Test.php +++ b/tests/Unit/Generators/Schema/Article_Test.php @@ -300,7 +300,7 @@ static function ( $data ) { $data['inLanguage'] = 'language'; return $data; - } + }, ); Monkey\Functions\expect( 'post_type_supports' ) diff --git a/tests/Unit/Generators/Schema/Author_Test.php b/tests/Unit/Generators/Schema/Author_Test.php index cb9b6d0e3d8..bc0a4b0db13 100644 --- a/tests/Unit/Generators/Schema/Author_Test.php +++ b/tests/Unit/Generators/Schema/Author_Test.php @@ -289,7 +289,7 @@ public function test_generate_on_posts_when_site_does_not_represent_author() { 'facebook' => 'https://facebook.example.org/admin', 'instagram' => 'https://instagram.example.org/admin', 'linkedin' => 'https://linkedin.example.org/admin', - ] + ], ); $this->set_pronouns_expectations( $user_id ); @@ -464,7 +464,7 @@ private function set_helpers_expectations( $user_data ) { 'url' => 'http://example.com/image.png', ], $user_data->display_name, - false + false, ) ->andReturn( 'our_image_schema' ); } diff --git a/tests/Unit/Generators/Schema/HowTo_Test.php b/tests/Unit/Generators/Schema/HowTo_Test.php index 4f82c1f5898..556f5304d26 100644 --- a/tests/Unit/Generators/Schema/HowTo_Test.php +++ b/tests/Unit/Generators/Schema/HowTo_Test.php @@ -172,7 +172,7 @@ static function ( $data ) { $data['inLanguage'] = 'language'; return $data; - } + }, ); $this->post @@ -271,7 +271,7 @@ public function test_empty_step() { // Remove JSON text and -name attributes. unset( $blocks['yoast/how-to-block'][0]['attrs']['steps'][0]['jsonText'], - $blocks['yoast/how-to-block'][0]['attrs']['steps'][0]['jsonName'] + $blocks['yoast/how-to-block'][0]['attrs']['steps'][0]['jsonName'], ); $schema = $this->base_schema; @@ -293,7 +293,7 @@ public function test_empty_steps() { $blocks = $this->base_blocks; // Remove the steps attribute. unset( - $blocks['yoast/how-to-block'][0]['attrs']['steps'] + $blocks['yoast/how-to-block'][0]['attrs']['steps'], ); $schema = $this->base_schema; @@ -335,7 +335,7 @@ public function test_generate_step_with_image() { ->expects( 'generate_from_url' ) ->with( '#schema-image-94025919e8fe3836562573a84a14a305', - 'https://example.com/wp-content/uploads/2020/02/download.jpeg' + 'https://example.com/wp-content/uploads/2020/02/download.jpeg', ) ->andReturn( [ @@ -345,7 +345,7 @@ public function test_generate_step_with_image() { 'url' => 'https://example.com/wp-content/uploads/2020/02/download.jpeg', 'width' => 474, 'height' => 474, - ] + ], ); $schema = $this->base_schema; diff --git a/tests/Unit/Generators/Schema/Organization_Test.php b/tests/Unit/Generators/Schema/Organization_Test.php index 1aa61c6c8c3..a9141ff1c3f 100644 --- a/tests/Unit/Generators/Schema/Organization_Test.php +++ b/tests/Unit/Generators/Schema/Organization_Test.php @@ -90,7 +90,7 @@ protected function set_up() { $this->instance = new Organization( $this->image, $this->options, - $this->html + $this->html, ); $this->instance->context = $this->context; diff --git a/tests/Unit/Generators/Schema/Person_Test.php b/tests/Unit/Generators/Schema/Person_Test.php index cb078c033a7..fe8d59f32c4 100644 --- a/tests/Unit/Generators/Schema/Person_Test.php +++ b/tests/Unit/Generators/Schema/Person_Test.php @@ -408,7 +408,7 @@ public function test_generate_social_profiles_non_string_or_falsy_values() { 'instagram' => 1234, 'youtube' => false, 'wikipedia' => 'wiki', - ] + ], ); $this->expects_for_pronouns( $this->instance->context->site_user_id, '' ); diff --git a/tests/Unit/Generators/Schema/WebPage_Test.php b/tests/Unit/Generators/Schema/WebPage_Test.php index 5642b010fb1..79d74a4d106 100644 --- a/tests/Unit/Generators/Schema/WebPage_Test.php +++ b/tests/Unit/Generators/Schema/WebPage_Test.php @@ -171,7 +171,7 @@ static function ( $data ) { $data['inLanguage'] = 'the-language'; return $data; - } + }, ); Monkey\Filters\expectApplied( 'wpseo_schema_webpage_potential_action_target' ) @@ -208,7 +208,7 @@ public function test_generate_with_provider( $values_to_test, $expected, $messag [ 'WebPage' ], 1, 1, - 1 + 1, ); $this->assertEquals( $expected, $this->instance->generate(), $message ); @@ -229,7 +229,7 @@ public function test_generate_on_front_page_site_does_not_represents_reference() [ 'WebPage' ], 1, 1, - 1 + 1, ); $expected = [ @@ -272,7 +272,7 @@ public function test_generate_on_front_page_site_represents_reference() { [ 'WebPage' ], 1, 1, - 1 + 1, ); $expected = [ @@ -322,7 +322,7 @@ public function test_generate_object_post_site_represents_true() { [ 'WebPage' ], 1, 1, - 1 + 1, ); $expected = [ @@ -371,7 +371,7 @@ public function test_generate_object_post_site_represents_false() { [ 'WebPage' ], 1, 1, - 1 + 1, ); $this->id @@ -421,7 +421,7 @@ public function test_generate_description_not_empty() { [ 'WebPage' ], 1, 1, - 1 + 1, ); $this->html @@ -474,7 +474,7 @@ public function test_generate_object_type_home_page() { 'CollectionPage', 0, 0, - 0 + 0, ); $expected = [ @@ -509,7 +509,7 @@ public function test_generate_home_static_page() { 'CollectionPage', 1, 1, - 0 + 0, ); $expected = [ diff --git a/tests/Unit/Generators/Schema/Website_Test.php b/tests/Unit/Generators/Schema/Website_Test.php index f0aaac2bb14..40316438b98 100644 --- a/tests/Unit/Generators/Schema/Website_Test.php +++ b/tests/Unit/Generators/Schema/Website_Test.php @@ -111,7 +111,7 @@ static function ( $data ) { $data['inLanguage'] = 'language'; return $data; - } + }, ); $expected = [ @@ -173,7 +173,7 @@ static function ( $data ) { $data['inLanguage'] = 'language'; return $data; - } + }, ); $expected = [ diff --git a/tests/Unit/Generators/Schema_Generator_Test.php b/tests/Unit/Generators/Schema_Generator_Test.php index e4e8fd160eb..1a25c7a5a93 100644 --- a/tests/Unit/Generators/Schema_Generator_Test.php +++ b/tests/Unit/Generators/Schema_Generator_Test.php @@ -120,13 +120,13 @@ protected function set_up() { Article_Helper::class => $this->article, Date_Helper::class => $this->date, Language_Helper::class => new Language_Helper(), - ] + ], ); $helpers = $this->create_helper_surface( $container ); $this->instance = Mockery::mock( Schema_Generator::class, - [ $helpers, $this->replace_vars_helper ] + [ $helpers, $this->replace_vars_helper ], )->shouldAllowMockingProtectedMethods()->makePartial(); $this->context = Mockery::mock( @@ -139,7 +139,7 @@ protected function set_up() { Mockery::mock( WPSEO_Replace_Vars::class ), Mockery::mock( Site_Helper::class ), Mockery::mock( User_Helper::class ), - ] + ], )->shouldAllowMockingProtectedMethods(); $this->context->blocks = [ @@ -317,7 +317,7 @@ public function test_generate_with_no_blocks() { ], ], ], - $this->instance->generate( $this->context ) + $this->instance->generate( $this->context ), ); } @@ -409,7 +409,7 @@ public function test_generate_with_empty_breadcrumb() { ], ], ], - $this->instance->generate( $this->context ) + $this->instance->generate( $this->context ), ); } @@ -485,7 +485,7 @@ public function test_generate_with_blocks() { $this->assertEquals( $this->get_expected_schema(), - $this->instance->generate( $this->context ) + $this->instance->generate( $this->context ), ); } @@ -684,7 +684,7 @@ public function test_generate_with_block_not_having_generated_output() { $this->assertEquals( $this->get_expected_schema(), - $this->instance->generate( $this->context ) + $this->instance->generate( $this->context ), ); } @@ -769,7 +769,7 @@ public function test_validate_type_singular_array() { ], ], 'inLanguage' => 'English', - ] + ], ); $this->current_page->expects( 'is_home_static_page' )->andReturns( false ); @@ -798,7 +798,7 @@ public function test_validate_type_singular_array() { ], 'inLanguage' => 'English', ], - $this->instance->generate( $this->context )['@graph'][1] + $this->instance->generate( $this->context )['@graph'][1], ); } @@ -886,7 +886,7 @@ public function test_validate_type_unique_array() { ], ], 'inLanguage' => 'English', - ] + ], ); $this->assertEquals( @@ -912,7 +912,7 @@ public function test_validate_type_unique_array() { ], 'inLanguage' => 'English', ], - $this->instance->generate( $this->context )['@graph'][1] + $this->instance->generate( $this->context )['@graph'][1], ); } @@ -1009,7 +1009,7 @@ public function test_get_graph_pieces_on_single_post_with_password_required() { ], ], ], - $this->instance->generate( $this->context ) + $this->instance->generate( $this->context ), ); } @@ -1126,7 +1126,7 @@ public function test_generate_with_search_page() { ], ], ], - $this->instance->generate( $this->context ) + $this->instance->generate( $this->context ), ); } @@ -1199,7 +1199,7 @@ public function test_get_graph_pieces_on_scheduled_post() { $this->assertEquals( $expected_schema, - $this->instance->generate( $this->context ) + $this->instance->generate( $this->context ), ); } diff --git a/tests/Unit/Generators/Twitter_Image_Generator_Test.php b/tests/Unit/Generators/Twitter_Image_Generator_Test.php index 8c9d87f857b..b8b9266b6a8 100644 --- a/tests/Unit/Generators/Twitter_Image_Generator_Test.php +++ b/tests/Unit/Generators/Twitter_Image_Generator_Test.php @@ -87,7 +87,7 @@ protected function set_up() { $this->instance = Mockery::mock( Twitter_Image_Generator::class, - [ $this->image, $this->url, $this->twitter_image ] + [ $this->image, $this->url, $this->twitter_image ], )->shouldAllowMockingProtectedMethods()->makePartial(); $this->instance diff --git a/tests/Unit/Helpers/Aioseo_Helper_Test.php b/tests/Unit/Helpers/Aioseo_Helper_Test.php index a5b08fa5687..a6f6c557144 100644 --- a/tests/Unit/Helpers/Aioseo_Helper_Test.php +++ b/tests/Unit/Helpers/Aioseo_Helper_Test.php @@ -51,7 +51,7 @@ public function set_up() { $this->wpdb_helper = Mockery::mock( Wpdb_Helper::class ); $this->instance = new Aioseo_Helper( $this->wpdb, - $this->wpdb_helper + $this->wpdb_helper, ); $this->wpdb->prefix = 'wp_'; diff --git a/tests/Unit/Helpers/Blocks_Helper_Test.php b/tests/Unit/Helpers/Blocks_Helper_Test.php index c79761de125..45dd78d540a 100644 --- a/tests/Unit/Helpers/Blocks_Helper_Test.php +++ b/tests/Unit/Helpers/Blocks_Helper_Test.php @@ -116,7 +116,7 @@ public function test_get_all_blocks_from_content() { ], ], ], - ] + ], ); $this->instance @@ -145,7 +145,7 @@ public function test_get_all_blocks_from_content() { ], ], ], - $this->instance->get_all_blocks_from_content( 'post content' ) + $this->instance->get_all_blocks_from_content( 'post content' ), ); } diff --git a/tests/Unit/Helpers/Capability_Helper_Test.php b/tests/Unit/Helpers/Capability_Helper_Test.php index 6e9dc1a7635..a3ef13045ca 100644 --- a/tests/Unit/Helpers/Capability_Helper_Test.php +++ b/tests/Unit/Helpers/Capability_Helper_Test.php @@ -184,7 +184,7 @@ public function test_get_applicable_roles_no_role() { (object) [ 'name' => 'administrator', 'capabilities' => $capabilities['administrator'], - ] + ], ); $wp_roles->expects( 'get_role' ) @@ -279,7 +279,7 @@ private function mock_wp_roles( $roles, $capabilities ) { (object) [ 'name' => $id, 'capabilities' => $capabilities[ $id ], - ] + ], ); } diff --git a/tests/Unit/Helpers/Crawl_Cleanup_Helper_Test.php b/tests/Unit/Helpers/Crawl_Cleanup_Helper_Test.php index 9fc2255286d..d7caefbd929 100644 --- a/tests/Unit/Helpers/Crawl_Cleanup_Helper_Test.php +++ b/tests/Unit/Helpers/Crawl_Cleanup_Helper_Test.php @@ -75,7 +75,7 @@ protected function set_up() { $this->current_page_helper, $this->options_helper, $this->url_helper, - $this->redirect_helper + $this->redirect_helper, ); } @@ -106,7 +106,7 @@ public function test_should_avoid_redirect( $is_robots, $sitemap, $get_response, [ 'is_robots' => $is_robots, 'is_user_logged_in' => $is_user_logged_in, - ] + ], ); $this->assertSame( $expected, $this->instance->should_avoid_redirect() ); @@ -261,7 +261,7 @@ public function test_page_not_found_url( $is_multisite, $is_subdomain_install, $ 'is_multisite' => $is_multisite, 'is_subdomain_install' => $is_subdomain_install, 'is_main_site' => $is_main_site, - ] + ], ); Monkey\Functions\expect( 'home_url' ) @@ -330,7 +330,7 @@ public function test_taxonomy_url( $is_feed, $get_term_feed_link_times, $get_ter (object) [ 'term_id' => 108, 'taxonomy' => 'products', - ] + ], ); Monkey\Functions\expect( 'is_feed' ) @@ -523,7 +523,7 @@ public function test_get_url_type( $singular, $front, $category, $tag, $tax, $se 'is_tax' => $tax, 'is_search' => $search, 'is_404' => $is404, - ] + ], ); $this->current_page_helper @@ -585,7 +585,7 @@ public function test_do_clean_redirect() { /* translators: %1$s: Yoast SEO */ \__( '%1$s: unregistered URL parameter removed. See %2$s', 'wordpress-seo' ), 'Yoast SEO', - 'https://yoa.st/advanced-crawl-settings' + 'https://yoa.st/advanced-crawl-settings', ); $this->redirect_helper diff --git a/tests/Unit/Helpers/Current_Page_Helper_Test.php b/tests/Unit/Helpers/Current_Page_Helper_Test.php index d0a90a61a1f..0b4315c119f 100644 --- a/tests/Unit/Helpers/Current_Page_Helper_Test.php +++ b/tests/Unit/Helpers/Current_Page_Helper_Test.php @@ -623,7 +623,7 @@ static function ( $option ) { } return null; - } + }, ); $this->assertTrue( $this->instance->is_home_static_page() ); diff --git a/tests/Unit/Helpers/Date_Helper_Test.php b/tests/Unit/Helpers/Date_Helper_Test.php index 32336d57fa7..5b3791944fd 100644 --- a/tests/Unit/Helpers/Date_Helper_Test.php +++ b/tests/Unit/Helpers/Date_Helper_Test.php @@ -87,9 +87,9 @@ public static function format_provider() { 'expected' => true, ], 'Test formatting the date with an integer as date' => [ - 'date' => 123456789, + 'date' => 123_456_789, 'format' => \DATE_W3C, - 'expected' => 123456789, + 'expected' => 123_456_789, ], 'Test formatting the date with a string as date' => [ 'date' => 'this is a date', @@ -133,7 +133,7 @@ public static function format_timestamp_provider() { 'expected' => '1973-11-29 21:33:09', ], 'Test formatting an integer timestamp to a date' => [ - 'timestamp' => 123456789, + 'timestamp' => 123_456_789, 'format' => \DATE_W3C, 'expected' => '1973-11-29T21:33:09+00:00', ], @@ -165,7 +165,7 @@ public function test_format_translated() { $this->assertSame( '2020-12-31', - $this->instance->format_translated( '2020-12-31 13:37:00' ) + $this->instance->format_translated( '2020-12-31 13:37:00' ), ); } @@ -208,7 +208,7 @@ public static function data_is_valid_datetime() { 'expected' => true, ], 'Other non-string' => [ - 'input' => 123456789, + 'input' => 123_456_789, 'expected' => false, ], ]; diff --git a/tests/Unit/Helpers/Home_Url_Helper_Test.php b/tests/Unit/Helpers/Home_Url_Helper_Test.php index c7bd0a0d8e5..f06253239d3 100644 --- a/tests/Unit/Helpers/Home_Url_Helper_Test.php +++ b/tests/Unit/Helpers/Home_Url_Helper_Test.php @@ -77,7 +77,7 @@ public function test_get_parsed() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $this->assertEquals( @@ -85,7 +85,7 @@ public function test_get_parsed() { 'scheme' => 'https', 'host' => 'example.com', ], - $this->instance->get_parsed() + $this->instance->get_parsed(), ); } @@ -105,7 +105,7 @@ public function test_get_parsed_cached() { 'scheme' => 'https', 'host' => 'example.com', ], - $this->instance->get_parsed() + $this->instance->get_parsed(), ); } } diff --git a/tests/Unit/Helpers/Image_Helper_Test.php b/tests/Unit/Helpers/Image_Helper_Test.php index 1a31b936062..e0a5f868a7f 100644 --- a/tests/Unit/Helpers/Image_Helper_Test.php +++ b/tests/Unit/Helpers/Image_Helper_Test.php @@ -143,7 +143,7 @@ public function test_get_gallery_image_when_gallery_is_present() { [ 'https://example.com/media/image.jpg', 'https://example.com/media/image2.jpg', - ] + ], ); $this->assertEquals( 'https://example.com/media/image.jpg', $this->instance->get_gallery_image( 100 ) ); @@ -354,7 +354,7 @@ public function test_get_term_content_image() { $this->assertEquals( 'https://example.com/media/content_image.jpg', - $this->instance->get_term_content_image( 1337 ) + $this->instance->get_term_content_image( 1337 ), ); } @@ -448,7 +448,7 @@ public function test_get_metadata() { [ 'meta' => 'data', ], - $this->instance->get_metadata( 1337 ) + $this->instance->get_metadata( 1337 ), ); } @@ -500,7 +500,7 @@ public function test_get_attachment_image_url() { $this->assertEquals( 'https://example.org/image.jpg', - $this->instance->get_attachment_image_url( 1337, 'full' ) + $this->instance->get_attachment_image_url( 1337, 'full' ), ); } @@ -535,7 +535,7 @@ public function test_get_attachment_by_url_with_external_url_image() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $this->url_helper->expects( 'get_link_type' )->andReturn( SEO_Links::TYPE_EXTERNAL ); $this->assertEquals( 0, $this->actual_instance->get_attachment_by_url( 'https://example.com/image.jpg' ) ); @@ -555,7 +555,7 @@ public function test_get_attachment_by_url_with_external_image() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $this->url_helper->expects( 'get_link_type' )->andReturn( SEO_Links::TYPE_EXTERNAL ); $this->assertEquals( 0, $this->actual_instance->get_attachment_by_url( '' ) ); @@ -575,7 +575,7 @@ public function test_get_attachment_by_url_with_existing_indexable() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $indexable = new Indexable_Mock(); $indexable->object_type = 'post'; @@ -601,7 +601,7 @@ public function test_get_attachment_by_url_with_existing_link() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $url = \md5( 'a_dir/something' ); diff --git a/tests/Unit/Helpers/Import_Cursor_Helper_Test.php b/tests/Unit/Helpers/Import_Cursor_Helper_Test.php index cf107b47492..d68174251e9 100644 --- a/tests/Unit/Helpers/Import_Cursor_Helper_Test.php +++ b/tests/Unit/Helpers/Import_Cursor_Helper_Test.php @@ -128,7 +128,7 @@ public static function not_set_cursor_values() { [ -1 ], [ 1336 ], [ 1337 ], - [ -9223372036854775808 ], + [ -9_223_372_036_854_775_808 ], [ 1336.3 ], [ null ], ]; @@ -171,7 +171,7 @@ public static function set_cursor_values() { return [ [ 1338 ], [ 1337.5 ], - [ 9223372036854775807 ], + [ 9_223_372_036_854_775_808 ], ]; } } diff --git a/tests/Unit/Helpers/Indexable_Helper_Test.php b/tests/Unit/Helpers/Indexable_Helper_Test.php index 37eaa4655f4..3616b87c656 100644 --- a/tests/Unit/Helpers/Indexable_Helper_Test.php +++ b/tests/Unit/Helpers/Indexable_Helper_Test.php @@ -83,15 +83,15 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Environment_Helper::class, - $this->getPropertyValue( $this->instance, 'environment_helper' ) + $this->getPropertyValue( $this->instance, 'environment_helper' ), ); $this->assertInstanceOf( Indexing_Helper::class, - $this->getPropertyValue( $this->instance, 'indexing_helper' ) + $this->getPropertyValue( $this->instance, 'indexing_helper' ), ); } @@ -360,18 +360,14 @@ public function test_should_index_indexable( $is_production_mode, $should_index_ ->andReturn( $is_production_mode ); // In order to test not having an overriding "Yoast\WP\SEO\should_index_indexables" filter. - if ( $should_index_indexables === null ) { - $should_index_indexables = $is_production_mode; - } + $should_index_indexables ??= $is_production_mode; Monkey\Filters\expectApplied( 'Yoast\WP\SEO\should_index_indexables' ) ->once() ->with( $is_production_mode ) ->andReturn( $should_index_indexables ); // In order to test not having an overriding "wpseo_should_save_indexable" filter. - if ( $should_save_indexable === null ) { - $should_save_indexable = $should_index_indexables; - } + $should_save_indexable ??= $should_index_indexables; Monkey\Filters\expectApplied( 'wpseo_should_save_indexable' ) ->once() ->with( $should_index_indexables, $indexable ) diff --git a/tests/Unit/Helpers/Indexing_Helper_Test.php b/tests/Unit/Helpers/Indexing_Helper_Test.php index 1830d395f33..6b3ad1f01f6 100644 --- a/tests/Unit/Helpers/Indexing_Helper_Test.php +++ b/tests/Unit/Helpers/Indexing_Helper_Test.php @@ -113,7 +113,7 @@ protected function set_up() { $this->instance = new Indexing_Helper( $this->options_helper, $this->date_helper, - $this->notification_center + $this->notification_center, ); $this->post_indexation = Mockery::mock( Indexable_Post_Indexation_Action::class ); @@ -128,7 +128,7 @@ protected function set_up() { $this->post_type_archive_indexation, $this->general_indexation, $this->post_link_indexing_action, - $this->term_link_indexing_action + $this->term_link_indexing_action, ); } @@ -142,11 +142,11 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Date_Helper::class, - $this->getPropertyValue( $this->instance, 'date_helper' ) + $this->getPropertyValue( $this->instance, 'date_helper' ), ); } @@ -160,27 +160,27 @@ public function test_construct() { public function test_set_indexing_actions() { $this->assertInstanceOf( Indexable_Post_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'indexing_actions' )[0] + $this->getPropertyValue( $this->instance, 'indexing_actions' )[0], ); $this->assertInstanceOf( Indexable_Term_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'indexing_actions' )[1] + $this->getPropertyValue( $this->instance, 'indexing_actions' )[1], ); $this->assertInstanceOf( Indexable_Post_Type_Archive_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'indexing_actions' )[2] + $this->getPropertyValue( $this->instance, 'indexing_actions' )[2], ); $this->assertInstanceOf( Indexable_General_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'indexing_actions' )[3] + $this->getPropertyValue( $this->instance, 'indexing_actions' )[3], ); $this->assertInstanceOf( Post_Link_Indexing_Action::class, - $this->getPropertyValue( $this->instance, 'indexing_actions' )[4] + $this->getPropertyValue( $this->instance, 'indexing_actions' )[4], ); $this->assertInstanceOf( Term_Link_Indexing_Action::class, - $this->getPropertyValue( $this->instance, 'indexing_actions' )[5] + $this->getPropertyValue( $this->instance, 'indexing_actions' )[5], ); } @@ -199,7 +199,7 @@ public function test_prepare() { ->once() ->with( 'indexing_first_time', false ); - $start_time = 160934509; + $start_time = 160_934_509; $this->date_helper ->expects( 'current_time' ) @@ -312,7 +312,7 @@ public function test_get_reason() { * @return void */ public function test_get_started() { - $start_time = 160934509; + $start_time = 160_934_509; $this->options_helper ->expects( 'get' ) ->once() diff --git a/tests/Unit/Helpers/Options_Helper_Test.php b/tests/Unit/Helpers/Options_Helper_Test.php index 27b9dbcc0f8..11ab9ebd466 100644 --- a/tests/Unit/Helpers/Options_Helper_Test.php +++ b/tests/Unit/Helpers/Options_Helper_Test.php @@ -49,7 +49,7 @@ public function test_get_title_default() { ->andReturn( [ 'my-title' => 'This is a title', - ] + ], ); $this->assertEquals( 'This is a title', $this->instance->get_title_default( 'my-title' ) ); diff --git a/tests/Unit/Helpers/Pagination_Helper_Test.php b/tests/Unit/Helpers/Pagination_Helper_Test.php index 629d4b6bde6..6275a23c8ef 100644 --- a/tests/Unit/Helpers/Pagination_Helper_Test.php +++ b/tests/Unit/Helpers/Pagination_Helper_Test.php @@ -76,11 +76,11 @@ protected function tear_down() { public function test_constructor() { $this->assertInstanceOf( WP_Rewrite_Wrapper::class, - $this->getPropertyValue( $this->instance, 'wp_rewrite_wrapper' ) + $this->getPropertyValue( $this->instance, 'wp_rewrite_wrapper' ), ); $this->assertInstanceOf( WP_Query_Wrapper::class, - $this->getPropertyValue( $this->instance, 'wp_query_wrapper' ) + $this->getPropertyValue( $this->instance, 'wp_query_wrapper' ), ); } @@ -475,7 +475,7 @@ static function ( $query_var, $default_response ) { } return $default_response; - } + }, ); $this->assertSame( 2, $this->instance->get_current_page_number() ); diff --git a/tests/Unit/Helpers/Permalink_Helper_Test.php b/tests/Unit/Helpers/Permalink_Helper_Test.php index 7bb31ec5ef1..50239d6bb01 100644 --- a/tests/Unit/Helpers/Permalink_Helper_Test.php +++ b/tests/Unit/Helpers/Permalink_Helper_Test.php @@ -51,7 +51,7 @@ public function test_get_permalink_for_post_indexable() { $this->assertEquals( 'https://example.org/permalink', - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -72,7 +72,7 @@ public function test_get_permalink_for_attachment_indexable() { $this->assertEquals( 'https://example.org/attachment', - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -92,7 +92,7 @@ public function test_get_permalink_for_homepage_indexable() { $this->assertEquals( 'https://example.org/homepage', - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -126,7 +126,7 @@ public function test_get_permalink_for_term_indexable() { $this->assertEquals( 'https://example.org/term', - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -147,7 +147,7 @@ public function test_get_permalink_for_term_indexable_term_not_found() { ->andReturn( null ); $this->assertNull( - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -176,7 +176,7 @@ public function test_get_permalink_for_term_indexable_term_is_wp_error() { ->andReturn( true ); $this->assertNull( - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -197,7 +197,7 @@ public function test_get_permalink_for_search_page_indexable() { $this->assertEquals( 'https://example.org/search', - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -219,7 +219,7 @@ public function test_get_permalink_for_post_type_archive_indexable() { $this->assertEquals( 'https://example.org/post-type', - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -241,7 +241,7 @@ public function test_get_permalink_for_user_indexable() { $this->assertEquals( 'https://example.org/user/1', - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } @@ -257,7 +257,7 @@ public function test_get_permalink_for_unknown_type_indexable() { $indexable->object_type = 'unknown'; $this->assertNull( - $this->instance->get_permalink_for_indexable( $indexable ) + $this->instance->get_permalink_for_indexable( $indexable ), ); } diff --git a/tests/Unit/Helpers/Primary_Term_Helper_Test.php b/tests/Unit/Helpers/Primary_Term_Helper_Test.php index 05416434ba2..f8a6b80dd21 100644 --- a/tests/Unit/Helpers/Primary_Term_Helper_Test.php +++ b/tests/Unit/Helpers/Primary_Term_Helper_Test.php @@ -65,7 +65,7 @@ public function test_get_primary_term_taxonomies() { 'name' => 'tag', 'hierarchical' => false, ], - ] + ], ); Monkey\Functions\expect( 'get_post_type' ) @@ -102,7 +102,7 @@ public function test_get_primary_term_taxonomies_no_hierarchical() { 'name' => 'tag', 'hierarchical' => false, ], - ] + ], ); Monkey\Functions\expect( 'get_post_type' ) diff --git a/tests/Unit/Helpers/Robots_Helper_Test.php b/tests/Unit/Helpers/Robots_Helper_Test.php index c64b863bd6b..1be477b97cf 100644 --- a/tests/Unit/Helpers/Robots_Helper_Test.php +++ b/tests/Unit/Helpers/Robots_Helper_Test.php @@ -64,11 +64,11 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); $this->assertInstanceOf( Taxonomy_Helper::class, - $this->getPropertyValue( $this->instance, 'taxonomy_helper' ) + $this->getPropertyValue( $this->instance, 'taxonomy_helper' ), ); } @@ -153,8 +153,8 @@ public function test_set_robots_no_index() { [ 'index' => 'index', 'follow' => 'follow', - ] - ) + ], + ), ); } @@ -170,12 +170,12 @@ public function test_set_robots_no_index_string_given() { ->with( Robots_Helper::class . '::set_robots_no_index', '14.1', - '$robots has to be a key-value paired array.' + '$robots has to be a key-value paired array.', ); $this->assertEquals( 'noindex,follow', - $this->instance->set_robots_no_index( 'noindex,follow' ) + $this->instance->set_robots_no_index( 'noindex,follow' ), ); } } diff --git a/tests/Unit/Helpers/Robots_Txt_Helper_Test.php b/tests/Unit/Helpers/Robots_Txt_Helper_Test.php index 484aca79881..ed6cdc7abef 100644 --- a/tests/Unit/Helpers/Robots_Txt_Helper_Test.php +++ b/tests/Unit/Helpers/Robots_Txt_Helper_Test.php @@ -41,10 +41,10 @@ public function set_up() { */ public function test_construct() { $this->assertIsObject( - $this->getPropertyValue( $this->instance, 'robots_txt_user_agents' ) + $this->getPropertyValue( $this->instance, 'robots_txt_user_agents' ), ); $this->assertIsArray( - $this->getPropertyValue( $this->instance, 'robots_txt_sitemaps' ) + $this->getPropertyValue( $this->instance, 'robots_txt_sitemaps' ), ); } diff --git a/tests/Unit/Helpers/Schema/ID_Helper_Test.php b/tests/Unit/Helpers/Schema/ID_Helper_Test.php index 7a66e9d344f..9dc100063a6 100644 --- a/tests/Unit/Helpers/Schema/ID_Helper_Test.php +++ b/tests/Unit/Helpers/Schema/ID_Helper_Test.php @@ -63,7 +63,7 @@ public function test_get_user_schema_id() { $this->assertEquals( 'https://example.org/#/schema/person/1234567890', - $this->instance->get_user_schema_id( 1337, $context ) + $this->instance->get_user_schema_id( 1337, $context ), ); } @@ -85,7 +85,7 @@ public function test_get_user_schema_id_no_user_found() { $this->assertEquals( '', - $this->instance->get_user_schema_id( 1337, $context ) + $this->instance->get_user_schema_id( 1337, $context ), ); } } diff --git a/tests/Unit/Helpers/Schema/Image_Helper_Test.php b/tests/Unit/Helpers/Schema/Image_Helper_Test.php index a7f060f4317..50dcb04886c 100644 --- a/tests/Unit/Helpers/Schema/Image_Helper_Test.php +++ b/tests/Unit/Helpers/Schema/Image_Helper_Test.php @@ -84,7 +84,7 @@ public function test_generate_from_url_with_found_attachment_id() { $this->assertEquals( [], - $this->instance->generate_from_url( '#schema-image-ABC', 'https://example.org/image.jpg', 'caption' ) + $this->instance->generate_from_url( '#schema-image-ABC', 'https://example.org/image.jpg', 'caption' ), ); } @@ -110,7 +110,7 @@ public function test_generate_from_url_with_no_found_attachment_id() { $this->assertEquals( [], - $this->instance->generate_from_url( '#schema-image-ABC', 'https://example.org/image.jpg', 'caption', false, false ) + $this->instance->generate_from_url( '#schema-image-ABC', 'https://example.org/image.jpg', 'caption', false, false ), ); } @@ -139,7 +139,7 @@ public function test_generate_from_attachment_id_with_caption_and_image_dimensio [ 'width' => 256, 'height' => 512, - ] + ], ); $this->language @@ -163,8 +163,8 @@ public function test_generate_from_attachment_id_with_caption_and_image_dimensio $this->instance->generate_from_attachment_id( 'https://example.com/#/schema/logo/image/', 1337, - 'Company name' - ) + 'Company name', + ), ); } @@ -209,8 +209,8 @@ public function test_generate_from_attachment_id_with_caption_given() { $this->instance->generate_from_attachment_id( 'https://example.com/#/schema/logo/image/', 1337, - 'Company name' - ) + 'Company name', + ), ); } @@ -267,7 +267,7 @@ public function test_generate_from_attachment_id_with_no_caption_given() { $actual = $this->instance->generate_from_attachment_id( 'https://example.com/#/schema/logo/image/', 1337, - '' + '', ); $this->assertEquals( $expected, $actual ); @@ -319,7 +319,7 @@ public function test_generate_from_attachment_id_with_no_caption_given_and_no_al $actual = $this->instance->generate_from_attachment_id( 'https://example.com/#/schema/logo/image/', 1337, - '' + '', ); $this->assertEquals( $expected, $actual ); @@ -360,7 +360,7 @@ public function test_simple_image_object() { $actual = $this->instance->simple_image_object( 'https://example.com/#/schema/logo/image/', 'https://example.com/logo.jpg', - 'Image caption' + 'Image caption', ); $this->assertEquals( $expected, $actual ); diff --git a/tests/Unit/Helpers/Schema/Language_Helper_Test.php b/tests/Unit/Helpers/Schema/Language_Helper_Test.php index 39c814f90a4..13a2720b37e 100644 --- a/tests/Unit/Helpers/Schema/Language_Helper_Test.php +++ b/tests/Unit/Helpers/Schema/Language_Helper_Test.php @@ -35,7 +35,7 @@ public function test_add_piece_language() { [ 'inLanguage' => 'English', ], - $instance->add_piece_language( [] ) + $instance->add_piece_language( [] ), ); } } diff --git a/tests/Unit/Helpers/Schema/Replace_Vars_Helper_Test.php b/tests/Unit/Helpers/Schema/Replace_Vars_Helper_Test.php index 2f19c171e94..2cf212b332a 100644 --- a/tests/Unit/Helpers/Schema/Replace_Vars_Helper_Test.php +++ b/tests/Unit/Helpers/Schema/Replace_Vars_Helper_Test.php @@ -75,7 +75,7 @@ public function set_up() { $this->instance = new Replace_Vars_Helper( $this->replace_vars, $this->id_helper, - $this->date_helper + $this->date_helper, ); } @@ -168,7 +168,7 @@ public function test_registers_the_right_replace_vars() { $this->replace_vars, $this->id_helper, $this->date_helper, - ] + ], ) ->shouldAllowMockingProtectedMethods() ->makePartial(); @@ -223,7 +223,7 @@ public function test_registers_the_right_replace_vars_on_non_post() { $this->replace_vars, $this->id_helper, $this->date_helper, - ] + ], ) ->shouldAllowMockingProtectedMethods() ->makePartial(); @@ -289,7 +289,7 @@ public function test_get_identity_function() { $instance = new Replace_Vars_Helper_Double( $this->replace_vars, $this->id_helper, - $this->date_helper + $this->date_helper, ); $value = 'a_value'; $closure = $instance->get_identity_function( $value ); diff --git a/tests/Unit/Helpers/Score_Icon_Helper_Test.php b/tests/Unit/Helpers/Score_Icon_Helper_Test.php index 92e9c829108..17fe5c21a4c 100644 --- a/tests/Unit/Helpers/Score_Icon_Helper_Test.php +++ b/tests/Unit/Helpers/Score_Icon_Helper_Test.php @@ -57,7 +57,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Robots_Helper::class, - $this->getPropertyValue( $this->instance, 'robots_helper' ) + $this->getPropertyValue( $this->instance, 'robots_helper' ), ); } diff --git a/tests/Unit/Helpers/Short_Link_Helper_Test.php b/tests/Unit/Helpers/Short_Link_Helper_Test.php index b3553a51d16..dfb33560110 100644 --- a/tests/Unit/Helpers/Short_Link_Helper_Test.php +++ b/tests/Unit/Helpers/Short_Link_Helper_Test.php @@ -54,7 +54,7 @@ protected function set_up() { $this->instance = new Short_Link_Helper( $this->options_helper, - $this->product_helper + $this->product_helper, ); } diff --git a/tests/Unit/Helpers/Site_Helper_Test.php b/tests/Unit/Helpers/Site_Helper_Test.php index c94853808fd..c8e85cdcbd7 100644 --- a/tests/Unit/Helpers/Site_Helper_Test.php +++ b/tests/Unit/Helpers/Site_Helper_Test.php @@ -66,7 +66,7 @@ public function test_is_multisite_and_switched() { [ 'is_multisite' => true, 'ms_is_switched' => true, - ] + ], ); self::assertTrue( $this->instance->is_multisite_and_switched() ); diff --git a/tests/Unit/Helpers/Social_Profiles_Helper_Test.php b/tests/Unit/Helpers/Social_Profiles_Helper_Test.php index af0d922a36e..f7111c4c0c0 100644 --- a/tests/Unit/Helpers/Social_Profiles_Helper_Test.php +++ b/tests/Unit/Helpers/Social_Profiles_Helper_Test.php @@ -236,7 +236,7 @@ public function test_set_organization_social_profiles( $social_profiles, $valida $social_profiles[ $field ], static function ( $other_social_url ) { return $other_social_url !== ''; - } + }, ); } diff --git a/tests/Unit/Helpers/Url_Helper_Test.php b/tests/Unit/Helpers/Url_Helper_Test.php index 7cb46eae92b..c75fb7f235a 100644 --- a/tests/Unit/Helpers/Url_Helper_Test.php +++ b/tests/Unit/Helpers/Url_Helper_Test.php @@ -58,7 +58,7 @@ public function test_build_absolute_url() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $expected = 'https://example.com/my-page'; @@ -88,7 +88,7 @@ public function test_build_absolute_url_relative_url() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $expected = 'https://example.com/my-page'; @@ -116,7 +116,7 @@ public function test_get_url_path( $url_input, $expected ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- Mocking wp_parse_url(), this is fine. return \parse_url( $url, $component ); }, - ] + ], ); $this->assertSame( $expected, $this->instance->get_url_path( $url_input ) ); @@ -195,7 +195,7 @@ public function test_get_url_host( $url_input, $expected ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- Mocking wp_parse_url(), this is fine. return \parse_url( $url, $component ); }, - ] + ], ); $this->assertSame( $expected, $this->instance->get_url_host( $url_input ) ); @@ -353,7 +353,7 @@ public function test_ensure_absolute_url_with_relative_url_given() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $this->assertEquals( 'https://example.com/page', $this->instance->ensure_absolute_url( 'page' ) ); @@ -528,7 +528,7 @@ public function test_get_link_type( $url, $home_url, $is_image, $link_type, $mes $this->assertEquals( $link_type, $this->instance->get_link_type( $url, $home_url, $is_image ), - $message + $message, ); } @@ -657,7 +657,7 @@ public function test_recreate_current_url( $params, $expected ) { $this->assertSame( $expected, - $this->instance->recreate_current_url( $params['with_request_uri'] ) + $this->instance->recreate_current_url( $params['with_request_uri'] ), ); if ( ! empty( $params['HTTPS'] ) ) { diff --git a/tests/Unit/Helpers/Wincher_Helper_Test.php b/tests/Unit/Helpers/Wincher_Helper_Test.php index a40e0e1792b..ada6b247485 100644 --- a/tests/Unit/Helpers/Wincher_Helper_Test.php +++ b/tests/Unit/Helpers/Wincher_Helper_Test.php @@ -74,7 +74,7 @@ public function test_constructor() { $this->assertInstanceOf( Wincher_Helper::class, $this->instance ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options' ) + $this->getPropertyValue( $this->instance, 'options' ), ); } @@ -104,7 +104,7 @@ public function test_is_active_unmet() { Monkey\Functions\stubs( [ 'is_multisite' => true, - ] + ], ); $this->assertFalse( $this->instance->is_active() ); diff --git a/tests/Unit/Inc/Addon_Manager_Test.php b/tests/Unit/Inc/Addon_Manager_Test.php index a1ed38051ff..60032e9ac18 100644 --- a/tests/Unit/Inc/Addon_Manager_Test.php +++ b/tests/Unit/Inc/Addon_Manager_Test.php @@ -76,7 +76,7 @@ public function test_get_subscriptions_with_no_installed_addons() { ->andReturn( (object) [ 'subscriptions' => [], - ] + ], ); $this->assertEquals( [], $this->instance->get_subscriptions() ); @@ -102,7 +102,7 @@ public function test_get_subscriptions_with_site_transient() { ->andReturn( (object) [ 'subscriptions' => [], - ] + ], ); $this->assertEquals( [], $this->instance->get_subscriptions() ); @@ -195,7 +195,7 @@ public function test_get_subscriptions_with_no_current_sites_found() { ->andReturn( (object) [ 'subscriptions' => [], - ] + ], ); $this->assertEquals( [], $this->instance->get_subscriptions() ); @@ -222,7 +222,7 @@ public function test_get_subscription() { $this->assertEquals( $subscription, - $this->instance->get_subscription( 'wordpress-seo' ) + $this->instance->get_subscription( 'wordpress-seo' ), ); } @@ -264,7 +264,7 @@ public function test_get_subscriptions_for_active_addons() { 'wp-seo-premium.php' => [ 'Version' => '10.0', ], - ] + ], ); $this->instance @@ -278,7 +278,7 @@ public function test_get_subscriptions_for_active_addons() { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -300,7 +300,7 @@ public function test_get_subscriptions_for_active_addons() { ], ], ], - $this->instance->get_subscriptions_for_active_addons() + $this->instance->get_subscriptions_for_active_addons(), ); } @@ -322,7 +322,7 @@ public function test_get_addon_filenames() { 'wpseo-woocommerce.php' => 'yoast-seo-woocommerce', 'local-seo.php' => 'yoast-seo-local', ], - $actual + $actual, ); } @@ -342,7 +342,7 @@ public function test_get_plugin_file() { 'wp-seo-premium.php' => [ 'Version' => '10.0' ], 'no-yoast-seo-extension-php' => [ 'Version' => '10.0' ], 'wpseo-news.php' => [ 'Version' => '9.5' ], - ] + ], ); $actual = $this->instance->get_plugin_file( 'yoast-seo-news' ); @@ -366,7 +366,7 @@ public function test_get_plugin_file_nonexistent_plugin() { 'wp-seo-premium.php' => [ 'Version' => '10.0' ], 'no-yoast-seo-extension-php' => [ 'Version' => '10.0' ], 'wpseo-news.php' => [ 'Version' => '9.5' ], - ] + ], ); $actual = $this->instance->get_plugin_file( 'some-other-plugin-slug' ); @@ -390,7 +390,7 @@ public function test_get_installed_addons_versions() { 'wp-seo-premium.php' => [ 'Version' => '10.0', ], - ] + ], ); $product_helper_mock = Mockery::mock( Product_Helper::class ); @@ -399,7 +399,7 @@ public function test_get_installed_addons_versions() { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -410,7 +410,7 @@ public function test_get_installed_addons_versions() { [ 'yoast-seo-wordpress-premium' => '10.0', ], - $this->instance->get_installed_addons_versions() + $this->instance->get_installed_addons_versions(), ); } @@ -447,13 +447,13 @@ public function test_get_plugin_information( $action, $args, $expected, $message 'requires' => \YOAST_SEO_WP_REQUIRED, ], ], - ] + ], ); $this->assertEquals( $expected, $this->instance->get_plugin_information( false, $action, (object) $args ), - $message + $message, ); } @@ -472,7 +472,7 @@ public function test_has_valid_subscription() { $this->assertEquals( true, - $this->instance->has_valid_subscription( 'yoast-seo-wordpress-premium' ) + $this->instance->has_valid_subscription( 'yoast-seo-wordpress-premium' ), ); } @@ -491,7 +491,7 @@ public function test_has_valid_subscription_with_an_expired_subscription() { $this->assertEquals( false, - $this->instance->has_valid_subscription( 'yoast-seo-news' ) + $this->instance->has_valid_subscription( 'yoast-seo-news' ), ); } @@ -510,7 +510,7 @@ public function test_has_valid_subscription_with_an_unknown_subscription() { $this->assertEquals( false, - $this->instance->has_valid_subscription( 'unknown-slug' ) + $this->instance->has_valid_subscription( 'unknown-slug' ), ); } @@ -547,7 +547,7 @@ public function test_check_for_updates( $addons, $data, $expected, $message ) { ->andReturn( (object) [ 'requires' => \YOAST_SEO_WP_REQUIRED, - ] + ], ); if ( ! empty( $addons ) ) { @@ -557,7 +557,7 @@ public function test_check_for_updates( $addons, $data, $expected, $message ) { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -574,7 +574,7 @@ public function test_check_for_updates( $addons, $data, $expected, $message ) { 'requires_php' => '7.4', ], ], - ] + ], ); global $wp_version; @@ -604,7 +604,7 @@ public function test_is_yoast_addon() { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -629,7 +629,7 @@ public function test_get_slug_by_plugin_file() { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -740,7 +740,7 @@ public function test_get_installed_addons_with_no_yoast_addons_installed() { 'no-yoast-seo-extension-php' => [ 'Version' => '10.0', ], - ] + ], ); $product_helper_mock = Mockery::mock( Product_Helper::class ); @@ -749,7 +749,7 @@ public function test_get_installed_addons_with_no_yoast_addons_installed() { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -758,7 +758,7 @@ public function test_get_installed_addons_with_no_yoast_addons_installed() { $this->assertEquals( [], - $this->instance->get_installed_addons() + $this->instance->get_installed_addons(), ); } @@ -778,7 +778,7 @@ public function test_has_installed_addons() { 'wp-seo-premium.php' => [ 'Version' => '10.0', ], - ] + ], ); $this->assertTrue( $this->instance->has_installed_addons() ); @@ -800,7 +800,7 @@ public function test_get_installed_addons_with_yoast_addon_installed() { 'wp-seo-premium.php' => [ 'Version' => '10.0', ], - ] + ], ); $product_helper_mock = Mockery::mock( Product_Helper::class ); @@ -809,7 +809,7 @@ public function test_get_installed_addons_with_yoast_addon_installed() { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -822,7 +822,7 @@ public function test_get_installed_addons_with_yoast_addon_installed() { 'Version' => '10.0', ], ], - $this->instance->get_installed_addons() + $this->instance->get_installed_addons(), ); } @@ -842,7 +842,7 @@ public function test_get_active_addons() { 'wp-seo-premium.php' => [ 'Version' => '10.0' ], 'no-yoast-seo-extension-php' => [ 'Version' => '10.0' ], 'wpseo-news.php' => [ 'Version' => '9.5' ], - ] + ], ); $this->instance @@ -856,7 +856,7 @@ public function test_get_active_addons() { $container = $this->create_container_with( [ Product_Helper::class => $product_helper_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) @@ -869,7 +869,7 @@ public function test_get_active_addons() { 'Version' => '10.0', ], ], - $this->instance->get_active_addons() + $this->instance->get_active_addons(), ); } @@ -1066,9 +1066,9 @@ protected function get_subscriptions() { 'changelog' => 'changelog', ], ], - ] + ], ), - false + false, ); } @@ -1078,9 +1078,7 @@ protected function get_subscriptions() { * @return string Future date. */ protected function get_future_date() { - if ( $this->future_date === null ) { - $this->future_date = \gmdate( 'Y-m-d\TH:i:s\Z', ( \time() + \DAY_IN_SECONDS ) ); - } + $this->future_date ??= \gmdate( 'Y-m-d\TH:i:s\Z', ( \time() + \DAY_IN_SECONDS ) ); return $this->future_date; } @@ -1091,9 +1089,7 @@ protected function get_future_date() { * @return string Past date. */ protected function get_past_date() { - if ( $this->past_date === null ) { - $this->past_date = \gmdate( 'Y-m-d\TH:i:s\Z', ( \time() - \DAY_IN_SECONDS ) ); - } + $this->past_date ??= \gmdate( 'Y-m-d\TH:i:s\Z', ( \time() - \DAY_IN_SECONDS ) ); return $this->past_date; } @@ -1236,7 +1232,7 @@ public function test_create_notification( $product_name, $short_link ) { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link_mock, - ] + ], ); $admin_user = Mockery::mock( WP_User::class ); @@ -1260,7 +1256,7 @@ public function test_create_notification( $product_name, $short_link ) { $expected = new Yoast_Notification( ' ' . $product_name . ' isn\'t working as expected and you are not receiving updates or support! Make sure to activate your product subscription in MyYoast to unlock all the features of ' . $product_name . '.', - $notification_options + $notification_options, ); $this->assertEquals( $expected, $notification ); } diff --git a/tests/Unit/Inc/Options/Option_Social_Test.php b/tests/Unit/Inc/Options/Option_Social_Test.php index 51858013a2e..69c6394c24f 100644 --- a/tests/Unit/Inc/Options/Option_Social_Test.php +++ b/tests/Unit/Inc/Options/Option_Social_Test.php @@ -45,14 +45,14 @@ public function test_validate_option_with_valid_data( $expected, $dirty, $clean, 'wp_parse_url' => static function ( $url ) { return \parse_url( $url ); }, - ] + ], ); $instance = new Option_Social_Double(); $this->assertEquals( $expected, - $instance->validate_option( $dirty, $clean, $old ) + $instance->validate_option( $dirty, $clean, $old ), ); } @@ -78,7 +78,7 @@ public function test_validate_option_with_invalid_data( $expected, $dirty, $clea 'wp_parse_url' => static function ( $url ) { return \parse_url( $url ); }, - ] + ], ); $instance = new Option_Social_Double(); @@ -96,7 +96,7 @@ public function test_validate_option_with_invalid_data( $expected, $dirty, $clea $this->assertEquals( $expected, - $instance->validate_option( $dirty, $clean, $old ) + $instance->validate_option( $dirty, $clean, $old ), ); unset( $GLOBALS['wp_settings_errors'] ); @@ -121,7 +121,7 @@ public function test_validate_option_with_invalid_array_data( $expected, $dirty, $this->assertEquals( $expected, - $instance->validate_option( $dirty, $clean, $old ) + $instance->validate_option( $dirty, $clean, $old ), ); } diff --git a/tests/Unit/Inc/Sitemaps/Sitemaps_Admin_Test.php b/tests/Unit/Inc/Sitemaps/Sitemaps_Admin_Test.php index a9ff922b1de..ee3dbf390fc 100644 --- a/tests/Unit/Inc/Sitemaps/Sitemaps_Admin_Test.php +++ b/tests/Unit/Inc/Sitemaps/Sitemaps_Admin_Test.php @@ -64,7 +64,7 @@ public function test_status_transition_on_development() { Monkey\Functions\stubs( [ 'wp_get_environment_type' => 'development', - ] + ], ); Monkey\Functions\expect( 'get_post_type' ) @@ -102,7 +102,7 @@ public function test_status_transition_on_production() { Monkey\Functions\stubs( [ 'wp_get_environment_type' => 'production', - ] + ], ); Monkey\Functions\expect( 'get_post_type' ) diff --git a/tests/Unit/Inc/Sitemaps/Sitemaps_Router_Test.php b/tests/Unit/Inc/Sitemaps/Sitemaps_Router_Test.php index d4f9fbe1e3e..304e576fe20 100644 --- a/tests/Unit/Inc/Sitemaps/Sitemaps_Router_Test.php +++ b/tests/Unit/Inc/Sitemaps/Sitemaps_Router_Test.php @@ -58,7 +58,7 @@ protected function set_up() { $this->container = $this->create_container_with( [ Deactivating_Yoast_Seo_Conditional::class => $this->deactivating_yoast_conditional, - ] + ], ); $this->deactivating_yoast_conditional->expects( 'is_met' ) ->once() diff --git a/tests/Unit/Initializers/Crawl_Cleanup_Permalinks_Test.php b/tests/Unit/Initializers/Crawl_Cleanup_Permalinks_Test.php index d2dea95f916..68ae1711b8c 100644 --- a/tests/Unit/Initializers/Crawl_Cleanup_Permalinks_Test.php +++ b/tests/Unit/Initializers/Crawl_Cleanup_Permalinks_Test.php @@ -75,7 +75,7 @@ protected function set_up() { $this->options_helper, $this->url_helper, $this->redirect_helper, - $this->crawl_cleanup_helper + $this->crawl_cleanup_helper, ); } diff --git a/tests/Unit/Integrations/Academy_Integration_Test.php b/tests/Unit/Integrations/Academy_Integration_Test.php index bb2c8ae14ba..4668fe633e3 100644 --- a/tests/Unit/Integrations/Academy_Integration_Test.php +++ b/tests/Unit/Integrations/Academy_Integration_Test.php @@ -75,7 +75,7 @@ public function set_up() { $this->asset_manager, $this->current_page_helper, $this->product_helper, - $this->shortlink_helper + $this->shortlink_helper, ); } @@ -93,8 +93,8 @@ public function test_construct() { $this->asset_manager, $this->current_page_helper, $this->product_helper, - $this->shortlink_helper - ) + $this->shortlink_helper, + ), ); } @@ -111,7 +111,7 @@ public function test_get_conditionals() { Admin_Conditional::class, User_Can_Manage_Wpseo_Options_Conditional::class, ], - Academy_Integration::get_conditionals() + Academy_Integration::get_conditionals(), ); } @@ -180,7 +180,7 @@ public function test_add_page() { [ 'page1', '', 'Page 1', 'manage_options', 'page1', [ $this, 'display_page' ] ], [ 'page2', '', 'Page 2', 'manage_options', 'page2', [ $this, 'display_page' ] ], [ 'page3', '', 'Page 3', 'manage_options', 'page3', [ $this, 'display_page' ] ], - ] + ], ); // Assert that the new page was added at index 3. diff --git a/tests/Unit/Integrations/Admin/Activation_Cleanup_Integration_Test.php b/tests/Unit/Integrations/Admin/Activation_Cleanup_Integration_Test.php index d20154f567a..8c6241ba17e 100644 --- a/tests/Unit/Integrations/Admin/Activation_Cleanup_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Activation_Cleanup_Integration_Test.php @@ -64,7 +64,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [], - Activation_Cleanup_Integration::get_conditionals() + Activation_Cleanup_Integration::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Admin/Background_Indexing_Integration_Test.php b/tests/Unit/Integrations/Admin/Background_Indexing_Integration_Test.php index 5ef22016158..9fc8f74b40c 100644 --- a/tests/Unit/Integrations/Admin/Background_Indexing_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Background_Indexing_Integration_Test.php @@ -158,7 +158,7 @@ protected function set_up() { $this->general_indexation, $this->post_link_indexing_action, $this->term_link_indexing_action, - ] + ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->stubTranslationFunctions(); @@ -176,7 +176,7 @@ public function test_get_conditionals() { [ Migrations_Conditional::class, ], - Background_Indexing_Integration::get_conditionals() + Background_Indexing_Integration::get_conditionals(), ); } @@ -191,15 +191,15 @@ public function test_constructor() { $this->assertInstanceOf( Indexable_Indexing_Complete_Action::class, - $this->getPropertyValue( $this->instance, 'complete_indexation_action' ) + $this->getPropertyValue( $this->instance, 'complete_indexation_action' ), ); $this->assertInstanceOf( Indexing_Helper::class, - $this->getPropertyValue( $this->instance, 'indexing_helper' ) + $this->getPropertyValue( $this->instance, 'indexing_helper' ), ); $this->assertInstanceOf( Yoast_Admin_And_Dashboard_Conditional::class, - $this->getPropertyValue( $this->instance, 'yoast_admin_and_dashboard_conditional' ) + $this->getPropertyValue( $this->instance, 'yoast_admin_and_dashboard_conditional' ), ); } @@ -578,8 +578,8 @@ public function test_index_with_wp_cron_with_cron_indexing_disabled() { ->with( true ) ->andReturn( false ); - Monkey\Functions\expect( 'wp_next_scheduled' )->once()->with( 'wpseo_indexable_index_batch' )->andReturn( 12345 ); - Monkey\Functions\expect( 'wp_unschedule_event' )->once()->with( 12345, 'wpseo_indexable_index_batch' ); + Monkey\Functions\expect( 'wp_next_scheduled' )->once()->with( 'wpseo_indexable_index_batch' )->andReturn( 12_345 ); + Monkey\Functions\expect( 'wp_unschedule_event' )->once()->with( 12_345, 'wpseo_indexable_index_batch' ); $this->instance->index(); } @@ -604,8 +604,8 @@ public function test_index_with_wp_cron_with_indexing_disabled() { ->once() ->andReturn( false ); - Monkey\Functions\expect( 'wp_next_scheduled' )->once()->with( 'wpseo_indexable_index_batch' )->andReturn( 12345 ); - Monkey\Functions\expect( 'wp_unschedule_event' )->once()->with( 12345, 'wpseo_indexable_index_batch' ); + Monkey\Functions\expect( 'wp_next_scheduled' )->once()->with( 'wpseo_indexable_index_batch' )->andReturn( 12_345 ); + Monkey\Functions\expect( 'wp_unschedule_event' )->once()->with( 12_345, 'wpseo_indexable_index_batch' ); $this->instance->index(); } @@ -636,8 +636,8 @@ public function test_index_with_wp_cron_with_complete_index() { ->once() ->andReturn( true ); - Monkey\Functions\expect( 'wp_next_scheduled' )->once()->with( 'wpseo_indexable_index_batch' )->andReturn( 12345 ); - Monkey\Functions\expect( 'wp_unschedule_event' )->once()->with( 12345, 'wpseo_indexable_index_batch' ); + Monkey\Functions\expect( 'wp_next_scheduled' )->once()->with( 'wpseo_indexable_index_batch' )->andReturn( 12_345 ); + Monkey\Functions\expect( 'wp_unschedule_event' )->once()->with( 12_345, 'wpseo_indexable_index_batch' ); $this->instance->index(); } diff --git a/tests/Unit/Integrations/Admin/Crawl_Settings_Integration_Test.php b/tests/Unit/Integrations/Admin/Crawl_Settings_Integration_Test.php index c6496379a46..ab902b848cf 100644 --- a/tests/Unit/Integrations/Admin/Crawl_Settings_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Crawl_Settings_Integration_Test.php @@ -65,7 +65,7 @@ public function test_get_conditionals() { [ Admin_Conditional::class, ], - Crawl_Settings_Integration::get_conditionals() + Crawl_Settings_Integration::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Admin/Cron_Integration_Test.php b/tests/Unit/Integrations/Admin/Cron_Integration_Test.php index 4780990974f..73bea32fede 100644 --- a/tests/Unit/Integrations/Admin/Cron_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Cron_Integration_Test.php @@ -58,7 +58,7 @@ public function test_get_conditionals() { [ Admin_Conditional::class, ], - Cron_Integration::get_conditionals() + Cron_Integration::get_conditionals(), ); } @@ -72,7 +72,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Date_Helper::class, - $this->getPropertyValue( $this->instance, 'date_helper' ) + $this->getPropertyValue( $this->instance, 'date_helper' ), ); } @@ -87,7 +87,7 @@ public function test_register_hooks() { $this->date_helper ->expects( 'current_time' ) ->once() - ->andReturn( 123456 ); + ->andReturn( 123_456 ); Monkey\Functions\expect( 'wp_next_scheduled' ) ->once() @@ -96,7 +96,7 @@ public function test_register_hooks() { Monkey\Functions\expect( 'wp_schedule_event' ) ->once() - ->with( 123456, 'daily', Indexing_Notification_Integration::NOTIFICATION_ID ); + ->with( 123_456, 'daily', Indexing_Notification_Integration::NOTIFICATION_ID ); $this->instance->register_hooks(); } diff --git a/tests/Unit/Integrations/Admin/Deactivated_Premium_Integration_Test.php b/tests/Unit/Integrations/Admin/Deactivated_Premium_Integration_Test.php index 728d335ee10..308a6f69bd3 100644 --- a/tests/Unit/Integrations/Admin/Deactivated_Premium_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Deactivated_Premium_Integration_Test.php @@ -126,7 +126,7 @@ function dismiss_premium_deactivated_notice(){ dismiss_premium_deactivated_notice(); } ); } ); - " + ", ); $this->instance->premium_deactivated_notice(); diff --git a/tests/Unit/Integrations/Admin/First_Time_Configuration_Notice_Integration_Test.php b/tests/Unit/Integrations/Admin/First_Time_Configuration_Notice_Integration_Test.php index eb7a9f74ba5..4f1439e2dbe 100644 --- a/tests/Unit/Integrations/Admin/First_Time_Configuration_Notice_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/First_Time_Configuration_Notice_Integration_Test.php @@ -75,7 +75,7 @@ protected function set_up() { $this->instance = new First_Time_Configuration_Notice_Integration( $this->options_helper, $this->first_time_configuration_notice_helper, - $this->admin_asset_manager + $this->admin_asset_manager, ); $this->notice_presenter = Mockery::mock( Notice_Presenter::class ); @@ -91,7 +91,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Admin_Conditional::class ], - $this->instance->get_conditionals() + $this->instance->get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Admin/Import_Integration_Test.php b/tests/Unit/Integrations/Admin/Import_Integration_Test.php index 3fc1db0c115..714a55e43f3 100644 --- a/tests/Unit/Integrations/Admin/Import_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Import_Integration_Test.php @@ -68,7 +68,7 @@ protected function set_up() { $this->instance = new Import_Integration( $this->asset_manager, $this->importable_detector, - $this->importing_route + $this->importing_route, ); } @@ -82,15 +82,15 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - self::getPropertyValue( $this->instance, 'asset_manager' ) + self::getPropertyValue( $this->instance, 'asset_manager' ), ); $this->assertInstanceOf( Importable_Detector_Service::class, - self::getPropertyValue( $this->instance, 'importable_detector' ) + self::getPropertyValue( $this->instance, 'importable_detector' ), ); $this->assertInstanceOf( Importing_Route::class, - self::getPropertyValue( $this->instance, 'importing_route' ) + self::getPropertyValue( $this->instance, 'importing_route' ), ); } diff --git a/tests/Unit/Integrations/Admin/Indexing_Notification_Integration_Test.php b/tests/Unit/Integrations/Admin/Indexing_Notification_Integration_Test.php index 3a92e47c78a..5ae5be94220 100644 --- a/tests/Unit/Integrations/Admin/Indexing_Notification_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Indexing_Notification_Integration_Test.php @@ -126,7 +126,7 @@ protected function set_up() { $this->notification_helper, $this->indexing_helper, $this->addon_manager, - $this->environment_helper + $this->environment_helper, ); } @@ -140,31 +140,31 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Yoast_Notification_Center::class, - $this->getPropertyValue( $this->instance, 'notification_center' ) + $this->getPropertyValue( $this->instance, 'notification_center' ), ); $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'page_helper' ) + $this->getPropertyValue( $this->instance, 'page_helper' ), ); $this->assertInstanceOf( Short_Link_Helper::class, - $this->getPropertyValue( $this->instance, 'short_link_helper' ) + $this->getPropertyValue( $this->instance, 'short_link_helper' ), ); $this->assertInstanceOf( Notification_Helper::class, - $this->getPropertyValue( $this->instance, 'notification_helper' ) + $this->getPropertyValue( $this->instance, 'notification_helper' ), ); $this->assertInstanceOf( Indexing_Helper::class, - $this->getPropertyValue( $this->instance, 'indexing_helper' ) + $this->getPropertyValue( $this->instance, 'indexing_helper' ), ); $this->assertInstanceOf( Environment_Helper::class, - $this->getPropertyValue( $this->instance, 'environment_helper' ) + $this->getPropertyValue( $this->instance, 'environment_helper' ), ); } @@ -260,7 +260,7 @@ public function test_get_conditionals() { Not_Admin_Ajax_Conditional::class, User_Can_Manage_Wpseo_Options_Conditional::class, ], - Indexing_Notification_Integration::get_conditionals() + Indexing_Notification_Integration::get_conditionals(), ); } @@ -310,7 +310,7 @@ public function test_create_notification_with_having_indexing_started() { $this->indexing_helper ->expects( 'get_started' ) - ->andReturn( 123456789 ); + ->andReturn( 123_456_789 ); $this->indexing_helper ->expects( 'get_filtered_unindexed_count' ) @@ -530,7 +530,7 @@ public function test_maybe_cleanup_notification_when_the_user_has_started_indexi $this->indexing_helper ->expects( 'get_started' ) ->once() - ->andReturn( 123456789 ); + ->andReturn( 123_456_789 ); $this->indexing_helper ->expects( 'get_filtered_unindexed_count' ) diff --git a/tests/Unit/Integrations/Admin/Indexing_Tool_Integration_Test.php b/tests/Unit/Integrations/Admin/Indexing_Tool_Integration_Test.php index 23059d9e14e..796be22770a 100644 --- a/tests/Unit/Integrations/Admin/Indexing_Tool_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Indexing_Tool_Integration_Test.php @@ -119,7 +119,7 @@ protected function set_up() { $this->addon_manager, $this->product_helper, $this->importable_detector, - $this->importing_route + $this->importing_route, ); } @@ -133,35 +133,35 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - self::getPropertyValue( $this->instance, 'asset_manager' ) + self::getPropertyValue( $this->instance, 'asset_manager' ), ); $this->assertInstanceOf( Indexable_Helper::class, - self::getPropertyValue( $this->instance, 'indexable_helper' ) + self::getPropertyValue( $this->instance, 'indexable_helper' ), ); $this->assertInstanceOf( Short_Link_Helper::class, - self::getPropertyValue( $this->instance, 'short_link_helper' ) + self::getPropertyValue( $this->instance, 'short_link_helper' ), ); $this->assertInstanceOf( Indexing_Helper::class, - self::getPropertyValue( $this->instance, 'indexing_helper' ) + self::getPropertyValue( $this->instance, 'indexing_helper' ), ); $this->assertInstanceOf( WPSEO_Addon_Manager::class, - self::getPropertyValue( $this->instance, 'addon_manager' ) + self::getPropertyValue( $this->instance, 'addon_manager' ), ); $this->assertInstanceOf( Product_Helper::class, - self::getPropertyValue( $this->instance, 'product_helper' ) + self::getPropertyValue( $this->instance, 'product_helper' ), ); $this->assertInstanceOf( Importable_Detector_Service::class, - self::getPropertyValue( $this->instance, 'importable_detector' ) + self::getPropertyValue( $this->instance, 'importable_detector' ), ); $this->assertInstanceOf( Importing_Route::class, - self::getPropertyValue( $this->instance, 'importing_route' ) + self::getPropertyValue( $this->instance, 'importing_route' ), ); } @@ -342,7 +342,7 @@ public function test_render_indexing_list_item_is_allowed() { // Assert. $this->expectOutputString( - '
  • Optimize SEO Data
    You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. If you have a lot of content it might take a while, but trust us, it\'s worth it. Learn more about the benefits of optimized SEO data.
  • ' + '
  • Optimize SEO Data
    You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. If you have a lot of content it might take a while, but trust us, it\'s worth it. Learn more about the benefits of optimized SEO data.
  • ', ); } } diff --git a/tests/Unit/Integrations/Admin/Installation_Success_Integration_Test.php b/tests/Unit/Integrations/Admin/Installation_Success_Integration_Test.php index d62332bbf4b..6dee0d8ea38 100644 --- a/tests/Unit/Integrations/Admin/Installation_Success_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Installation_Success_Integration_Test.php @@ -66,7 +66,7 @@ protected function set_up() { $this->options_helper, $this->product_helper, $this->shortlinker, - ] + ], )->makePartial(); } @@ -82,7 +82,7 @@ public function test_get_conditionals() { [ Admin_Conditional::class, ], - Installation_Success_Integration::get_conditionals() + Installation_Success_Integration::get_conditionals(), ); } @@ -96,12 +96,12 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); } @@ -120,9 +120,9 @@ public function test_register_hooks() { [ $this->instance, 'add_submenu_page', - ] + ], ), - 'Does not have expected admin_menu filter' + 'Does not have expected admin_menu filter', ); $this->assertNotFalse( Monkey\Actions\has( @@ -130,9 +130,9 @@ public function test_register_hooks() { [ $this->instance, 'enqueue_assets', - ] + ], ), - 'Does not have expected admin_enqueue_scripts action' + 'Does not have expected admin_enqueue_scripts action', ); $this->assertNotFalse( Monkey\Actions\has( @@ -140,9 +140,9 @@ public function test_register_hooks() { [ $this->instance, 'maybe_redirect', - ] + ], ), - 'Does not have expected admin_init action' + 'Does not have expected admin_init action', ); } @@ -421,7 +421,7 @@ public function test_add_submenu_page() { [ $this->instance, 'render_page', - ] + ], ); $submenu_pages = [ diff --git a/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php b/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php index 207153d59d4..c6179dca092 100644 --- a/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php @@ -106,7 +106,7 @@ protected function set_up() { $this->jetpack_conditional, $this->site_kit_configuration, $this->site_kit_consent_management_endpoint, - $this->schema_configuration + $this->schema_configuration, ); } @@ -120,7 +120,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Admin_Conditional::class ], - $this->instance->get_conditionals() + $this->instance->get_conditionals(), ); } @@ -243,7 +243,7 @@ public function test_enqueue_assets() { 'site_kit_configuration' => $site_kit_config, 'site_kit_consent_management_url' => 'https://www.example.com/manage-consent', 'schema_framework_enabled' => true, - ] + ], ); $this->instance->enqueue_assets(); diff --git a/tests/Unit/Integrations/Admin/Migration_Error_Integration_Test.php b/tests/Unit/Integrations/Admin/Migration_Error_Integration_Test.php index 09b5162e9c2..859eeae08f1 100644 --- a/tests/Unit/Integrations/Admin/Migration_Error_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Migration_Error_Integration_Test.php @@ -60,7 +60,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Migration_Status::class, - $this->getPropertyValue( $this->instance, 'migration_status' ) + $this->getPropertyValue( $this->instance, 'migration_status' ), ); } @@ -158,7 +158,7 @@ private function expect_shortlinker() { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) diff --git a/tests/Unit/Integrations/Admin/Old_Configuration_Integration_Test.php b/tests/Unit/Integrations/Admin/Old_Configuration_Integration_Test.php index 82d2f695045..739fc85acf6 100644 --- a/tests/Unit/Integrations/Admin/Old_Configuration_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Old_Configuration_Integration_Test.php @@ -47,7 +47,7 @@ public function test_get_conditionals() { [ Admin_Conditional::class, ], - Old_Configuration_Integration::get_conditionals() + Old_Configuration_Integration::get_conditionals(), ); } @@ -66,9 +66,9 @@ public function test_register_hooks() { [ $this->instance, 'add_submenu_page', - ] + ], ), - 'Does not have expected admin_menu filter' + 'Does not have expected admin_menu filter', ); $this->assertNotFalse( Monkey\Actions\has( @@ -76,9 +76,9 @@ public function test_register_hooks() { [ $this->instance, 'redirect_to_new_configuration', - ] + ], ), - 'Does not have expected admin_init action' + 'Does not have expected admin_init action', ); } @@ -103,7 +103,7 @@ public function test_add_submenu_page() { [ $this->instance, 'render_page', - ] + ], ); $submenu_pages = [ diff --git a/tests/Unit/Integrations/Admin/Redirect_Integration_Test.php b/tests/Unit/Integrations/Admin/Redirect_Integration_Test.php index 34a2b884fc7..bfa40c901c4 100644 --- a/tests/Unit/Integrations/Admin/Redirect_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Redirect_Integration_Test.php @@ -77,7 +77,7 @@ public function test_get_conditionals() { [ Admin_Conditional::class, ], - Redirect_Integration::get_conditionals() + Redirect_Integration::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Admin/Redirects_Page_Integration_Test.php b/tests/Unit/Integrations/Admin/Redirects_Page_Integration_Test.php index 03b868daab1..94cd45cd991 100644 --- a/tests/Unit/Integrations/Admin/Redirects_Page_Integration_Test.php +++ b/tests/Unit/Integrations/Admin/Redirects_Page_Integration_Test.php @@ -64,7 +64,7 @@ protected function set_up() { $this->instance = new Redirects_Page_Integration( $this->current_page_helper, $this->user_helper, - $this->wistia_embed_permission_repository + $this->wistia_embed_permission_repository, ); } @@ -81,7 +81,7 @@ public function test_get_conditionals() { Admin_Conditional::class, Premium_Inactive_Conditional::class, ], - Redirects_Page_Integration::get_conditionals() + Redirects_Page_Integration::get_conditionals(), ); } @@ -102,9 +102,9 @@ public function test_register_hooks() { [ $this->instance, 'add_submenu_page', - ] + ], ), - 'Does not have expected wpseo_submenu_pages filter' + 'Does not have expected wpseo_submenu_pages filter', ); } diff --git a/tests/Unit/Integrations/Blocks/Block_Editor_Integration_Test.php b/tests/Unit/Integrations/Blocks/Block_Editor_Integration_Test.php index ab721813c3a..20be6084bdf 100644 --- a/tests/Unit/Integrations/Blocks/Block_Editor_Integration_Test.php +++ b/tests/Unit/Integrations/Blocks/Block_Editor_Integration_Test.php @@ -56,7 +56,7 @@ public function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Post_Conditional::class ], - Block_Editor_Integration::get_conditionals() + Block_Editor_Integration::get_conditionals(), ); } @@ -70,7 +70,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $this->instance, 'asset_manager' ) + $this->getPropertyValue( $this->instance, 'asset_manager' ), ); } diff --git a/tests/Unit/Integrations/Blocks/Structured_Data_Blocks_Test.php b/tests/Unit/Integrations/Blocks/Structured_Data_Blocks_Test.php index d3f90d7b704..8c9584cb636 100644 --- a/tests/Unit/Integrations/Blocks/Structured_Data_Blocks_Test.php +++ b/tests/Unit/Integrations/Blocks/Structured_Data_Blocks_Test.php @@ -54,7 +54,7 @@ protected function set_up() { $this->instance = new Structured_Data_Blocks( $this->asset_manager, - $this->image_helper + $this->image_helper, ); } @@ -70,8 +70,8 @@ public function test_construct() { Structured_Data_Blocks::class, new Structured_Data_Blocks( $this->asset_manager, - $this->image_helper - ) + $this->image_helper, + ), ); } @@ -168,9 +168,9 @@ public function test_present_duration_text( $expected, $attributes, $content, $m $expected, $this->instance->present_duration_text( $attributes, - $content + $content, ), - $message + $message, ); } @@ -234,9 +234,9 @@ public function test_optimize_how_to_images( $expected, $attributes, $content, $ $expected, $this->instance->optimize_how_to_images( $attributes, - $content + $content, ), - $message + $message, ); } } diff --git a/tests/Unit/Integrations/Breadcrumbs_Integration_Test.php b/tests/Unit/Integrations/Breadcrumbs_Integration_Test.php index 34924e0f727..a2482885172 100644 --- a/tests/Unit/Integrations/Breadcrumbs_Integration_Test.php +++ b/tests/Unit/Integrations/Breadcrumbs_Integration_Test.php @@ -53,7 +53,7 @@ protected function set_up() { $this->instance = new Breadcrumbs_Integration( Mockery::mock( Helpers_Surface::class ), Mockery::mock( WPSEO_Replace_Vars::class ), - $this->context_memoizer + $this->context_memoizer, ); } diff --git a/tests/Unit/Integrations/Cleanup_Integration_Test.php b/tests/Unit/Integrations/Cleanup_Integration_Test.php index 274c73a5518..2c7c14acfc8 100644 --- a/tests/Unit/Integrations/Cleanup_Integration_Test.php +++ b/tests/Unit/Integrations/Cleanup_Integration_Test.php @@ -61,7 +61,7 @@ protected function set_up() { $this->instance = new Cleanup_Integration( $this->indexable_repository, - $this->indexable_helper + $this->indexable_helper, ); global $wpdb; diff --git a/tests/Unit/Integrations/Estimated_Reading_Time_Test.php b/tests/Unit/Integrations/Estimated_Reading_Time_Test.php index b9e0147ff1f..e7cdfc9aded 100644 --- a/tests/Unit/Integrations/Estimated_Reading_Time_Test.php +++ b/tests/Unit/Integrations/Estimated_Reading_Time_Test.php @@ -58,7 +58,7 @@ public function test_register_hooks() { public function test_get_conditionals() { $this->assertEquals( [ Estimated_Reading_Time_Conditional::class ], - Estimated_Reading_Time::get_conditionals() + Estimated_Reading_Time::get_conditionals(), ); } @@ -79,7 +79,7 @@ public function test_add_estimated_reading_time_hidden_fields() { 'type' => 'hidden', 'title' => 'estimated-reading-time-minutes', ], - $actual['estimated-reading-time-minutes'] + $actual['estimated-reading-time-minutes'], ); } diff --git a/tests/Unit/Integrations/Feature_Flag_Integration_Test.php b/tests/Unit/Integrations/Feature_Flag_Integration_Test.php index c00e4e1e7f1..e7da0ed7d22 100644 --- a/tests/Unit/Integrations/Feature_Flag_Integration_Test.php +++ b/tests/Unit/Integrations/Feature_Flag_Integration_Test.php @@ -69,14 +69,14 @@ public function set_up() { public function test_constructor() { self::assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - self::getPropertyValue( $this->instance, 'asset_manager' ) + self::getPropertyValue( $this->instance, 'asset_manager' ), ); self::assertIsArray( - self::getPropertyValue( $this->instance, 'feature_flags' ) + self::getPropertyValue( $this->instance, 'feature_flags' ), ); self::assertInstanceOf( Feature_Flag_Conditional::class, - self::getPropertyValue( $this->instance, 'feature_flags' )[0] + self::getPropertyValue( $this->instance, 'feature_flags' )[0], ); } diff --git a/tests/Unit/Integrations/Front_End/Category_Term_Description_Test.php b/tests/Unit/Integrations/Front_End/Category_Term_Description_Test.php index a31caf9e8c7..d83eaa952c4 100644 --- a/tests/Unit/Integrations/Front_End/Category_Term_Description_Test.php +++ b/tests/Unit/Integrations/Front_End/Category_Term_Description_Test.php @@ -45,7 +45,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Category_Term_Description::get_conditionals() + Category_Term_Description::get_conditionals(), ); } @@ -76,7 +76,7 @@ public function test_add_shortcode_support() { $this->assertEquals( 'This is a category text', - $this->instance->add_shortcode_support( 'This is a category text' ) + $this->instance->add_shortcode_support( 'This is a category text' ), ); } } diff --git a/tests/Unit/Integrations/Front_End/Comment_Link_Fixer_Test.php b/tests/Unit/Integrations/Front_End/Comment_Link_Fixer_Test.php index 44fc3d5f2ef..b24b4f026dc 100644 --- a/tests/Unit/Integrations/Front_End/Comment_Link_Fixer_Test.php +++ b/tests/Unit/Integrations/Front_End/Comment_Link_Fixer_Test.php @@ -66,7 +66,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Comment_Link_Fixer::get_conditionals() + Comment_Link_Fixer::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Basic_Test.php b/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Basic_Test.php index 1a6da0ffb4d..f8835a4e663 100644 --- a/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Basic_Test.php +++ b/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Basic_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Crawl_Cleanup_Basic::get_conditionals() + Crawl_Cleanup_Basic::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Rss_Test.php b/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Rss_Test.php index 0292e460152..d7b1e36f7ba 100644 --- a/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Rss_Test.php +++ b/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Rss_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Crawl_Cleanup_Rss::get_conditionals() + Crawl_Cleanup_Rss::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Searches_Test.php b/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Searches_Test.php index c6b9d717ec8..5feb539a414 100644 --- a/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Searches_Test.php +++ b/tests/Unit/Integrations/Front_End/Crawl_Cleanup_Searches_Test.php @@ -67,7 +67,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Crawl_Cleanup_Searches::get_conditionals() + Crawl_Cleanup_Searches::get_conditionals(), ); } @@ -104,8 +104,8 @@ public function test_register_hooks() { [ $this->instance, 'maybe_redirect_searches', - ] - ) + ], + ), ); } diff --git a/tests/Unit/Integrations/Front_End/Force_Rewrite_Title_Test.php b/tests/Unit/Integrations/Front_End/Force_Rewrite_Title_Test.php index 27c92058494..ad57f503290 100644 --- a/tests/Unit/Integrations/Front_End/Force_Rewrite_Title_Test.php +++ b/tests/Unit/Integrations/Front_End/Force_Rewrite_Title_Test.php @@ -66,7 +66,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Force_Rewrite_Title::get_conditionals() + Force_Rewrite_Title::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Front_End/Handle_404_Test.php b/tests/Unit/Integrations/Front_End/Handle_404_Test.php index abae85fe66a..fb9111416b9 100644 --- a/tests/Unit/Integrations/Front_End/Handle_404_Test.php +++ b/tests/Unit/Integrations/Front_End/Handle_404_Test.php @@ -59,7 +59,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Handle_404::get_conditionals() + Handle_404::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Front_End/Indexing_Controls_Test.php b/tests/Unit/Integrations/Front_End/Indexing_Controls_Test.php index 82c1521e85b..181ed59c85b 100644 --- a/tests/Unit/Integrations/Front_End/Indexing_Controls_Test.php +++ b/tests/Unit/Integrations/Front_End/Indexing_Controls_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Indexing_Controls::get_conditionals() + Indexing_Controls::get_conditionals(), ); } @@ -104,7 +104,7 @@ public function test_no_index_and_is_no_robots() { public function test_nofollow_link() { $this->assertEquals( 'A link', - $this->instance->nofollow_link( 'A link' ) + $this->instance->nofollow_link( 'A link' ), ); } } diff --git a/tests/Unit/Integrations/Front_End/Open_Graph_OEmbed_Test.php b/tests/Unit/Integrations/Front_End/Open_Graph_OEmbed_Test.php index 45e6635aa90..0a1992598c8 100644 --- a/tests/Unit/Integrations/Front_End/Open_Graph_OEmbed_Test.php +++ b/tests/Unit/Integrations/Front_End/Open_Graph_OEmbed_Test.php @@ -59,7 +59,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class, Open_Graph_Conditional::class ], - Open_Graph_OEmbed::get_conditionals() + Open_Graph_OEmbed::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Front_End/RSS_Footer_Embed_Test.php b/tests/Unit/Integrations/Front_End/RSS_Footer_Embed_Test.php index 1e8db76fc09..119e6d120be 100644 --- a/tests/Unit/Integrations/Front_End/RSS_Footer_Embed_Test.php +++ b/tests/Unit/Integrations/Front_End/RSS_Footer_Embed_Test.php @@ -57,7 +57,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - RSS_Footer_Embed::get_conditionals() + RSS_Footer_Embed::get_conditionals(), ); } @@ -88,7 +88,7 @@ public function test_embed_rssfooter_not_on_feed_page() { $this->assertEquals( 'Not on feed page', - $this->instance->embed_rssfooter( 'Not on feed page' ) + $this->instance->embed_rssfooter( 'Not on feed page' ), ); } @@ -109,7 +109,7 @@ public function test_embed_rssfooter_disabled_by_filter() { $this->assertEquals( 'Disabled feature by filter.', - $this->instance->embed_rssfooter( 'Disabled feature by filter.' ) + $this->instance->embed_rssfooter( 'Disabled feature by filter.' ), ); } @@ -134,7 +134,7 @@ public function test_embed_rss_footer_with_no_set_option_values() { $this->assertEquals( 'No options set', - $this->instance->embed_rssfooter( 'No options set' ) + $this->instance->embed_rssfooter( 'No options set' ), ); } @@ -168,7 +168,7 @@ public function test_embed_rss_footer() { '%%POSTLINK%%' => 'post_link', '%%BLOGLINK%%' => 'blog_link', '%%BLOGDESCLINK%%' => 'blog_description_link', - ] + ], ); $this->options->expects( 'get' )->with( 'rssbefore', '' )->once()->andReturn( '%%authorlink%%' ); @@ -176,7 +176,7 @@ public function test_embed_rss_footer() { $this->assertEquals( 'author_linkNo options set', - $this->instance->embed_rssfooter( 'No options set' ) + $this->instance->embed_rssfooter( 'No options set' ), ); } @@ -192,7 +192,7 @@ public function test_embed_rss_footer_excerpt_is_disabled() { $this->assertEquals( 'Feature is disabled', - $this->instance->embed_rssfooter_excerpt( 'Feature is disabled' ) + $this->instance->embed_rssfooter_excerpt( 'Feature is disabled' ), ); } @@ -230,7 +230,7 @@ public function test_embed_rss_footer_excerpt() { '%%POSTLINK%%' => 'post_link', '%%BLOGLINK%%' => 'blog_link', '%%BLOGDESCLINK%%' => 'blog_description_link', - ] + ], ); $this->options->expects( 'get' )->with( 'rssbefore', '' )->once()->andReturn( '%%authorlink%%' ); @@ -238,7 +238,7 @@ public function test_embed_rss_footer_excerpt() { $this->assertEquals( 'author_linkNo options set', - $this->instance->embed_rssfooter_excerpt( 'No options set' ) + $this->instance->embed_rssfooter_excerpt( 'No options set' ), ); } } diff --git a/tests/Unit/Integrations/Front_End/Redirects_Test.php b/tests/Unit/Integrations/Front_End/Redirects_Test.php index 779a7ed3515..21481a1e614 100644 --- a/tests/Unit/Integrations/Front_End/Redirects_Test.php +++ b/tests/Unit/Integrations/Front_End/Redirects_Test.php @@ -93,7 +93,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Redirects::get_conditionals() + Redirects::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php b/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php index e2bef069556..f1154815d44 100644 --- a/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php +++ b/tests/Unit/Integrations/Front_End/Robots_Txt_Integration_Test.php @@ -76,15 +76,15 @@ public function test_construct() { $this->assertInstanceOf( Robots_Txt_Integration::class, $this->instance ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Robots_Txt_Helper::class, - $this->getPropertyValue( $this->instance, 'robots_txt_helper' ) + $this->getPropertyValue( $this->instance, 'robots_txt_helper' ), ); $this->assertInstanceOf( Robots_Txt_Presenter::class, - $this->getPropertyValue( $this->instance, 'robots_txt_presenter' ) + $this->getPropertyValue( $this->instance, 'robots_txt_presenter' ), ); } @@ -98,7 +98,7 @@ public function test_construct() { public function test_get_conditionals() { $this->assertEquals( [ Robots_Txt_Conditional::class ], - Robots_Txt_Integration::get_conditionals() + Robots_Txt_Integration::get_conditionals(), ); } @@ -237,7 +237,7 @@ public function test_multisite_sitemaps( $multisite ) { [ 'allow_enable_xml_sitemap' => true, 'wordpress-seo/wp-seo.php' => true, - ] + ], ); foreach ( $multisite['sites'] as $blog_id => $site ) { @@ -362,7 +362,7 @@ public function test_multisite_sitemaps_without_yoast_seo_active() { Monkey\Functions\when( 'get_network_option' )->justReturn( [ 'allow_enable_xml_sitemap' => true, - ] + ], ); Monkey\Functions\expect( 'get_sites' )->andReturn( [ 1, 2 ] ); Monkey\Functions\expect( 'get_home_url' ) @@ -541,7 +541,7 @@ public function test_remove_default_robots( $input, $expected ) { 'wpseo_should_add_subdirectory_multisite_xml_sitemaps', static function () { return false; - } + }, ); $this->options_helper diff --git a/tests/Unit/Integrations/Front_End/WP_Robots_Integration_Test.php b/tests/Unit/Integrations/Front_End/WP_Robots_Integration_Test.php index 66a832f43e8..27e84a1f5c5 100644 --- a/tests/Unit/Integrations/Front_End/WP_Robots_Integration_Test.php +++ b/tests/Unit/Integrations/Front_End/WP_Robots_Integration_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Meta_Tags_Context_Memoizer::class, - $this->getPropertyValue( $this->instance, 'context_memoizer' ) + $this->getPropertyValue( $this->instance, 'context_memoizer' ), ); } @@ -85,7 +85,7 @@ public function test_get_conditionals() { Front_End_Conditional::class, WP_Robots_Conditional::class, ], - WP_Robots_Integration::get_conditionals() + WP_Robots_Integration::get_conditionals(), ); } @@ -117,7 +117,7 @@ public function test_add_robots_string_given() { 'index' => true, 'follow' => true, ], - $this->instance->add_robots( 'robots_string' ) + $this->instance->add_robots( 'robots_string' ), ); } @@ -153,7 +153,7 @@ public function test_add_robots_overwrite_robots_value_set_to_true() { [ 'index' => true, 'follow' => true, - ] + ], ); $this->assertEquals( @@ -162,7 +162,7 @@ public function test_add_robots_overwrite_robots_value_set_to_true() { 'index' => true, 'max-image-preview' => 'large', ], - $result + $result, ); } @@ -205,8 +205,8 @@ public function test_add_robots_with_noimageindex() { [ 'index' => true, 'follow' => true, - ] - ) + ], + ), ); } @@ -248,8 +248,8 @@ public function test_add_robots_with_noindex_set() { [ 'index' => true, 'follow' => true, - ] - ) + ], + ), ); } @@ -291,8 +291,8 @@ public function test_add_robots_with_index_true_and_noindex_false() { [ 'index' => true, 'noindex' => false, - ] - ) + ], + ), ); } @@ -336,8 +336,8 @@ public function test_add_robots_with_noimageindex_and_maximagepreview_empty() { [ 'noimageindex' => true, 'max-image-preview' => '', - ] - ) + ], + ), ); } @@ -385,8 +385,8 @@ public function test_enforce_robots_congruence() { 'archive' => true, 'imageindex' => true, 'snippet' => true, - ] - ) + ], + ), ); } } diff --git a/tests/Unit/Integrations/Front_End_Integration_Test.php b/tests/Unit/Integrations/Front_End_Integration_Test.php index c492da93d07..808558c2abd 100644 --- a/tests/Unit/Integrations/Front_End_Integration_Test.php +++ b/tests/Unit/Integrations/Front_End_Integration_Test.php @@ -115,7 +115,7 @@ protected function set_up() { Mockery::mock( WPSEO_Replace_Vars::class ), $this->indexable_repository, $this->permalink_helper, - ] + ], )->makePartial(); // Set up mocks for classes which which are used in multiple tests. @@ -136,7 +136,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - Front_End_Integration::get_conditionals() + Front_End_Integration::get_conditionals(), ); } @@ -270,7 +270,7 @@ public function test_get_presenters_for_singular_page() { $this->assertEquals( $expected, - \array_map( $callback, $this->instance->get_presenters( 'Post_Type' ) ) + \array_map( $callback, $this->instance->get_presenters( 'Post_Type' ) ), ); } @@ -342,7 +342,7 @@ public function test_get_presenters_for_static_home_page() { $this->assertEquals( $expected, - \array_map( $callback, $this->instance->get_presenters( 'Static_Home_Page' ) ) + \array_map( $callback, $this->instance->get_presenters( 'Static_Home_Page' ) ), ); } @@ -390,7 +390,7 @@ public function test_get_presenters_for_error_page() { 'Yoast\WP\SEO\Presenters\Schema_Presenter', 'Yoast\WP\SEO\Presenters\Debug\Marker_Close_Presenter', ], - $expected + $expected, ); } @@ -460,7 +460,7 @@ public function test_get_presenters_for_non_singular_page() { 'Yoast\WP\SEO\Presenters\Schema_Presenter', 'Yoast\WP\SEO\Presenters\Debug\Marker_Close_Presenter', ], - $expected + $expected, ); } @@ -513,7 +513,7 @@ public function test_get_presenters_for_theme_without_title_tag_and_force_rewrit 'Yoast\WP\SEO\Presenters\Schema_Presenter', 'Yoast\WP\SEO\Presenters\Debug\Marker_Close_Presenter', ], - $actual + $actual, ); } @@ -560,7 +560,7 @@ public function test_get_presenters_for_theme_on_rest_request() { 'Yoast\WP\SEO\Presenters\Schema_Presenter', 'Yoast\WP\SEO\Presenters\Debug\Marker_Close_Presenter', ], - $actual + $actual, ); } @@ -614,7 +614,7 @@ public function test_get_presenters_for_theme_without_title_tag_and_force_rewrit 'Yoast\WP\SEO\Presenters\Schema_Presenter', 'Yoast\WP\SEO\Presenters\Debug\Marker_Close_Presenter', ], - $expected + $expected, ); } @@ -681,7 +681,7 @@ public function test_filter_robots_presenter_and_wp_robots_to_wp_head_filter() { 'Yoast\WP\SEO\Presenters\Title_Presenter', 'Yoast\WP\SEO\Presenters\Meta_Description_Presenter', ], - $this->instance->filter_robots_presenter( $presenters ) + $this->instance->filter_robots_presenter( $presenters ), ); } @@ -713,7 +713,7 @@ public function test_rest_request_should_output_robots_presenter() { 'Yoast\WP\SEO\Presenters\Meta_Description_Presenter', 'Yoast\WP\SEO\Presenters\Robots_Presenter', ], - $this->instance->filter_robots_presenter( $presenters ) + $this->instance->filter_robots_presenter( $presenters ), ); } diff --git a/tests/Unit/Integrations/Settings_Integration_Test.php b/tests/Unit/Integrations/Settings_Integration_Test.php index 59b7e01e83f..ca1907f425d 100644 --- a/tests/Unit/Integrations/Settings_Integration_Test.php +++ b/tests/Unit/Integrations/Settings_Integration_Test.php @@ -149,7 +149,7 @@ public function set_up() { $manual_post_collection, $file_runner, $this->route_helper, - $this->schema_configuration + $this->schema_configuration, ); $this->instance_double = new Settings_Integration_Double( @@ -170,7 +170,7 @@ public function set_up() { $manual_post_collection, $file_runner, $this->route_helper, - $this->schema_configuration + $this->schema_configuration, ); } @@ -186,7 +186,7 @@ public function test_get_conditionals() { [ Settings_Conditional::class, ], - Settings_Integration::get_conditionals() + Settings_Integration::get_conditionals(), ); } @@ -224,77 +224,77 @@ public function test_construct() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, $this->getPropertyValue( $this->instance, 'asset_manager' ), - 'asset_manager is set.' + 'asset_manager is set.', ); $this->assertInstanceOf( WPSEO_Replace_Vars::class, $this->getPropertyValue( $this->instance, 'replace_vars' ), - 'replace_vars is set.' + 'replace_vars is set.', ); $this->assertInstanceOf( Schema_Types::class, $this->getPropertyValue( $this->instance, 'schema_types' ), - 'schema_types is set.' + 'schema_types is set.', ); $this->assertInstanceOf( Current_Page_Helper::class, $this->getPropertyValue( $this->instance, 'current_page_helper' ), - 'current_page_helper is set.' + 'current_page_helper is set.', ); $this->assertInstanceOf( Post_Type_Helper::class, $this->getPropertyValue( $this->instance, 'post_type_helper' ), - 'post_type_helper is set.' + 'post_type_helper is set.', ); $this->assertInstanceOf( Language_Helper::class, $this->getPropertyValue( $this->instance, 'language_helper' ), - 'language_helper is set.' + 'language_helper is set.', ); $this->assertInstanceOf( Taxonomy_Helper::class, $this->getPropertyValue( $this->instance, 'taxonomy_helper' ), - 'taxonomy_helper is set.' + 'taxonomy_helper is set.', ); $this->assertInstanceOf( Product_Helper::class, $this->getPropertyValue( $this->instance, 'product_helper' ), - 'product_helper is set.' + 'product_helper is set.', ); $this->assertInstanceOf( Woocommerce_Helper::class, $this->getPropertyValue( $this->instance, 'woocommerce_helper' ), - 'woocommerce_helper is set.' + 'woocommerce_helper is set.', ); $this->assertInstanceOf( Article_Helper::class, $this->getPropertyValue( $this->instance, 'article_helper' ), - 'article_helper is set.' + 'article_helper is set.', ); $this->assertInstanceOf( User_Helper::class, $this->getPropertyValue( $this->instance, 'user_helper' ), - 'user_helper is set.' + 'user_helper is set.', ); $this->assertInstanceOf( Options_Helper::class, $this->getPropertyValue( $this->instance, 'options' ), - 'Options helper is set.' + 'Options helper is set.', ); $this->assertInstanceOf( Content_Type_Visibility_Dismiss_Notifications::class, $this->getPropertyValue( $this->instance, 'content_type_visibility' ), - 'Content type visibility notifications is set.' + 'Content type visibility notifications is set.', ); $this->assertInstanceOf( Route_Helper::class, $this->getPropertyValue( $this->instance, 'route_helper' ), - 'Route_Helper is set.' + 'Route_Helper is set.', ); $this->assertInstanceOf( Schema_Configuration::class, $this->getPropertyValue( $this->instance, 'schema_configuration' ), - 'Schema_Configuration is set.' + 'Schema_Configuration is set.', ); } @@ -570,7 +570,7 @@ public function test_get_defaults_from_local_seo( $should_local_get_options, $mu 'location_email' => 'example@location.con', 'location_vat_id' => '123456', 'location_tax_id' => '654321', - ] + ], ); Monkey\Functions\expect( 'wpseo_has_primary_location' ) @@ -611,7 +611,7 @@ public function test_get_defaults_from_local_seo_when_there_is_primary_location( 'location_email' => 'example@location.con', 'location_vat_id' => '123456', 'location_tax_id' => '654321', - ] + ], ); Monkey\Functions\expect( 'wpseo_has_primary_location' ) @@ -681,7 +681,7 @@ public function test_get_defaults_from_local_seo_with_shared_business_info_and_p 'location_email' => 'example@location.con', 'location_vat_id' => '123456', 'location_tax_id' => '654321', - ] + ], ); Monkey\Functions\expect( 'wpseo_has_primary_location' ) diff --git a/tests/Unit/Integrations/Support_Integration_Test.php b/tests/Unit/Integrations/Support_Integration_Test.php index 05e65248c69..cb0ac672200 100644 --- a/tests/Unit/Integrations/Support_Integration_Test.php +++ b/tests/Unit/Integrations/Support_Integration_Test.php @@ -131,8 +131,8 @@ public function test_construct() { $this->product_helper, $this->shortlink_helper, $this->woocommerce_conditional, - $this->addon_manager - ) + $this->addon_manager, + ), ); } @@ -149,7 +149,7 @@ public function test_get_conditionals() { Admin_Conditional::class, User_Can_Manage_Wpseo_Options_Conditional::class, ], - Support_Integration::get_conditionals() + Support_Integration::get_conditionals(), ); } @@ -218,7 +218,7 @@ public function test_add_page() { [ 'page1', '', 'Page 1', 'manage_options', 'page1', [ $this, 'display_page' ] ], [ 'page2', '', 'Page 2', 'manage_options', 'page2', [ $this, 'display_page' ] ], [ 'page3', '', 'Page 3', 'manage_options', 'page3', [ $this, 'display_page' ] ], - ] + ], ); // Assert that the new page was added at index 3. diff --git a/tests/Unit/Integrations/Third_Party/AMP_Test.php b/tests/Unit/Integrations/Third_Party/AMP_Test.php index d3aacbd6110..3681b174690 100644 --- a/tests/Unit/Integrations/Third_Party/AMP_Test.php +++ b/tests/Unit/Integrations/Third_Party/AMP_Test.php @@ -54,7 +54,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - AMP::get_conditionals() + AMP::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Third_Party/BbPress_Test.php b/tests/Unit/Integrations/Third_Party/BbPress_Test.php index 81b38255a8f..d6c4b6d4855 100644 --- a/tests/Unit/Integrations/Third_Party/BbPress_Test.php +++ b/tests/Unit/Integrations/Third_Party/BbPress_Test.php @@ -54,7 +54,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class ], - BbPress::get_conditionals() + BbPress::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Third_Party/Exclude_Elementor_Post_Types_Test.php b/tests/Unit/Integrations/Third_Party/Exclude_Elementor_Post_Types_Test.php index 594e81afe7b..585f93f600e 100644 --- a/tests/Unit/Integrations/Third_Party/Exclude_Elementor_Post_Types_Test.php +++ b/tests/Unit/Integrations/Third_Party/Exclude_Elementor_Post_Types_Test.php @@ -45,7 +45,7 @@ public function set_up() { public function test_get_conditionals() { self::assertEquals( [ Elementor_Activated_Conditional::class ], - Exclude_Elementor_Post_Types::get_conditionals() + Exclude_Elementor_Post_Types::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Third_Party/Exclude_WooCommerce_Post_Types_Test.php b/tests/Unit/Integrations/Third_Party/Exclude_WooCommerce_Post_Types_Test.php index baf8430bd60..0526fb73f7d 100644 --- a/tests/Unit/Integrations/Third_Party/Exclude_WooCommerce_Post_Types_Test.php +++ b/tests/Unit/Integrations/Third_Party/Exclude_WooCommerce_Post_Types_Test.php @@ -45,7 +45,7 @@ public function set_up() { public function test_get_conditionals() { self::assertEquals( [ WooCommerce_Conditional::class ], - Exclude_WooCommerce_Post_Types::get_conditionals() + Exclude_WooCommerce_Post_Types::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Third_Party/Jetpack_Test.php b/tests/Unit/Integrations/Third_Party/Jetpack_Test.php index 77b98e6b570..e1ad22a1350 100644 --- a/tests/Unit/Integrations/Third_Party/Jetpack_Test.php +++ b/tests/Unit/Integrations/Third_Party/Jetpack_Test.php @@ -45,7 +45,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Front_End_Conditional::class, Jetpack_Conditional::class, Open_Graph_Conditional::class ], - Jetpack::get_conditionals() + Jetpack::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Third_Party/WPML_Test.php b/tests/Unit/Integrations/Third_Party/WPML_Test.php index 97d8e4b3ff7..760a7715064 100644 --- a/tests/Unit/Integrations/Third_Party/WPML_Test.php +++ b/tests/Unit/Integrations/Third_Party/WPML_Test.php @@ -44,7 +44,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ WPML_Conditional::class ], - WPML::get_conditionals() + WPML::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Third_Party/WPML_WPSEO_Notification_Test.php b/tests/Unit/Integrations/Third_Party/WPML_WPSEO_Notification_Test.php index b80aea3c10f..db9e4762baf 100644 --- a/tests/Unit/Integrations/Third_Party/WPML_WPSEO_Notification_Test.php +++ b/tests/Unit/Integrations/Third_Party/WPML_WPSEO_Notification_Test.php @@ -60,7 +60,7 @@ public function set_up() { $this->instance = new WPML_WPSEO_Notification( $this->short_link_helper, $this->notification_center, - $this->wpml_wpseo_conditional + $this->wpml_wpseo_conditional, ); } @@ -74,15 +74,15 @@ public function set_up() { public function test_constructor() { self::assertInstanceOf( Yoast_Notification_Center::class, - $this->getPropertyValue( $this->instance, 'notification_center' ) + $this->getPropertyValue( $this->instance, 'notification_center' ), ); self::assertInstanceOf( WPML_WPSEO_Conditional::class, - $this->getPropertyValue( $this->instance, 'wpml_wpseo_conditional' ) + $this->getPropertyValue( $this->instance, 'wpml_wpseo_conditional' ), ); self::assertInstanceOf( Short_Link_Helper::class, - $this->getPropertyValue( $this->instance, 'short_link_helper' ) + $this->getPropertyValue( $this->instance, 'short_link_helper' ), ); } diff --git a/tests/Unit/Integrations/Third_Party/Web_Stories_Post_Edit_Test.php b/tests/Unit/Integrations/Third_Party/Web_Stories_Post_Edit_Test.php index 2ad0d61aa94..54d90674845 100644 --- a/tests/Unit/Integrations/Third_Party/Web_Stories_Post_Edit_Test.php +++ b/tests/Unit/Integrations/Third_Party/Web_Stories_Post_Edit_Test.php @@ -46,7 +46,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Web_Stories_Conditional::class, Post_Conditional::class ], - Web_Stories_Post_Edit::get_conditionals() + Web_Stories_Post_Edit::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Third_Party/Web_Stories_Test.php b/tests/Unit/Integrations/Third_Party/Web_Stories_Test.php index bc222c9b13f..ddfb6c7d765 100644 --- a/tests/Unit/Integrations/Third_Party/Web_Stories_Test.php +++ b/tests/Unit/Integrations/Third_Party/Web_Stories_Test.php @@ -62,7 +62,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Web_Stories_Conditional::class ], - Web_Stories::get_conditionals() + Web_Stories::get_conditionals(), ); } @@ -76,7 +76,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Front_End_Integration::class, - $this->getPropertyValue( $this->instance, 'front_end' ) + $this->getPropertyValue( $this->instance, 'front_end' ), ); } diff --git a/tests/Unit/Integrations/Third_Party/Wincher_Publish_Test.php b/tests/Unit/Integrations/Third_Party/Wincher_Publish_Test.php index e1c92a6a1c1..d358d8e0778 100644 --- a/tests/Unit/Integrations/Third_Party/Wincher_Publish_Test.php +++ b/tests/Unit/Integrations/Third_Party/Wincher_Publish_Test.php @@ -81,7 +81,7 @@ protected function set_up() { $this->options_helper, $this->keyphrases_action, $this->account_action, - ] + ], ) ->shouldAllowMockingProtectedMethods() ->makePartial(); @@ -102,7 +102,7 @@ public function test_get_conditionals() { Wincher_Automatically_Track_Conditional::class, Wincher_Token_Conditional::class, ], - Wincher_Publish::get_conditionals() + Wincher_Publish::get_conditionals(), ); } @@ -118,27 +118,27 @@ public function test_constructor() { $this->wincher_enabled, $this->options_helper, $this->keyphrases_action, - $this->account_action + $this->account_action, ); $this->assertInstanceOf( Wincher_Enabled_Conditional::class, - $this->getPropertyValue( $instance, 'wincher_enabled' ) + $this->getPropertyValue( $instance, 'wincher_enabled' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $instance, 'options_helper' ) + $this->getPropertyValue( $instance, 'options_helper' ), ); $this->assertInstanceOf( Wincher_Keyphrases_Action::class, - $this->getPropertyValue( $instance, 'keyphrases_action' ) + $this->getPropertyValue( $instance, 'keyphrases_action' ), ); $this->assertInstanceOf( Wincher_Account_Action::class, - $this->getPropertyValue( $instance, 'account_action' ) + $this->getPropertyValue( $instance, 'account_action' ), ); } @@ -174,7 +174,7 @@ public function test_track_request() { 'yoast seo', 'blog seo', 'wincher', - ] + ], ); $this->account_action @@ -186,7 +186,7 @@ public function test_track_request() { 'limit' => 100, 'usage' => 10, 'status' => 200, - ] + ], ); $this->keyphrases_action->expects( 'track_keyphrases' )->once(); diff --git a/tests/Unit/Integrations/Third_Party/WooCommerce_Permalinks_Test.php b/tests/Unit/Integrations/Third_Party/WooCommerce_Permalinks_Test.php index b57b13e7187..02f2b43734b 100644 --- a/tests/Unit/Integrations/Third_Party/WooCommerce_Permalinks_Test.php +++ b/tests/Unit/Integrations/Third_Party/WooCommerce_Permalinks_Test.php @@ -57,7 +57,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ WooCommerce_Conditional::class, Migrations_Conditional::class ], - Woocommerce_Permalinks::get_conditionals() + Woocommerce_Permalinks::get_conditionals(), ); } @@ -71,7 +71,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); } @@ -107,8 +107,8 @@ public function test_filter_product_from_post_types() { 'post' => 'post', 'page' => 'page', 'product' => 'product', - ] - ) + ], + ), ); } diff --git a/tests/Unit/Integrations/Third_Party/WooCommerce_Post_Edit_Test.php b/tests/Unit/Integrations/Third_Party/WooCommerce_Post_Edit_Test.php index 97045487d84..6cb366949a3 100644 --- a/tests/Unit/Integrations/Third_Party/WooCommerce_Post_Edit_Test.php +++ b/tests/Unit/Integrations/Third_Party/WooCommerce_Post_Edit_Test.php @@ -46,7 +46,7 @@ protected function set_up() { public function test_conditionals() { $this->assertEquals( [ WooCommerce_Conditional::class, Post_Conditional::class ], - WooCommerce_Post_Edit::get_conditionals() + WooCommerce_Post_Edit::get_conditionals(), ); } @@ -66,8 +66,8 @@ public function test_register_hooks() { [ $this->instance, 'remove_meta_description_date', - ] - ) + ], + ), ); } diff --git a/tests/Unit/Integrations/Third_Party/WooCommerce_Test.php b/tests/Unit/Integrations/Third_Party/WooCommerce_Test.php index 83fe51b6994..d04cdfcf13d 100644 --- a/tests/Unit/Integrations/Third_Party/WooCommerce_Test.php +++ b/tests/Unit/Integrations/Third_Party/WooCommerce_Test.php @@ -113,7 +113,7 @@ protected function set_up() { $this->context_memoizer, $this->repository, $this->pagination_helper, - $this->woocommerce_helper + $this->woocommerce_helper, ); $presentation = new Indexable_Presentation(); @@ -131,7 +131,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ WooCommerce_Conditional::class, Front_End_Conditional::class ], - WooCommerce::get_conditionals() + WooCommerce::get_conditionals(), ); } @@ -149,16 +149,16 @@ public function test_constructor() { $this->context_memoizer, $this->repository, $this->pagination_helper, - $this->woocommerce_helper + $this->woocommerce_helper, ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $instance, 'options' ) + $this->getPropertyValue( $instance, 'options' ), ); $this->assertInstanceOf( WPSEO_Replace_Vars::class, - $this->getPropertyValue( $instance, 'replace_vars' ) + $this->getPropertyValue( $instance, 'replace_vars' ), ); } @@ -321,7 +321,7 @@ public function test_title( $expected, $model_value, $template_value, $is_shop_p $this->assertEquals( $expected, - $this->instance->title( 'This is a value', $this->presentation ) + $this->instance->title( 'This is a value', $this->presentation ), ); } @@ -366,7 +366,7 @@ public function test_description( $expected, $model_value, $template_value, $is_ $this->assertEquals( $expected, - $this->instance->description( 'This is a value', $this->presentation ) + $this->instance->description( 'This is a value', $this->presentation ), ); } @@ -461,7 +461,7 @@ public function test_title_by_using_the_product_archive_template() { $this->assertEquals( 'This is a template value', - $this->instance->title( 'This is a value', $this->presentation ) + $this->instance->title( 'This is a value', $this->presentation ), ); } @@ -498,7 +498,7 @@ public function test_description_by_using_the_product_archive_template() { $this->assertEquals( 'This is a template value', - $this->instance->description( 'This is a value', $this->presentation ) + $this->instance->description( 'This is a value', $this->presentation ), ); } diff --git a/tests/Unit/Integrations/Watchers/Addon_Update_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Addon_Update_Watcher_Test.php index c1477324815..6306ff6f94b 100644 --- a/tests/Unit/Integrations/Watchers/Addon_Update_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Addon_Update_Watcher_Test.php @@ -173,7 +173,7 @@ public function test_enable_auto_updates_for_add_ons_on_free_auto_update_enabled $this->instance->toggle_auto_updates_for_add_ons( 'auto_update_plugins', $new, - $old + $old, ); } @@ -221,7 +221,7 @@ public function test_disable_auto_updates_for_add_ons_on_free_auto_update_disabl $this->instance->toggle_auto_updates_for_add_ons( 'auto_update_plugins', $new, - $old + $old, ); } @@ -265,7 +265,7 @@ public function test_do_nothing_for_add_ons_when_nothing_happens_to_free_auto_up $this->instance->toggle_auto_updates_for_add_ons( 'auto_update_plugins', $new, - $old + $old, ); } @@ -285,7 +285,7 @@ public function test_html_not_replaced_when_html_not_string() { $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - 'other-plugin/plugin-file.php' + 'other-plugin/plugin-file.php', ); self::assertEquals( $old_html, $new_html ); @@ -308,7 +308,7 @@ public function test_html_not_replaced_when_auto_updated_plugins_does_not_exist( $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - 'wordpress-seo-premium/wp-seo-premium.php' + 'wordpress-seo-premium/wp-seo-premium.php', ); self::assertEquals( 'Auto-updates are disabled based on this setting for Yoast SEO.', $new_html ); @@ -331,7 +331,7 @@ public function test_html_not_replaced_when_auto_updated_plugins_not_an_array() $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - 'wordpress-seo-premium/wp-seo-premium.php' + 'wordpress-seo-premium/wp-seo-premium.php', ); self::assertEquals( 'Auto-updates are disabled based on this setting for Yoast SEO.', $new_html ); @@ -355,7 +355,7 @@ public function test_do_not_replace_auto_update_toggles_from_other_plugins() { $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - 'other-plugin/plugin-file.php' + 'other-plugin/plugin-file.php', ); self::assertEquals( $old_html, $new_html ); @@ -383,7 +383,7 @@ public function test_replace_auto_update_toggles_from_addons_with_enabled_text( $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - $plugin + $plugin, ); self::assertEquals( 'Auto-updates are enabled based on this setting for Yoast SEO.', $new_html ); @@ -412,7 +412,7 @@ public function test_replace_auto_update_toggles_from_addons_with_disabled_text( $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - $plugin + $plugin, ); self::assertEquals( 'Auto-updates are disabled based on this setting for Yoast SEO.', $new_html ); @@ -441,7 +441,7 @@ public function test_replace_auto_update_toggles_from_addons_when_enabled_plugin $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - $plugin + $plugin, ); self::assertEquals( 'Auto-updates are disabled based on this setting for Yoast SEO.', $new_html ); @@ -470,7 +470,7 @@ public function test_replace_auto_update_toggles_from_addons_when_enabled_plugin $new_html = $this->instance->replace_auto_update_toggles_of_addons( $old_html, - $plugin + $plugin, ); self::assertEquals( 'Auto-updates are disabled based on this setting for Yoast SEO.', $new_html ); diff --git a/tests/Unit/Integrations/Watchers/Auto_Update_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Auto_Update_Watcher_Test.php index 08807215f49..fe858495a2f 100644 --- a/tests/Unit/Integrations/Watchers/Auto_Update_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Auto_Update_Watcher_Test.php @@ -43,7 +43,7 @@ public function set_up() { $this->notification_center = Mockery::mock( Yoast_Notification_Center::class ); $this->instance = new Auto_Update_Watcher( - $this->notification_center + $this->notification_center, ); } @@ -57,7 +57,7 @@ public function set_up() { public function test_constructor() { self::assertInstanceOf( Yoast_Notification_Center::class, - self::getPropertyValue( $this->instance, 'notification_center' ) + self::getPropertyValue( $this->instance, 'notification_center' ), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Ancestor_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Ancestor_Watcher_Test.php index 30065b03a78..fe033cb19ac 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Ancestor_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Ancestor_Watcher_Test.php @@ -96,7 +96,7 @@ protected function set_up() { $this->indexable_hierarchy_repository, $this->indexable_helper, $this->permalink_helper, - $this->post_type_helper + $this->post_type_helper, ); } @@ -145,15 +145,15 @@ public function test_reset_children_for_non_changed_permalink() { public function test_construct() { $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); $this->assertInstanceOf( Indexable_Hierarchy_Builder::class, - $this->getPropertyValue( $this->instance, 'indexable_hierarchy_builder' ) + $this->getPropertyValue( $this->instance, 'indexable_hierarchy_builder' ), ); $this->assertInstanceOf( Permalink_Helper::class, - $this->getPropertyValue( $this->instance, 'permalink_helper' ) + $this->getPropertyValue( $this->instance, 'permalink_helper' ), ); } @@ -167,7 +167,7 @@ public function test_construct() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Ancestor_Watcher::get_conditionals() + Indexable_Ancestor_Watcher::get_conditionals(), ); } @@ -355,9 +355,9 @@ static function ( $haystack, $prop ) { static function ( $e ) use ( $prop ) { return $e->{$prop}; }, - $haystack + $haystack, ); - } + }, ); $this->set_expectations_for_get_object_ids_for_term( $term_id, $indexable_1->object_id, $indexable_2->object_id ); @@ -375,7 +375,7 @@ static function ( $e ) use ( $prop ) { 2 => 21, ], 'post', - false + false, ) ->andReturn( [ $indexable_term_1, $indexable_term_2 ] ); @@ -390,7 +390,7 @@ static function ( $e ) use ( $prop ) { [ 0 => 566, 2 => 569, - ] + ], ) ->andReturn( [ $additional_indexable_2 ] ); @@ -418,7 +418,7 @@ private function set_expectations_for_get_object_ids_for_term( ...$object_ids ) FROM %i WHERE term_id IN( ' . \implode( ', ', \array_fill( 0, ( \count( $object_ids ) ), '%s' ) ) . ' )', $wpdb->term_taxonomy, - ...$object_ids + ...$object_ids, ); $wpdb->expects( 'get_col' ) @@ -432,7 +432,7 @@ private function set_expectations_for_get_object_ids_for_term( ...$object_ids ) $wpdb->term_relationships, 321, 322, - 323 + 323, ); $wpdb->expects( 'get_col' ) diff --git a/tests/Unit/Integrations/Watchers/Indexable_Attachment_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Attachment_Watcher_Test.php index dfd2f04125f..6c535fa1cd4 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Attachment_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Attachment_Watcher_Test.php @@ -78,7 +78,7 @@ protected function set_up() { $this->indexing_helper, $this->attachment_cleanup, $this->notification_center, - $this->indexable_helper + $this->indexable_helper, ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Author_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Author_Watcher_Test.php index a831707de35..97d3b35dede 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Author_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Author_Watcher_Test.php @@ -67,7 +67,7 @@ protected function set_up() { $this->instance = new Indexable_Author_Watcher( $this->repository, $this->indexable_helper, - $this->builder + $this->builder, ); } @@ -81,7 +81,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Author_Watcher::get_conditionals() + Indexable_Author_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Category_Permalink_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Category_Permalink_Watcher_Test.php index 5332f00d481..a5faf118c72 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Category_Permalink_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Category_Permalink_Watcher_Test.php @@ -71,7 +71,7 @@ protected function set_up() { [ 'wp_next_scheduled' => false, 'wp_schedule_event' => false, - ] + ], ); $this->options = Mockery::mock( Options_Helper::class ); @@ -83,7 +83,7 @@ protected function set_up() { $this->post_type, $this->options, $this->indexable_helper, - $this->taxonomy_helper + $this->taxonomy_helper, ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Date_Archive_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Date_Archive_Watcher_Test.php index 2aad3381ebe..3b6bceefe9c 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Date_Archive_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Date_Archive_Watcher_Test.php @@ -66,7 +66,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Date_Archive_Watcher::get_conditionals() + Indexable_Date_Archive_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_HomeUrl_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_HomeUrl_Watcher_Test.php index 5e958e0a467..4e256ce770b 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_HomeUrl_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_HomeUrl_Watcher_Test.php @@ -63,7 +63,7 @@ protected function set_up() { [ 'wp_next_scheduled' => false, 'wp_schedule_event' => false, - ] + ], ); $this->post_type = Mockery::mock( Post_Type_Helper::class ); @@ -84,7 +84,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_HomeUrl_Watcher::get_conditionals() + Indexable_HomeUrl_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Home_Page_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Home_Page_Watcher_Test.php index 5daeae0d21c..00e2054f5e5 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Home_Page_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Home_Page_Watcher_Test.php @@ -66,7 +66,7 @@ protected function set_up() { $this->instance = new Indexable_Home_Page_Watcher( $this->repository, $this->indexable_helper, - $this->builder + $this->builder, ); } @@ -80,7 +80,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Home_Page_Watcher::get_conditionals() + Indexable_Home_Page_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Permalink_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Permalink_Watcher_Test.php index 364532e51f7..e0f701b65d9 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Permalink_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Permalink_Watcher_Test.php @@ -71,7 +71,7 @@ protected function set_up() { [ 'wp_next_scheduled' => false, 'wp_schedule_event' => false, - ] + ], ); $this->post_type = Mockery::mock( Post_Type_Helper::class ); @@ -93,7 +93,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Permalink_Watcher::get_conditionals() + Indexable_Permalink_Watcher::get_conditionals(), ); } @@ -450,7 +450,7 @@ public function test_should_reset_altered_custom_taxonomies() { [ 'book-category' => 'book-category', 'book-genre' => 'book-genre', - ] + ], ); $this->options @@ -461,7 +461,7 @@ public function test_should_reset_altered_custom_taxonomies() { [ 'book-category' => 'yoast-book-category', 'book-genre' => 'yoast-test-book-genre', - ] + ], ); $this->taxonomy_helper @@ -480,7 +480,7 @@ public function test_should_reset_altered_custom_taxonomies() { [ 'book-category' => 'yoast-test-book-category', 'book-genre' => 'yoast-test-book-genre', - ] + ], ); $this->instance->reset_altered_custom_taxonomies(); @@ -501,7 +501,7 @@ public function test_shouldnt_reset_altered_custom_taxonomies() { [ 'book-category' => 'book-category', 'book-genre' => 'book-genre', - ] + ], ); $this->options @@ -512,7 +512,7 @@ public function test_shouldnt_reset_altered_custom_taxonomies() { [ 'book-category' => 'yoast-test-book-category', 'book-genre' => 'yoast-test-book-genre', - ] + ], ); $this->taxonomy_helper @@ -531,7 +531,7 @@ public function test_shouldnt_reset_altered_custom_taxonomies() { [ 'book-category' => 'yoast-test-book-category', 'book-genre' => 'yoast-test-book-genre', - ] + ], ); $this->instance->reset_altered_custom_taxonomies(); diff --git a/tests/Unit/Integrations/Watchers/Indexable_Post_Meta_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Post_Meta_Watcher_Test.php index e827878bc01..e1a5ffc002c 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Post_Meta_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Post_Meta_Watcher_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Post_Watcher::get_conditionals() + Indexable_Post_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Archive_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Archive_Watcher_Test.php index b1a65c97312..ecd7b20b82c 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Archive_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Archive_Watcher_Test.php @@ -68,7 +68,7 @@ protected function set_up() { $this->instance = new Indexable_Post_Type_Archive_Watcher( $this->repository, $this->indexable_helper, - $this->builder + $this->builder, ); } @@ -82,7 +82,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Post_Type_Archive_Watcher::get_conditionals() + Indexable_Post_Type_Archive_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Change_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Change_Watcher_Test.php index 711f0ac39fb..bba9626ba39 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Change_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Post_Type_Change_Watcher_Test.php @@ -93,7 +93,7 @@ protected function set_up() { $this->indexing_helper, $this->post_type_helper, $this->notification_center, - $this->indexable_helper + $this->indexable_helper, ); } @@ -111,7 +111,7 @@ public function test_get_conditionals() { Admin_Conditional::class, Migrations_Conditional::class, ], - Indexable_Post_Type_Change_Watcher::get_conditionals() + Indexable_Post_Type_Change_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Post_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Post_Watcher_Test.php index fd0f8942b5d..e1715455a7d 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Post_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Post_Watcher_Test.php @@ -122,7 +122,7 @@ protected function set_up() { $this->indexable_helper, $this->post, $this->logger, - ] + ], ) ->makePartial() ->shouldAllowMockingProtectedMethods(); @@ -138,7 +138,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Post_Watcher::get_conditionals() + Indexable_Post_Watcher::get_conditionals(), ); } @@ -627,7 +627,7 @@ public function test_get_related_indexables() { [ 'taxonomy', 'another-taxonomy', - ] + ], ); Monkey\Functions\expect( 'is_taxonomy_viewable' ) @@ -651,7 +651,7 @@ public function test_get_related_indexables() { (object) [ 'term_id' => 1414, ], - ] + ], ); Monkey\Functions\expect( 'get_the_terms' ) @@ -670,7 +670,7 @@ public function test_get_related_indexables() { 'term_id' => 1414, ], ], - 'term_id' + 'term_id', ) ->andReturn( [ 1337, 1414 ] ); @@ -702,7 +702,7 @@ public function test_get_related_indexables() { $this->assertEquals( [ $indexable, $indexable, $indexable, $indexable ], - $this->instance->get_related_indexables( $post ) + $this->instance->get_related_indexables( $post ), ); } } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Static_Home_Page_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Static_Home_Page_Watcher_Test.php index 7d546cbe578..dc26b5b3a18 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Static_Home_Page_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Static_Home_Page_Watcher_Test.php @@ -57,7 +57,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Admin_Conditional::class ], - Indexable_Static_Home_Page_Watcher::get_conditionals() + Indexable_Static_Home_Page_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_System_Page_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_System_Page_Watcher_Test.php index 056bb4a4d31..d2be5b8df4d 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_System_Page_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_System_Page_Watcher_Test.php @@ -66,7 +66,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_System_Page_Watcher::get_conditionals() + Indexable_System_Page_Watcher::get_conditionals(), ); } @@ -131,7 +131,7 @@ public function test_update_wpseo_titles_value_without_change() { 'other_key' => 'baz', 'title-search-wpseo' => 'baz', 'title-404-wpseo' => 'baz', - ] + ], ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Taxonomy_Change_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Taxonomy_Change_Watcher_Test.php index eaae46db50f..7b2b89d0acd 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Taxonomy_Change_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Taxonomy_Change_Watcher_Test.php @@ -93,7 +93,7 @@ protected function set_up() { $this->options, $this->taxonomy_helper, $this->notification_center, - $this->indexable_helper + $this->indexable_helper, ); } @@ -111,7 +111,7 @@ public function test_get_conditionals() { Admin_Conditional::class, Migrations_Conditional::class, ], - Indexable_Taxonomy_Change_Watcher::get_conditionals() + Indexable_Taxonomy_Change_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Indexable_Term_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Indexable_Term_Watcher_Test.php index c770d601568..93c098f1300 100644 --- a/tests/Unit/Integrations/Watchers/Indexable_Term_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Indexable_Term_Watcher_Test.php @@ -87,7 +87,7 @@ protected function set_up() { $this->builder, $this->link_builder, $this->indexable_helper, - $this->site + $this->site, ); } @@ -101,7 +101,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Indexable_Term_Watcher::get_conditionals() + Indexable_Term_Watcher::get_conditionals(), ); } @@ -212,7 +212,7 @@ public function test_build_indexable() { ->expects( 'build' ) ->with( $indexable, - 'This is a term description, with a link.' + 'This is a term description, with a link.', ); $this->indexable_helper @@ -377,7 +377,7 @@ public function test_build_does_not_exist() { ->expects( 'build' ) ->with( $indexable, - 'This is a term description, with a link.' + 'This is a term description, with a link.', ); $this->indexable_helper diff --git a/tests/Unit/Integrations/Watchers/Option_Titles_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Option_Titles_Watcher_Test.php index fa6c7cebb83..3fb913aaac1 100644 --- a/tests/Unit/Integrations/Watchers/Option_Titles_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Option_Titles_Watcher_Test.php @@ -48,7 +48,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Option_Titles_Watcher::get_conditionals() + Option_Titles_Watcher::get_conditionals(), ); } @@ -157,7 +157,7 @@ public function test_check_option_with_ancestors_being_removed() { )", 'wp_yoast_indexable_hierarchy', 'wp_yoast_indexable', - 'post' + 'post', ) ->andReturn( " @@ -167,7 +167,7 @@ public function test_check_option_with_ancestors_being_removed() { FROM `wp_yoast_indexable` WHERE object_type = 'post' AND object_sub_type IN( post ) - )" + )", ); $wpdb @@ -181,7 +181,7 @@ public function test_check_option_with_ancestors_being_removed() { FROM `wp_yoast_indexable` WHERE object_type = 'post' AND object_sub_type IN( post ) - )" + )", ) ->andReturn( 2 ); @@ -199,8 +199,8 @@ public function test_check_option_with_ancestors_being_removed() { ], [ 'post_types-post-maintax' => 1, - ] - ) + ], + ), ); } @@ -232,7 +232,7 @@ public function test_check_option_with_ancestors_not_being_removed() { )", 'wp_yoast_indexable_hierarchy', 'wp_yoast_indexable', - 'post' + 'post', ) ->andReturn( 'the query' ); @@ -256,8 +256,8 @@ public function test_check_option_with_ancestors_not_being_removed() { ], [ 'post_types-post-maintax' => 1, - ] - ) + ], + ), ); } } diff --git a/tests/Unit/Integrations/Watchers/Primary_Category_Quick_Edit_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Primary_Category_Quick_Edit_Watcher_Test.php index c43911cfcaa..d29a2c391e9 100644 --- a/tests/Unit/Integrations/Watchers/Primary_Category_Quick_Edit_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Primary_Category_Quick_Edit_Watcher_Test.php @@ -90,7 +90,7 @@ public function set_up() { $this->primary_term_repository, $this->post_type_helper, $this->indexable_repository, - $this->indexable_hierarchy_builder + $this->indexable_hierarchy_builder, ); } @@ -132,7 +132,7 @@ public function test_get_conditionals() { Migrations_Conditional::class, Doing_Post_Quick_Edit_Save_Conditional::class, ], - Primary_Category_Quick_Edit_Watcher::get_conditionals() + Primary_Category_Quick_Edit_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Primary_Term_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Primary_Term_Watcher_Test.php index eb248ab289d..5e92ce4db72 100644 --- a/tests/Unit/Integrations/Watchers/Primary_Term_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Primary_Term_Watcher_Test.php @@ -77,7 +77,7 @@ protected function set_up() { $this->site, $this->primary_term, $this->primary_term_builder, - ] + ], ) ->shouldAllowMockingProtectedMethods() ->makePartial(); @@ -93,7 +93,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Migrations_Conditional::class ], - Primary_Term_Watcher::get_conditionals() + Primary_Term_Watcher::get_conditionals(), ); } diff --git a/tests/Unit/Integrations/Watchers/Search_Engines_Discouraged_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Search_Engines_Discouraged_Watcher_Test.php index ed295485ee1..b6176007f0d 100644 --- a/tests/Unit/Integrations/Watchers/Search_Engines_Discouraged_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Search_Engines_Discouraged_Watcher_Test.php @@ -93,7 +93,7 @@ public function set_up() { $this->notification_helper, $this->current_page_helper, $this->options_helper, - $this->capability_helper + $this->capability_helper, ); } @@ -107,23 +107,23 @@ public function set_up() { public function test_constructor() { self::assertInstanceOf( Yoast_Notification_Center::class, - self::getPropertyValue( $this->instance, 'notification_center' ) + self::getPropertyValue( $this->instance, 'notification_center' ), ); self::assertInstanceOf( Notification_Helper::class, - self::getPropertyValue( $this->instance, 'notification_helper' ) + self::getPropertyValue( $this->instance, 'notification_helper' ), ); self::assertInstanceOf( Current_Page_Helper::class, - self::getPropertyValue( $this->instance, 'current_page_helper' ) + self::getPropertyValue( $this->instance, 'current_page_helper' ), ); self::assertInstanceOf( Options_Helper::class, - self::getPropertyValue( $this->instance, 'options_helper' ) + self::getPropertyValue( $this->instance, 'options_helper' ), ); self::assertInstanceOf( Capability_Helper::class, - self::getPropertyValue( $this->instance, 'capability_helper' ) + self::getPropertyValue( $this->instance, 'capability_helper' ), ); } diff --git a/tests/Unit/Integrations/Watchers/Woocommerce_Beta_Editor_Watcher_Test.php b/tests/Unit/Integrations/Watchers/Woocommerce_Beta_Editor_Watcher_Test.php index edccab9652b..fce942f56b9 100644 --- a/tests/Unit/Integrations/Watchers/Woocommerce_Beta_Editor_Watcher_Test.php +++ b/tests/Unit/Integrations/Watchers/Woocommerce_Beta_Editor_Watcher_Test.php @@ -76,7 +76,7 @@ public function set_up() { $this->notification_center, $this->notification_helper, $this->short_link_helper, - $this->woocommerce_conditional + $this->woocommerce_conditional, ); } @@ -90,15 +90,15 @@ public function set_up() { public function test_constructor() { self::assertInstanceOf( Yoast_Notification_Center::class, - self::getPropertyValue( $this->instance, 'notification_center' ) + self::getPropertyValue( $this->instance, 'notification_center' ), ); self::assertInstanceOf( Notification_Helper::class, - self::getPropertyValue( $this->instance, 'notification_helper' ) + self::getPropertyValue( $this->instance, 'notification_helper' ), ); self::assertInstanceOf( Short_Link_Helper::class, - self::getPropertyValue( $this->instance, 'short_link_helper' ) + self::getPropertyValue( $this->instance, 'short_link_helper' ), ); } diff --git a/tests/Unit/Integrations/Woocommerce_Product_Category_Permalink_Integration_Test.php b/tests/Unit/Integrations/Woocommerce_Product_Category_Permalink_Integration_Test.php index 8b564a08fd3..f555b3b6129 100644 --- a/tests/Unit/Integrations/Woocommerce_Product_Category_Permalink_Integration_Test.php +++ b/tests/Unit/Integrations/Woocommerce_Product_Category_Permalink_Integration_Test.php @@ -45,7 +45,7 @@ protected function set_up() { $this->dynamic_product_permalinks_conditional = Mockery::mock( Dynamic_Product_Permalinks_Conditional::class ); $this->instance = new Woocommerce_Product_Category_Permalink_Integration( - $this->dynamic_product_permalinks_conditional + $this->dynamic_product_permalinks_conditional, ); } @@ -62,7 +62,7 @@ public function test_get_conditionals() { WooCommerce_Version_Conditional::class, Woo_SEO_Inactive_Conditional::class, ], - Woocommerce_Product_Category_Permalink_Integration::get_conditionals() + Woocommerce_Product_Category_Permalink_Integration::get_conditionals(), ); } @@ -76,7 +76,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Dynamic_Product_Permalinks_Conditional::class, - $this->getPropertyValue( $this->instance, 'dynamic_product_permalinks_conditional' ) + $this->getPropertyValue( $this->instance, 'dynamic_product_permalinks_conditional' ), ); } @@ -92,7 +92,7 @@ public function test_register_hooks() { $this->assertNotFalse( \has_filter( 'wc_product_post_type_link_product_cat', [ $this->instance, 'restore_legacy_permalink_category' ] ), - 'Does not have expected wc_product_post_type_link_product_cat filter' + 'Does not have expected wc_product_post_type_link_product_cat filter', ); } @@ -150,7 +150,7 @@ public function test_restore_legacy_permalink_category_with_dynamic_permalinks_d [ 'parent' => 'DESC', 'term_id' => 'ASC', - ] + ], ) ->andReturn( $sorted_terms ); diff --git a/tests/Unit/Introductions/Application/AI_Brand_Insights_Post_Launch_Test.php b/tests/Unit/Introductions/Application/AI_Brand_Insights_Post_Launch_Test.php index 723f91f28ab..05063995bb3 100644 --- a/tests/Unit/Introductions/Application/AI_Brand_Insights_Post_Launch_Test.php +++ b/tests/Unit/Introductions/Application/AI_Brand_Insights_Post_Launch_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); } diff --git a/tests/Unit/Introductions/Application/Ai_Fix_Assessments_Upsell_Test.php b/tests/Unit/Introductions/Application/Ai_Fix_Assessments_Upsell_Test.php index 1b1e5114a10..6127eb714f4 100644 --- a/tests/Unit/Introductions/Application/Ai_Fix_Assessments_Upsell_Test.php +++ b/tests/Unit/Introductions/Application/Ai_Fix_Assessments_Upsell_Test.php @@ -71,11 +71,11 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } diff --git a/tests/Unit/Introductions/Application/Black_Friday_Announcement_Test.php b/tests/Unit/Introductions/Application/Black_Friday_Announcement_Test.php index b8deff2c58b..dae27d56bfc 100644 --- a/tests/Unit/Introductions/Application/Black_Friday_Announcement_Test.php +++ b/tests/Unit/Introductions/Application/Black_Friday_Announcement_Test.php @@ -63,7 +63,7 @@ protected function set_up() { $this->instance = new Black_Friday_Announcement( $this->current_page_helper, $this->promotion_manager, - $this->product_helper + $this->product_helper, ); } @@ -77,15 +77,15 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); $this->assertInstanceOf( Promotion_Manager::class, - $this->getPropertyValue( $this->instance, 'promotion_manager' ) + $this->getPropertyValue( $this->instance, 'promotion_manager' ), ); $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); } diff --git a/tests/Unit/Introductions/Application/Google_Docs_Addon_Upsell_Test.php b/tests/Unit/Introductions/Application/Google_Docs_Addon_Upsell_Test.php index 7e099eb29e4..24e38191d55 100644 --- a/tests/Unit/Introductions/Application/Google_Docs_Addon_Upsell_Test.php +++ b/tests/Unit/Introductions/Application/Google_Docs_Addon_Upsell_Test.php @@ -73,17 +73,17 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); } diff --git a/tests/Unit/Introductions/Domain/Introduction_Item_Test.php b/tests/Unit/Introductions/Domain/Introduction_Item_Test.php index ab9c3aeae8d..f3680a8c890 100644 --- a/tests/Unit/Introductions/Domain/Introduction_Item_Test.php +++ b/tests/Unit/Introductions/Domain/Introduction_Item_Test.php @@ -56,7 +56,7 @@ public function test_to_array() { 'id' => 'test', 'priority' => 5, ], - $this->instance->to_array() + $this->instance->to_array(), ); } diff --git a/tests/Unit/Introductions/Domain/Introductions_Bucket_Test.php b/tests/Unit/Introductions/Domain/Introductions_Bucket_Test.php index 72f987dda5f..e23c0d4c1d9 100644 --- a/tests/Unit/Introductions/Domain/Introductions_Bucket_Test.php +++ b/tests/Unit/Introductions/Domain/Introductions_Bucket_Test.php @@ -67,7 +67,7 @@ public function test_to_array() { 'priority' => 2, ], ], - $instance->to_array() + $instance->to_array(), ); } } diff --git a/tests/Unit/Introductions/Infrastructure/Introductions_Seen_Repository_Test.php b/tests/Unit/Introductions/Infrastructure/Introductions_Seen_Repository_Test.php index 52299877f51..5ae04e6ee80 100644 --- a/tests/Unit/Introductions/Infrastructure/Introductions_Seen_Repository_Test.php +++ b/tests/Unit/Introductions/Infrastructure/Introductions_Seen_Repository_Test.php @@ -54,7 +54,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } @@ -97,13 +97,13 @@ public static function provide_get_all_introductions_test_data() { 'meta' => [ 'foo' => [ 'is_seen' => true, - 'seen_on' => 12345678, + 'seen_on' => 12_345_678, ], ], 'expected' => [ 'foo' => [ 'is_seen' => true, - 'seen_on' => 12345678, + 'seen_on' => 12_345_678, ], ], ], @@ -190,7 +190,7 @@ public static function provide_is_introduction_seen_test_data() { 'meta' => [ 'foo' => [ 'is_seen' => true, - 'seen_on' => 12345678, + 'seen_on' => 12_345_678, ], ], 'expected' => true, @@ -210,7 +210,7 @@ public static function provide_is_introduction_seen_test_data() { 'meta' => [ 'foo' => [ 'is_seen' => 1, - 'seen_on' => 12345678, + 'seen_on' => 12_345_678, ], ], 'expected' => true, @@ -225,7 +225,7 @@ public static function provide_is_introduction_seen_test_data() { 'meta' => [ 'foo' => [ 'is_seen' => '1', - 'seen_on' => 12345678, + 'seen_on' => 12_345_678, ], ], 'expected' => true, @@ -298,13 +298,13 @@ public static function provide_set_introduction_test_data() { 'meta' => [ 'foo' => [ 'is_seen' => true, - 'seen_on' => 12345678, + 'seen_on' => 12_345_678, ], ], 'expected_meta' => [ 'foo' => [ 'is_seen' => true, - 'seen_on' => 12345678, + 'seen_on' => 12_345_678, ], ], ], diff --git a/tests/Unit/Introductions/Infrastructure/Wistia_Embed_Permission_Repository_Test.php b/tests/Unit/Introductions/Infrastructure/Wistia_Embed_Permission_Repository_Test.php index 77a9782cd73..59bddedf869 100644 --- a/tests/Unit/Introductions/Infrastructure/Wistia_Embed_Permission_Repository_Test.php +++ b/tests/Unit/Introductions/Infrastructure/Wistia_Embed_Permission_Repository_Test.php @@ -54,7 +54,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } diff --git a/tests/Unit/Introductions/User_Interface/Introductions_Integration_Test.php b/tests/Unit/Introductions/User_Interface/Introductions_Integration_Test.php index 2125ca980a6..19812998b82 100644 --- a/tests/Unit/Introductions/User_Interface/Introductions_Integration_Test.php +++ b/tests/Unit/Introductions/User_Interface/Introductions_Integration_Test.php @@ -106,7 +106,7 @@ protected function set_up() { $this->user_helper, $this->short_link_helper, $this->wistia_embed_permission_repository, - $this->woocommerce_conditional + $this->woocommerce_conditional, ); } @@ -131,31 +131,31 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $this->instance, 'admin_asset_manager' ) + $this->getPropertyValue( $this->instance, 'admin_asset_manager' ), ); $this->assertInstanceOf( Introductions_Collector::class, - $this->getPropertyValue( $this->instance, 'introductions_collector' ) + $this->getPropertyValue( $this->instance, 'introductions_collector' ), ); $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); $this->assertInstanceOf( Short_Link_Helper::class, - $this->getPropertyValue( $this->instance, 'short_link_helper' ) + $this->getPropertyValue( $this->instance, 'short_link_helper' ), ); $this->assertInstanceOf( Wistia_Embed_Permission_Repository::class, - $this->getPropertyValue( $this->instance, 'wistia_embed_permission_repository' ) + $this->getPropertyValue( $this->instance, 'wistia_embed_permission_repository' ), ); $this->assertInstanceOf( WooCommerce_Conditional::class, - $this->getPropertyValue( $this->instance, 'woocommerce_conditional' ) + $this->getPropertyValue( $this->instance, 'woocommerce_conditional' ), ); } @@ -368,7 +368,7 @@ private function expect_localized_data_for( $introductions, $user_id ) { 'pluginUrl' => $plugin_url, 'wistiaEmbedPermission' => $wistia_embed_permission, 'isWooEnabled' => true, - ] + ], ); } } diff --git a/tests/Unit/Introductions/User_Interface/Introductions_Seen_Route_Test.php b/tests/Unit/Introductions/User_Interface/Introductions_Seen_Route_Test.php index 6f995b4daea..cb044a4b74c 100644 --- a/tests/Unit/Introductions/User_Interface/Introductions_Seen_Route_Test.php +++ b/tests/Unit/Introductions/User_Interface/Introductions_Seen_Route_Test.php @@ -78,11 +78,11 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Introductions_Seen_Repository::class, - $this->getPropertyValue( $this->instance, 'introductions_seen_repository' ) + $this->getPropertyValue( $this->instance, 'introductions_seen_repository' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } @@ -129,7 +129,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); @@ -175,7 +175,7 @@ public function test_set_introduction_seen() { 'success' => true, ], ], - 200 + 200, ) ->once(); @@ -187,12 +187,12 @@ public function test_set_introduction_seen() { [ 'introduction_id' => $introduction_id, 'is_seen' => true, - ] + ], ); $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->set_introduction_seen( $wp_rest_request ) + $this->instance->set_introduction_seen( $wp_rest_request ), ); } @@ -223,7 +223,7 @@ public function test_set_introduction_seen_failed() { 'success' => false, ], ], - 400 + 400, ) ->once(); @@ -235,12 +235,12 @@ public function test_set_introduction_seen_failed() { [ 'introduction_id' => $introduction_id, 'is_seen' => true, - ] + ], ); $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->set_introduction_seen( $wp_rest_request ) + $this->instance->set_introduction_seen( $wp_rest_request ), ); } @@ -270,12 +270,12 @@ public function test_set_wistia_embed_permission_with_error() { [ 'introduction_id' => $introduction_id, 'is_seen' => true, - ] + ], ); $this->assertInstanceOf( 'WP_Error', - $this->instance->set_introduction_seen( $wp_rest_request ) + $this->instance->set_introduction_seen( $wp_rest_request ), ); } @@ -297,7 +297,7 @@ public function test_set_introduction_seen_invalid_id() { ->expects( '__construct' ) ->with( [], - 400 + 400, ) ->once(); @@ -309,12 +309,12 @@ public function test_set_introduction_seen_invalid_id() { [ 'introduction_id' => $introduction_id, 'is_seen' => true, - ] + ], ); $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->set_introduction_seen( $wp_rest_request ) + $this->instance->set_introduction_seen( $wp_rest_request ), ); } } diff --git a/tests/Unit/Introductions/User_Interface/Wistia_Embed_Permission_Route_Test.php b/tests/Unit/Introductions/User_Interface/Wistia_Embed_Permission_Route_Test.php index 29f491f37e4..5e83434863d 100644 --- a/tests/Unit/Introductions/User_Interface/Wistia_Embed_Permission_Route_Test.php +++ b/tests/Unit/Introductions/User_Interface/Wistia_Embed_Permission_Route_Test.php @@ -69,11 +69,11 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Wistia_Embed_Permission_Repository::class, - $this->getPropertyValue( $this->instance, 'wistia_embed_permission_repository' ) + $this->getPropertyValue( $this->instance, 'wistia_embed_permission_repository' ), ); $this->assertInstanceOf( User_Helper::class, - $this->getPropertyValue( $this->instance, 'user_helper' ) + $this->getPropertyValue( $this->instance, 'user_helper' ), ); } @@ -119,7 +119,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); @@ -162,13 +162,13 @@ public function test_get_wistia_embed_permission() { 'json' => (object) [ 'value' => true, ], - ] + ], ) ->once(); $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->get_wistia_embed_permission() + $this->instance->get_wistia_embed_permission(), ); } @@ -190,7 +190,7 @@ public function test_get_wistia_embed_permission_with_error() { $this->assertInstanceOf( 'WP_Error', - $this->instance->get_wistia_embed_permission() + $this->instance->get_wistia_embed_permission(), ); } @@ -219,7 +219,7 @@ public function test_set_wistia_embed_permission() { 'success' => true, ], ], - 200 + 200, ) ->once(); @@ -231,7 +231,7 @@ public function test_set_wistia_embed_permission() { $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->set_wistia_embed_permission( $wp_rest_request ) + $this->instance->set_wistia_embed_permission( $wp_rest_request ), ); } @@ -260,7 +260,7 @@ public function test_set_wistia_embed_permission_failed() { 'success' => false, ], ], - 400 + 400, ) ->once(); @@ -272,7 +272,7 @@ public function test_set_wistia_embed_permission_failed() { $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->set_wistia_embed_permission( $wp_rest_request ) + $this->instance->set_wistia_embed_permission( $wp_rest_request ), ); } @@ -300,7 +300,7 @@ public function test_set_wistia_embed_permission_with_error() { $this->assertInstanceOf( 'WP_Error', - $this->instance->set_wistia_embed_permission( $wp_rest_request ) + $this->instance->set_wistia_embed_permission( $wp_rest_request ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/Configuration/Abstract_Llms_Txt_Configuration_Test.php b/tests/Unit/Llms_Txt/Application/Configuration/Abstract_Llms_Txt_Configuration_Test.php index dff3c704caa..7ea96590c57 100644 --- a/tests/Unit/Llms_Txt/Application/Configuration/Abstract_Llms_Txt_Configuration_Test.php +++ b/tests/Unit/Llms_Txt/Application/Configuration/Abstract_Llms_Txt_Configuration_Test.php @@ -60,7 +60,7 @@ protected function set_up() { $this->instance = new Llms_Txt_Configuration( $this->runner, $this->post_type_helper, - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Llms_Txt/Application/Configuration/Llms_Txt_Configuration_Constructor_Test.php b/tests/Unit/Llms_Txt/Application/Configuration/Llms_Txt_Configuration_Constructor_Test.php index 432038714f7..2fa1209b019 100644 --- a/tests/Unit/Llms_Txt/Application/Configuration/Llms_Txt_Configuration_Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/Configuration/Llms_Txt_Configuration_Constructor_Test.php @@ -26,15 +26,15 @@ final class Llms_Txt_Configuration_Constructor_Test extends Abstract_Llms_Txt_Co public function test_constructor() { $this->assertInstanceOf( File_Runner::class, - $this->getPropertyValue( $this->instance, 'runner' ) + $this->getPropertyValue( $this->instance, 'runner' ), ); $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Abstract_Populate_File_Command_Handler_Test.php b/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Abstract_Populate_File_Command_Handler_Test.php index 36e04da278e..9c2aaa86db2 100644 --- a/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Abstract_Populate_File_Command_Handler_Test.php +++ b/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Abstract_Populate_File_Command_Handler_Test.php @@ -71,7 +71,7 @@ protected function setUp(): void { $this->options_helper, $this->file_system_adapter, $this->markdown_builder, - $this->permission_gate + $this->permission_gate, ); } } diff --git a/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Constructor_Test.php index 6cde9929425..a5711ef31cd 100644 --- a/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/File/Commands/Populate_File/Constructor_Test.php @@ -27,19 +27,19 @@ final class Constructor_Test extends Abstract_Populate_File_Command_Handler_Test public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( WordPress_File_System_Adapter::class, - $this->getPropertyValue( $this->instance, 'file_system_adapter' ) + $this->getPropertyValue( $this->instance, 'file_system_adapter' ), ); $this->assertInstanceOf( Markdown_Builder::class, - $this->getPropertyValue( $this->instance, 'markdown_builder' ) + $this->getPropertyValue( $this->instance, 'markdown_builder' ), ); $this->assertInstanceOf( WordPress_Llms_Txt_Permission_Gate::class, - $this->getPropertyValue( $this->instance, 'permission_gate' ) + $this->getPropertyValue( $this->instance, 'permission_gate' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Abstract_Remove_File_Command_Handler_Test.php b/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Abstract_Remove_File_Command_Handler_Test.php index acc5338f821..5cf2403daf0 100644 --- a/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Abstract_Remove_File_Command_Handler_Test.php +++ b/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Abstract_Remove_File_Command_Handler_Test.php @@ -61,7 +61,7 @@ protected function setUp(): void { $this->instance = new Remove_File_Command_Handler( $this->options_helper, $this->file_system_adapter, - $this->permission_gate + $this->permission_gate, ); } } diff --git a/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Constructor_Test.php index a895f8c9941..ae28d08bf9c 100644 --- a/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/File/Commands/Remove_File/Constructor_Test.php @@ -26,15 +26,15 @@ final class Constructor_Test extends Abstract_Remove_File_Command_Handler_Test { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( WordPress_File_System_Adapter::class, - $this->getPropertyValue( $this->instance, 'file_system_adapter' ) + $this->getPropertyValue( $this->instance, 'file_system_adapter' ), ); $this->assertInstanceOf( WordPress_Llms_Txt_Permission_Gate::class, - $this->getPropertyValue( $this->instance, 'permission_gate' ) + $this->getPropertyValue( $this->instance, 'permission_gate' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/File/Llms_Txt_Cron_Scheduler/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/File/Llms_Txt_Cron_Scheduler/Constructor_Test.php index 71ce9a61afa..6102bdd142f 100644 --- a/tests/Unit/Llms_Txt/Application/File/Llms_Txt_Cron_Scheduler/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/File/Llms_Txt_Cron_Scheduler/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Llms_Txt_Cron_Scheduler_Test { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Abstract_Description_Builder_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Abstract_Description_Builder_Test.php index 9fbce44f92d..aafc90336e1 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Abstract_Description_Builder_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Abstract_Description_Builder_Test.php @@ -41,7 +41,7 @@ protected function set_up() { $this->description_adapter = Mockery::mock( Description_Adapter::class ); $this->instance = new Description_Builder( - $this->description_adapter + $this->description_adapter, ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Constructor_Test.php index 8c0bc487b5b..4b4d8be6ed3 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Description_Builder/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Description_Builder_Test { public function test_constructor() { $this->assertInstanceOf( Description_Adapter::class, - $this->getPropertyValue( $this->instance, 'description_adapter' ) + $this->getPropertyValue( $this->instance, 'description_adapter' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Intro_Builder/Build_Intro_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Intro_Builder/Build_Intro_Test.php index d2604dcf487..6251c6bf8b6 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Intro_Builder/Build_Intro_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Intro_Builder/Build_Intro_Test.php @@ -24,7 +24,7 @@ final class Build_Intro_Test extends Abstract_Intro_Builder_Test { public function test_build_intro() { $built_intro = new Intro( 'Generated by Yoast SEO v1.0, this is an llms.txt file, meant for consumption by LLMs.', - [] + [], ); $this->assertEquals( $built_intro, $this->instance->build_intro() ); } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Abstract_Link_Lists_Builder_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Abstract_Link_Lists_Builder_Test.php index b57f2757df5..83e53b50076 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Abstract_Link_Lists_Builder_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Abstract_Link_Lists_Builder_Test.php @@ -51,7 +51,7 @@ protected function set_up() { $this->instance = new Link_Lists_Builder( $this->content_types_collector, - $this->terms_collector + $this->terms_collector, ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Constructor_Test.php index 3bcffd0321c..2ea5438258c 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Link_Lists_Builder/Constructor_Test.php @@ -24,11 +24,11 @@ final class Constructor_Test extends Abstract_Link_Lists_Builder_Test { public function test_constructor() { $this->assertInstanceOf( Content_Types_Collector::class, - $this->getPropertyValue( $this->instance, 'content_types_collector' ) + $this->getPropertyValue( $this->instance, 'content_types_collector' ), ); $this->assertInstanceOf( Terms_Collector::class, - $this->getPropertyValue( $this->instance, 'terms_collector' ) + $this->getPropertyValue( $this->instance, 'terms_collector' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Abstract_Markdown_Builder_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Abstract_Markdown_Builder_Test.php index f2606dc9b4a..0289addf717 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Abstract_Markdown_Builder_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Abstract_Markdown_Builder_Test.php @@ -101,7 +101,7 @@ protected function set_up() { $this->description_builder, $this->link_lists_builder, $this->markdown_escaper, - $this->optional_link_list_builder + $this->optional_link_list_builder, ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Constructor_Test.php index db3040dd377..055858897cb 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Constructor_Test.php @@ -29,31 +29,31 @@ final class Constructor_Test extends Abstract_Markdown_Builder_Test { public function test_constructor() { $this->assertInstanceOf( Llms_Txt_Renderer::class, - $this->getPropertyValue( $this->instance, 'llms_txt_renderer' ) + $this->getPropertyValue( $this->instance, 'llms_txt_renderer' ), ); $this->assertInstanceOf( Intro_Builder::class, - $this->getPropertyValue( $this->instance, 'intro_builder' ) + $this->getPropertyValue( $this->instance, 'intro_builder' ), ); $this->assertInstanceOf( Title_Builder::class, - $this->getPropertyValue( $this->instance, 'title_builder' ) + $this->getPropertyValue( $this->instance, 'title_builder' ), ); $this->assertInstanceOf( Description_Builder::class, - $this->getPropertyValue( $this->instance, 'description_builder' ) + $this->getPropertyValue( $this->instance, 'description_builder' ), ); $this->assertInstanceOf( Link_Lists_Builder::class, - $this->getPropertyValue( $this->instance, 'link_lists_builder' ) + $this->getPropertyValue( $this->instance, 'link_lists_builder' ), ); $this->assertInstanceOf( Markdown_Escaper::class, - $this->getPropertyValue( $this->instance, 'markdown_escaper' ) + $this->getPropertyValue( $this->instance, 'markdown_escaper' ), ); $this->assertInstanceOf( Optional_Link_List_Builder::class, - $this->getPropertyValue( $this->instance, 'optional_link_list_builder' ) + $this->getPropertyValue( $this->instance, 'optional_link_list_builder' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Render_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Render_Test.php index 30c0144ecf9..f72e8dd2537 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Render_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Markdown_Builder/Render_Test.php @@ -68,7 +68,7 @@ public function test_render() { $built_link_list1, $built_link_list2, $optional_built_link_list, - ] + ], ); $built_intro->shouldReceive( 'escape_markdown' )->once()->with( $this->markdown_escaper ); diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Abstract_Optional_Link_List_Builder_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Abstract_Optional_Link_List_Builder_Test.php index 24e9b423520..67b103b7ad1 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Abstract_Optional_Link_List_Builder_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Abstract_Optional_Link_List_Builder_Test.php @@ -41,7 +41,7 @@ protected function set_up() { $this->sitemap_link_collector = Mockery::mock( Sitemap_Link_Collector::class ); $this->instance = new Optional_Link_List_Builder( - $this->sitemap_link_collector + $this->sitemap_link_collector, ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Constructor_Test.php index dc9e31597f2..9fe34e062e4 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Optional_Link_List_Builder/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Optional_Link_List_Builder_Test { public function test_constructor() { $this->assertInstanceOf( Sitemap_Link_Collector::class, - $this->getPropertyValue( $this->instance, 'sitemap_link_collector' ) + $this->getPropertyValue( $this->instance, 'sitemap_link_collector' ), ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Abstract_Title_Builder_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Abstract_Title_Builder_Test.php index d0d870ef0f8..88a80d59467 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Abstract_Title_Builder_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Abstract_Title_Builder_Test.php @@ -41,7 +41,7 @@ protected function set_up() { $this->title_adapter = Mockery::mock( Title_Adapter::class ); $this->instance = new Title_Builder( - $this->title_adapter + $this->title_adapter, ); } } diff --git a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Constructor_Test.php b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Constructor_Test.php index d32a5dbeb76..66645cae8d2 100644 --- a/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Application/Markdown_Builders/Title_Builder/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Title_Builder_Test { public function test_constructor() { $this->assertInstanceOf( Title_Adapter::class, - $this->getPropertyValue( $this->instance, 'title_adapter' ) + $this->getPropertyValue( $this->instance, 'title_adapter' ), ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Abstract_Content_Types_Collector_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Abstract_Content_Types_Collector_Test.php index 7c4995fc178..d5d523339ac 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Abstract_Content_Types_Collector_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Abstract_Content_Types_Collector_Test.php @@ -77,7 +77,7 @@ protected function set_up() { $this->instance = new Content_Types_Collector( $this->post_type_helper, $this->post_collection_factory, - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Constructor_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Constructor_Test.php index bdf3caa77b8..a5032f45b0f 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Content_Types_Collector/Constructor_Test.php @@ -25,15 +25,15 @@ final class Constructor_Test extends Abstract_Content_Types_Collector_Test { public function test_constructor() { $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); $this->assertInstanceOf( Post_Collection_Factory::class, - $this->getPropertyValue( $this->instance, 'collection_factory' ) + $this->getPropertyValue( $this->instance, 'collection_factory' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Abstract_Description_Adapter_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Abstract_Description_Adapter_Test.php index e220ee215e7..3b171d0595e 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Abstract_Description_Adapter_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Abstract_Description_Adapter_Test.php @@ -41,7 +41,7 @@ protected function set_up() { $this->meta = Mockery::mock( Meta_Surface::class ); $this->instance = new Description_Adapter( - $this->meta + $this->meta, ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Constructor_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Constructor_Test.php index a13378a0907..7dd78cfabc8 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Description_Adapter/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Description_Adapter_Test { public function test_constructor() { $this->assertInstanceOf( Meta_Surface::class, - $this->getPropertyValue( $this->instance, 'meta' ) + $this->getPropertyValue( $this->instance, 'meta' ), ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Abstract_Terms_Collector_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Abstract_Terms_Collector_Test.php index 9237114b62a..124c1deedfe 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Abstract_Terms_Collector_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Abstract_Terms_Collector_Test.php @@ -41,7 +41,7 @@ protected function set_up() { $this->taxonomy_helper = Mockery::mock( Taxonomy_Helper::class ); $this->instance = new Terms_Collector( - $this->taxonomy_helper + $this->taxonomy_helper, ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Constructor_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Constructor_Test.php index 809295b5fcf..a85e73a728c 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Terms_Collector/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Terms_Collector_Test { public function test_constructor() { $this->assertInstanceOf( Taxonomy_Helper::class, - $this->getPropertyValue( $this->instance, 'taxonomy_helper' ) + $this->getPropertyValue( $this->instance, 'taxonomy_helper' ), ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Abstract_Title_Adapter_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Abstract_Title_Adapter_Test.php index 762be8fb8a1..0961221be78 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Abstract_Title_Adapter_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Abstract_Title_Adapter_Test.php @@ -41,7 +41,7 @@ protected function set_up() { $this->default_tagline_runner = Mockery::mock( Default_Tagline_Runner::class ); $this->instance = new Title_Adapter( - $this->default_tagline_runner + $this->default_tagline_runner, ); } } diff --git a/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Constructor_Test.php b/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Constructor_Test.php index 55418b056a7..ae304e2caa3 100644 --- a/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/Infrastructure/Title_Adapter/Constructor_Test.php @@ -23,7 +23,7 @@ final class Constructor_Test extends Abstract_Title_Adapter_Test { public function test_constructor() { $this->assertInstanceOf( Default_Tagline_Runner::class, - $this->getPropertyValue( $this->instance, 'default_tagline_runner' ) + $this->getPropertyValue( $this->instance, 'default_tagline_runner' ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Abstract_Available_Posts_Route_Test.php b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Abstract_Available_Posts_Route_Test.php index e3a5b9b864e..17b61b2445e 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Abstract_Available_Posts_Route_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Abstract_Available_Posts_Route_Test.php @@ -52,7 +52,7 @@ protected function set_up() { $this->instance = new Available_Posts_Route( $this->available_posts_repository, - $this->capability_helper + $this->capability_helper, ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Constructor_Test.php b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Constructor_Test.php index d0ed1fb0cd2..ac5358f88b8 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Constructor_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Constructor_Test.php @@ -25,12 +25,12 @@ final class Available_Posts_Route_Constructor_Test extends Abstract_Available_Po public function test_construct() { $this->assertInstanceOf( Available_Posts_Repository::class, - $this->getPropertyValue( $this->instance, 'available_posts_repository' ) + $this->getPropertyValue( $this->instance, 'available_posts_repository' ), ); $this->assertInstanceOf( Capability_Helper::class, - $this->getPropertyValue( $this->instance, 'capability_helper' ) + $this->getPropertyValue( $this->instance, 'capability_helper' ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Get_Posts_Test.php b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Get_Posts_Test.php index 580b6e81b04..22588237aaa 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Get_Posts_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Get_Posts_Test.php @@ -87,15 +87,15 @@ static function ( $request_parameters ) use ( $post_type, $search ) { return $request_parameters instanceof Parameters && $request_parameters->get_post_type() === $post_type && $request_parameters->get_search_filter() === $search; - } - ) + }, + ), ) ->times( $available_posts_times ) ->andReturn( $data_container_mock ); $this->assertInstanceOf( 'WP_REST_Response', - $this->instance->get_available_posts( $wp_rest_request ) + $this->instance->get_available_posts( $wp_rest_request ), ); } diff --git a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Register_Routes_Test.php b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Register_Routes_Test.php index 170ee7291be..dfa0c7071a1 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Register_Routes_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Available_Posts/Available_Posts_Route_Register_Routes_Test.php @@ -45,7 +45,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Abstract_Cleanup_Llms_Txt_On_Deactivation_Test.php b/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Abstract_Cleanup_Llms_Txt_On_Deactivation_Test.php index c5a9e835f2f..e69c4dd2226 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Abstract_Cleanup_Llms_Txt_On_Deactivation_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Abstract_Cleanup_Llms_Txt_On_Deactivation_Test.php @@ -53,7 +53,7 @@ protected function setUp(): void { $this->instance = new Cleanup_Llms_Txt_On_Deactivation( $this->command_handler, - $this->cron_scheduler + $this->cron_scheduler, ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Constructor_Test.php b/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Constructor_Test.php index 3dcab5b0a2d..f7dafc8339e 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Constructor_Test.php @@ -24,11 +24,11 @@ final class Constructor_Test extends Abstract_Cleanup_Llms_Txt_On_Deactivation_T public function test_constructor() { $this->assertInstanceOf( Remove_File_Command_Handler::class, - $this->getPropertyValue( $this->instance, 'command_handler' ) + $this->getPropertyValue( $this->instance, 'command_handler' ), ); $this->assertInstanceOf( Llms_Txt_Cron_Scheduler::class, - $this->getPropertyValue( $this->instance, 'cron_scheduler' ) + $this->getPropertyValue( $this->instance, 'cron_scheduler' ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Register_Hooks_Test.php b/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Register_Hooks_Test.php index 0e4bc628c11..274eab90d3e 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Register_Hooks_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Cleanup_Llms_Txt_On_Deactivation/Register_Hooks_Test.php @@ -25,8 +25,8 @@ public function test_register_hooks() { 10, \has_action( 'wpseo_deactivate', - [ $this->instance, 'maybe_remove_llms_file' ] - ) + [ $this->instance, 'maybe_remove_llms_file' ], + ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Abstract_Enable_Llms_Txt_Option_Watcher_Test.php b/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Abstract_Enable_Llms_Txt_Option_Watcher_Test.php index f805ec346b4..39b094f1d75 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Abstract_Enable_Llms_Txt_Option_Watcher_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Abstract_Enable_Llms_Txt_Option_Watcher_Test.php @@ -74,7 +74,7 @@ protected function setUp(): void { $this->cron_scheduler, $this->command_handler, $this->populate_file_command_handler, - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Constructor_Test.php b/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Constructor_Test.php index b9f855bbbe0..4552d9885b2 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Constructor_Test.php @@ -25,15 +25,15 @@ final class Constructor_Test extends Abstract_Enable_Llms_Txt_Option_Watcher_Tes public function test_constructor() { $this->assertInstanceOf( Llms_Txt_Cron_Scheduler::class, - $this->getPropertyValue( $this->instance, 'scheduler' ) + $this->getPropertyValue( $this->instance, 'scheduler' ), ); $this->assertInstanceOf( Remove_File_Command_Handler::class, - $this->getPropertyValue( $this->instance, 'remove_file_command_handler' ) + $this->getPropertyValue( $this->instance, 'remove_file_command_handler' ), ); $this->assertInstanceOf( Populate_File_Command_Handler::class, - $this->getPropertyValue( $this->instance, 'populate_file_command_handler' ) + $this->getPropertyValue( $this->instance, 'populate_file_command_handler' ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Register_Hooks_Test.php b/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Register_Hooks_Test.php index fa211be0458..1449445441f 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Register_Hooks_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Enable_Llms_Txt_Option_Watcher/Register_Hooks_Test.php @@ -25,8 +25,8 @@ public function test_register_hooks() { 10, \has_action( 'update_option_wpseo', - [ $this->instance, 'check_toggle_llms_txt' ] - ) + [ $this->instance, 'check_toggle_llms_txt' ], + ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Abstract_File_Failure_Llms_Txt_Notification_Integration_Test.php b/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Abstract_File_Failure_Llms_Txt_Notification_Integration_Test.php index 8ba13d69540..32d9c7c4418 100644 --- a/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Abstract_File_Failure_Llms_Txt_Notification_Integration_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Abstract_File_Failure_Llms_Txt_Notification_Integration_Test.php @@ -63,7 +63,7 @@ protected function set_up() { $this->instance = new File_Failure_Llms_Txt_Notification_Integration( $this->options_helper, $this->notification_center, - $this->file_failure_notification_presenter + $this->file_failure_notification_presenter, ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Constructor_Test.php b/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Constructor_Test.php index 5f5baea5ce0..4ab21bb648c 100644 --- a/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Constructor_Test.php @@ -25,15 +25,15 @@ final class Constructor_Test extends Abstract_File_Failure_Llms_Txt_Notification public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Yoast_Notification_Center::class, - $this->getPropertyValue( $this->instance, 'notification_center' ) + $this->getPropertyValue( $this->instance, 'notification_center' ), ); $this->assertInstanceOf( File_Failure_Notification_Presenter::class, - $this->getPropertyValue( $this->instance, 'presenter' ) + $this->getPropertyValue( $this->instance, 'presenter' ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Register_Hooks_Test.php b/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Register_Hooks_Test.php index 2b5635a3f1c..5c1968b807c 100644 --- a/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Register_Hooks_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/File_Failure_Llms_Txt_Notification_Integration/Register_Hooks_Test.php @@ -25,8 +25,8 @@ public function test_register_hooks() { 10, \has_action( 'admin_init', - [ $this->instance, 'maybe_show_notification' ] - ) + [ $this->instance, 'maybe_show_notification' ], + ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Abstract_Llms_Txt_Cron_Callback_Integration_Test.php b/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Abstract_Llms_Txt_Cron_Callback_Integration_Test.php index dd343b44eb5..eed21e2db7c 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Abstract_Llms_Txt_Cron_Callback_Integration_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Abstract_Llms_Txt_Cron_Callback_Integration_Test.php @@ -74,7 +74,7 @@ protected function setUp(): void { $this->options_helper, $this->cron_scheduler, $this->populate_file_command_handler, - $this->command_handler + $this->command_handler, ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Constructor_Test.php b/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Constructor_Test.php index 5f88aa9ad25..af95efc43e7 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Constructor_Test.php @@ -26,19 +26,19 @@ final class Constructor_Test extends Abstract_Llms_Txt_Cron_Callback_Integration public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Llms_Txt_Cron_Scheduler::class, - $this->getPropertyValue( $this->instance, 'scheduler' ) + $this->getPropertyValue( $this->instance, 'scheduler' ), ); $this->assertInstanceOf( Populate_File_Command_Handler::class, - $this->getPropertyValue( $this->instance, 'populate_file_command_handler' ) + $this->getPropertyValue( $this->instance, 'populate_file_command_handler' ), ); $this->assertInstanceOf( Remove_File_Command_Handler::class, - $this->getPropertyValue( $this->instance, 'remove_file_command_handler' ) + $this->getPropertyValue( $this->instance, 'remove_file_command_handler' ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Register_Hooks_Test.php b/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Register_Hooks_Test.php index 38fceef2b06..b8ae6c87a48 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Register_Hooks_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Llms_Txt_Cron_Callback_Integration/Register_Hooks_Test.php @@ -27,8 +27,8 @@ public function test_register_hooks() { 10, \has_action( Llms_Txt_Cron_Scheduler::LLMS_TXT_POPULATION, - [ $this->instance, 'populate_file' ] - ) + [ $this->instance, 'populate_file' ], + ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Abstract_Schedule_Population_On_Activation_Integration_Test.php b/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Abstract_Schedule_Population_On_Activation_Integration_Test.php index 71217787172..0dc01285e88 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Abstract_Schedule_Population_On_Activation_Integration_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Abstract_Schedule_Population_On_Activation_Integration_Test.php @@ -54,7 +54,7 @@ protected function setUp(): void { $this->instance = new Schedule_Population_On_Activation_Integration( $this->cron_scheduler, - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Constructor_Test.php b/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Constructor_Test.php index e959c37a21e..2de7fdd6bd4 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Constructor_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Constructor_Test.php @@ -24,11 +24,11 @@ final class Constructor_Test extends Abstract_Schedule_Population_On_Activation_ public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Llms_Txt_Cron_Scheduler::class, - $this->getPropertyValue( $this->instance, 'scheduler' ) + $this->getPropertyValue( $this->instance, 'scheduler' ), ); } } diff --git a/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Register_Hooks_Test.php b/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Register_Hooks_Test.php index 52e7c768957..a63a0c6ed60 100644 --- a/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Register_Hooks_Test.php +++ b/tests/Unit/Llms_Txt/User_Interface/Schedule_Population_On_Activation_Integration/Register_Hooks_Test.php @@ -25,8 +25,8 @@ public function test_register_hooks() { 10, \has_action( 'wpseo_activate', - [ $this->instance, 'schedule_llms_txt_population' ] - ) + [ $this->instance, 'schedule_llms_txt_population' ], + ), ); } } diff --git a/tests/Unit/Memoizers/Meta_Tags_Context_Memoizer_Test.php b/tests/Unit/Memoizers/Meta_Tags_Context_Memoizer_Test.php index f6a7448fdc5..b13d95612b2 100644 --- a/tests/Unit/Memoizers/Meta_Tags_Context_Memoizer_Test.php +++ b/tests/Unit/Memoizers/Meta_Tags_Context_Memoizer_Test.php @@ -110,7 +110,7 @@ protected function set_up() { $this->current_page, $this->indexable_repository, $this->meta_tags_context, - $this->presentation_memoizer + $this->presentation_memoizer, ); $this->meta_tags_context_mock = new Meta_Tags_Context_Mock(); @@ -127,23 +127,23 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Blocks_Helper::class, - $this->getPropertyValue( $this->instance, 'blocks' ) + $this->getPropertyValue( $this->instance, 'blocks' ), ); $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page' ) + $this->getPropertyValue( $this->instance, 'current_page' ), ); $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'repository' ) + $this->getPropertyValue( $this->instance, 'repository' ), ); $this->assertInstanceOf( Meta_Tags_Context::class, - $this->getPropertyValue( $this->instance, 'context_prototype' ) + $this->getPropertyValue( $this->instance, 'context_prototype' ), ); $this->assertInstanceOf( Presentation_Memoizer::class, - $this->getPropertyValue( $this->instance, 'presentation_memoizer' ) + $this->getPropertyValue( $this->instance, 'presentation_memoizer' ), ); } diff --git a/tests/Unit/Memoizers/Presentation_Memoizer_Test.php b/tests/Unit/Memoizers/Presentation_Memoizer_Test.php index fa0da31a1f2..f2b05ab649b 100644 --- a/tests/Unit/Memoizers/Presentation_Memoizer_Test.php +++ b/tests/Unit/Memoizers/Presentation_Memoizer_Test.php @@ -87,7 +87,7 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( ContainerInterface::class, - $this->getPropertyValue( $this->instance, 'container' ) + $this->getPropertyValue( $this->instance, 'container' ), ); } diff --git a/tests/Unit/Models/Indexable_Test.php b/tests/Unit/Models/Indexable_Test.php index 9c54c5205e3..a131f9c1492 100644 --- a/tests/Unit/Models/Indexable_Test.php +++ b/tests/Unit/Models/Indexable_Test.php @@ -59,7 +59,7 @@ public function test_save() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $this->instance->orm->expects( 'set' ) @@ -99,7 +99,7 @@ public function test_save_trailing_slash() { [ 'scheme' => 'https', 'host' => 'example.com', - ] + ], ); $this->instance->orm->expects( 'set' )->once()->with( 'permalink', $permalink_slash ); diff --git a/tests/Unit/Plans/Application/Add_Ons_Collector_Test.php b/tests/Unit/Plans/Application/Add_Ons_Collector_Test.php index 363d608b61a..0dee27b524e 100644 --- a/tests/Unit/Plans/Application/Add_Ons_Collector_Test.php +++ b/tests/Unit/Plans/Application/Add_Ons_Collector_Test.php @@ -86,7 +86,7 @@ public function test_get() { $this->premium, $this->woo, ], - $this->instance->get() + $this->instance->get(), ); } diff --git a/tests/Unit/Plans/User_Interface/Plans_Page_Integration_Test.php b/tests/Unit/Plans/User_Interface/Plans_Page_Integration_Test.php index 67646e5a229..1c214a0dbf5 100644 --- a/tests/Unit/Plans/User_Interface/Plans_Page_Integration_Test.php +++ b/tests/Unit/Plans/User_Interface/Plans_Page_Integration_Test.php @@ -111,7 +111,7 @@ protected function set_up() { 'has_license' => true, 'get_ctb_action' => 'load-nfd-ctb', 'get_ctb_id' => 'f6a84663-465f-4cb5-8ba5-f7a6d72224b2', - ] + ], ); $this->add_ons_collector = new Add_Ons_Collector( $this->addon_manager, $premium_add_on ); @@ -128,7 +128,7 @@ protected function set_up() { $this->short_link_helper, $this->admin_conditional, $this->promotion_manager, - $this->duplicate_post_manager + $this->duplicate_post_manager, ); } @@ -255,7 +255,7 @@ public function test_add_page() { [ $this->instance, 'display_page' ], ], ], - $this->instance->add_page( [ 'wpseo_tools' ] ) + $this->instance->add_page( [ 'wpseo_tools' ] ), ); } diff --git a/tests/Unit/Presentations/Indexable_Author_Archive_Presentation/Presentation_Instance_Builder.php b/tests/Unit/Presentations/Indexable_Author_Archive_Presentation/Presentation_Instance_Builder.php index 97eb4e20a30..d2fbf3186d7 100644 --- a/tests/Unit/Presentations/Indexable_Author_Archive_Presentation/Presentation_Instance_Builder.php +++ b/tests/Unit/Presentations/Indexable_Author_Archive_Presentation/Presentation_Instance_Builder.php @@ -80,7 +80,7 @@ protected function set_instance() { [ 'model' => $this->indexable, 'context' => $this->context, - ] + ], ); $this->set_instance_dependencies( $this->instance ); diff --git a/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Canonical_Test.php b/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Canonical_Test.php index 8dd19dd2e47..fa869ae2d15 100644 --- a/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Canonical_Test.php +++ b/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Canonical_Test.php @@ -68,7 +68,7 @@ public function test_without_canonical() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); Monkey\Functions\expect( 'is_date' ) @@ -115,7 +115,7 @@ public function test_with_pagination() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); Monkey\Functions\expect( 'is_date' ) @@ -162,7 +162,7 @@ public function test_without_canonical_with_dynamic_permalinks() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); $this->assertEquals( 'https://example.com/dynamic-permalink/', $this->instance->generate_canonical() ); @@ -207,7 +207,7 @@ public function test_with_pagination_with_dynamic_permalinks() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); $this->assertEquals( 'https://example.com/dynamic-permalink/2/', $this->instance->generate_canonical() ); diff --git a/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Presentation_Instance_Builder.php b/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Presentation_Instance_Builder.php index 52d1e549efd..93a4f35e55c 100644 --- a/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Presentation_Instance_Builder.php +++ b/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Presentation_Instance_Builder.php @@ -89,7 +89,7 @@ protected function set_instance() { $this->date, $this->pagination, $this->post, - ] + ], ) ->shouldAllowMockingProtectedMethods() ->makePartial(); @@ -98,7 +98,7 @@ protected function set_instance() { [ 'model' => $this->indexable, 'context' => $this->context, - ] + ], ); $this->set_instance_dependencies( $this->instance ); diff --git a/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Twitter_Image_Test.php b/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Twitter_Image_Test.php index 8274d09475f..08687f9b7c1 100644 --- a/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Twitter_Image_Test.php +++ b/tests/Unit/Presentations/Indexable_Post_Type_Presentation/Twitter_Image_Test.php @@ -67,7 +67,7 @@ public function test_generate_twitter_image() { 'twitter_image.jpg' => [ 'url' => 'twitter_image.jpg', ], - ] + ], ); $this->assertEquals( 'twitter_image.jpg', $this->instance->generate_twitter_image() ); diff --git a/tests/Unit/Presentations/Indexable_Presentation/Presentation_Instance_Builder.php b/tests/Unit/Presentations/Indexable_Presentation/Presentation_Instance_Builder.php index 4840f68774c..3d1e9635e28 100644 --- a/tests/Unit/Presentations/Indexable_Presentation/Presentation_Instance_Builder.php +++ b/tests/Unit/Presentations/Indexable_Presentation/Presentation_Instance_Builder.php @@ -54,7 +54,7 @@ protected function set_instance() { [ 'model' => $this->indexable, 'context' => $this->context, - ] + ], ); $this->set_instance_dependencies( $this->instance ); diff --git a/tests/Unit/Presentations/Indexable_Presentation/Robots_Test.php b/tests/Unit/Presentations/Indexable_Presentation/Robots_Test.php index e907878d296..8f14897507b 100644 --- a/tests/Unit/Presentations/Indexable_Presentation/Robots_Test.php +++ b/tests/Unit/Presentations/Indexable_Presentation/Robots_Test.php @@ -71,7 +71,7 @@ public function test_generate_robots_with_filter_return_false() { 'index' => 'noindex', 'follow' => 'nofollow', ], - $this->instance->generate_robots() + $this->instance->generate_robots(), ); } @@ -96,7 +96,7 @@ public function test_generate_robots_with_filter_returning_duplicates() { 'index' => 'noindex', 'follow' => 'follow', ], - $this->instance->generate_robots() + $this->instance->generate_robots(), ); } @@ -121,13 +121,13 @@ public function test_generate_robots_with_array_filter() { 'max-image-preview' => 'max-image-preview:large', 'max-video-preview' => 'max-video-preview:-1', ], - $this->instance + $this->instance, ) ->andReturn( [ 'index' => 'noindex', 'follow' => 'nofollow', - ] + ], ); $this->assertEquals( @@ -135,7 +135,7 @@ public function test_generate_robots_with_array_filter() { 'index' => 'noindex', 'follow' => 'nofollow', ], - $this->instance->generate_robots() + $this->instance->generate_robots(), ); } diff --git a/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Canonical_Test.php b/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Canonical_Test.php index e10aab502e6..02d3390d3dd 100644 --- a/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Canonical_Test.php +++ b/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Canonical_Test.php @@ -68,7 +68,7 @@ public function test_without_canonical() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); Monkey\Functions\expect( 'is_date' ) @@ -116,7 +116,7 @@ public function test_with_pagination() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); Monkey\Functions\expect( 'is_date' ) @@ -163,7 +163,7 @@ public function test_without_canonical_with_dynamic_permalinks() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); $this->assertEquals( 'https://example.com/dynamic-permalink/', $this->instance->generate_canonical() ); @@ -209,7 +209,7 @@ public function test_with_pagination_with_dynamic_permalinks() { ->andReturnUsing( static function ( $val ) { return $val; - } + }, ); $this->assertEquals( 'https://example.com/dynamic-permalink/2/', $this->instance->generate_canonical() ); diff --git a/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Presentation_Instance_Builder.php b/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Presentation_Instance_Builder.php index 2dc94f35522..227830d6a7a 100644 --- a/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Presentation_Instance_Builder.php +++ b/tests/Unit/Presentations/Indexable_Static_Home_Page_Presentation/Presentation_Instance_Builder.php @@ -90,7 +90,7 @@ protected function set_instance() { $this->date, $this->pagination, $this->post, - ] + ], ) ->shouldAllowMockingProtectedMethods() ->makePartial(); @@ -99,7 +99,7 @@ protected function set_instance() { [ 'model' => $this->indexable, 'context' => $this->context, - ] + ], ); $this->set_instance_dependencies( $this->instance ); diff --git a/tests/Unit/Presentations/Indexable_Static_Posts_Page_Presentation/Presentation_Instance_Builder.php b/tests/Unit/Presentations/Indexable_Static_Posts_Page_Presentation/Presentation_Instance_Builder.php index 692e23bde9a..d7bdbda2694 100644 --- a/tests/Unit/Presentations/Indexable_Static_Posts_Page_Presentation/Presentation_Instance_Builder.php +++ b/tests/Unit/Presentations/Indexable_Static_Posts_Page_Presentation/Presentation_Instance_Builder.php @@ -78,7 +78,7 @@ protected function set_instance() { $this->post_type, $this->date, $this->pagination, - $this->post + $this->post, ); $this->instance = $instance->of( [ 'model' => $this->indexable ] ); diff --git a/tests/Unit/Presentations/Indexable_Term_Archive_Presentation/Presentation_Instance_Builder.php b/tests/Unit/Presentations/Indexable_Term_Archive_Presentation/Presentation_Instance_Builder.php index 8831ae38aea..43e7a5c1148 100644 --- a/tests/Unit/Presentations/Indexable_Term_Archive_Presentation/Presentation_Instance_Builder.php +++ b/tests/Unit/Presentations/Indexable_Term_Archive_Presentation/Presentation_Instance_Builder.php @@ -78,7 +78,7 @@ protected function set_instance() { [ $this->wp_query_wrapper, $this->taxonomy, - ] + ], ) ->makePartial() ->shouldAllowMockingProtectedMethods(); diff --git a/tests/Unit/Presentations/Presentation_Instance_Dependencies.php b/tests/Unit/Presentations/Presentation_Instance_Dependencies.php index 1ca29289745..1da5161bff2 100644 --- a/tests/Unit/Presentations/Presentation_Instance_Dependencies.php +++ b/tests/Unit/Presentations/Presentation_Instance_Dependencies.php @@ -133,7 +133,7 @@ protected function set_instance_dependencies( Indexable_Presentation $presentati $this->user, $this->indexable_helper, $this->permalink_helper, - $this->values_helper + $this->values_helper, ); $this->open_graph_image_generator = Mockery::mock( @@ -143,7 +143,7 @@ protected function set_instance_dependencies( Indexable_Presentation $presentati $this->image, $this->options, $this->url, - ] + ], ); $this->twitter_image_generator = Mockery::mock( @@ -152,7 +152,7 @@ protected function set_instance_dependencies( Indexable_Presentation $presentati $this->image, $this->url, $this->twitter, - ] + ], ); $presentation_instance->set_generators( @@ -160,7 +160,7 @@ protected function set_instance_dependencies( Indexable_Presentation $presentati new Open_Graph_Locale_Generator(), $this->open_graph_image_generator, $this->twitter_image_generator, - Mockery::mock( Breadcrumbs_Generator::class ) + Mockery::mock( Breadcrumbs_Generator::class ), ); } } diff --git a/tests/Unit/Presenters/Admin/Alert_Presenter_Test.php b/tests/Unit/Presenters/Admin/Alert_Presenter_Test.php index 8906904092d..5a7c468015c 100644 --- a/tests/Unit/Presenters/Admin/Alert_Presenter_Test.php +++ b/tests/Unit/Presenters/Admin/Alert_Presenter_Test.php @@ -44,7 +44,7 @@ public function test_construct() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $test, 'asset_manager' ) + $this->getPropertyValue( $test, 'asset_manager' ), ); } diff --git a/tests/Unit/Presenters/Admin/Help_Link_Presenter_Test.php b/tests/Unit/Presenters/Admin/Help_Link_Presenter_Test.php index 68c9eb9e902..0efad42b5c7 100644 --- a/tests/Unit/Presenters/Admin/Help_Link_Presenter_Test.php +++ b/tests/Unit/Presenters/Admin/Help_Link_Presenter_Test.php @@ -45,7 +45,7 @@ public function test_construct() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $test, 'asset_manager' ) + $this->getPropertyValue( $test, 'asset_manager' ), ); } diff --git a/tests/Unit/Presenters/Admin/Indexing_Error_Presenter_Test.php b/tests/Unit/Presenters/Admin/Indexing_Error_Presenter_Test.php index af342165d2d..7b97edf47fd 100644 --- a/tests/Unit/Presenters/Admin/Indexing_Error_Presenter_Test.php +++ b/tests/Unit/Presenters/Admin/Indexing_Error_Presenter_Test.php @@ -59,7 +59,7 @@ protected function set_up() { $this->instance = new Indexing_Error_Presenter( $this->short_link_helper, $this->product_helper, - $this->addon_manager + $this->addon_manager, ); $this->short_link_helper @@ -80,15 +80,15 @@ protected function set_up() { public function test_constructor() { self::assertInstanceOf( Short_Link_Helper::class, - self::getPropertyValue( $this->instance, 'short_link_helper' ) + self::getPropertyValue( $this->instance, 'short_link_helper' ), ); self::assertInstanceOf( Product_Helper::class, - self::getPropertyValue( $this->instance, 'product_helper' ) + self::getPropertyValue( $this->instance, 'product_helper' ), ); self::assertInstanceOf( WPSEO_Addon_Manager::class, - self::getPropertyValue( $this->instance, 'addon_manager' ) + self::getPropertyValue( $this->instance, 'addon_manager' ), ); } @@ -117,7 +117,7 @@ public function test_present_not_premium_no_valid_premium_subscription() { self::assertEquals( '

    Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please click the button again to re-start the process.

    ' . '

    Below are the technical details for the error. See this page for a more detailed explanation.

    ', - $actual + $actual, ); } @@ -147,7 +147,7 @@ public function test_present_premium_no_valid_premium_subscription() { '

    Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. ' . 'Please make sure to activate your subscription in MyYoast by completing these steps.

    ' . '

    Below are the technical details for the error. See this page for a more detailed explanation.

    ', - $actual + $actual, ); } @@ -177,7 +177,7 @@ public function test_present_premium_valid_premium_subscription() { '

    Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. ' . 'Please click the button again to re-start the process. If the problem persists, please contact support.

    ' . '

    Below are the technical details for the error. See this page for a more detailed explanation.

    ', - $actual + $actual, ); } } diff --git a/tests/Unit/Presenters/Admin/Indexing_Notification_Presenter_Test.php b/tests/Unit/Presenters/Admin/Indexing_Notification_Presenter_Test.php index 1ffcbce2e52..965b714708b 100644 --- a/tests/Unit/Presenters/Admin/Indexing_Notification_Presenter_Test.php +++ b/tests/Unit/Presenters/Admin/Indexing_Notification_Presenter_Test.php @@ -53,7 +53,7 @@ public function test_present_few_indexables() { $instance = new Indexing_Notification_Presenter( $this->short_link_helper, 50, - '' + '', ); $expected = '

    You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. We estimate this will take less than a minute.

    Start SEO data optimization'; @@ -78,7 +78,7 @@ public function test_present_some_indexables() { $instance = new Indexing_Notification_Presenter( $this->short_link_helper, 500, - '' + '', ); $expected = '

    You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. We estimate this will take a couple of minutes.

    Start SEO data optimization'; @@ -111,7 +111,7 @@ public function test_present_many_indexables() { $instance = new Indexing_Notification_Presenter( $this->short_link_helper, 4000, - 'A message to show in the notification.' + 'A message to show in the notification.', ); $expected = '

    You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. We estimate this could take a long time, due to the size of your site. As an alternative to waiting, you could:

    Start SEO data optimization'; diff --git a/tests/Unit/Presenters/Admin/Migration_Error_Presenter_Test.php b/tests/Unit/Presenters/Admin/Migration_Error_Presenter_Test.php index 5d0655c22ed..9adca471042 100644 --- a/tests/Unit/Presenters/Admin/Migration_Error_Presenter_Test.php +++ b/tests/Unit/Presenters/Admin/Migration_Error_Presenter_Test.php @@ -65,7 +65,7 @@ private function expect_shortlinker() { $container = $this->create_container_with( [ Short_Link_Helper::class => $short_link_mock, - ] + ], ); Monkey\Functions\expect( 'YoastSEO' ) diff --git a/tests/Unit/Presenters/Admin/Notice_Presenter_Test.php b/tests/Unit/Presenters/Admin/Notice_Presenter_Test.php index 46218efbd43..55683c47ade 100644 --- a/tests/Unit/Presenters/Admin/Notice_Presenter_Test.php +++ b/tests/Unit/Presenters/Admin/Notice_Presenter_Test.php @@ -46,7 +46,7 @@ public function test_construct() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $test, 'asset_manager' ) + $this->getPropertyValue( $test, 'asset_manager' ), ); } diff --git a/tests/Unit/Presenters/Breadcrumbs_Presenter_Test.php b/tests/Unit/Presenters/Breadcrumbs_Presenter_Test.php index 55851b59dda..5f73cd7e76a 100644 --- a/tests/Unit/Presenters/Breadcrumbs_Presenter_Test.php +++ b/tests/Unit/Presenters/Breadcrumbs_Presenter_Test.php @@ -132,7 +132,7 @@ public function test_present_happy_path() { $this->assertEquals( $output_with_prefix, - $this->instance->present() + $this->instance->present(), ); } @@ -264,7 +264,7 @@ public function test_present_no_breadcrumbs_prefix() { $this->assertEquals( $output_without_prefix, - $this->instance->present() + $this->instance->present(), ); } @@ -291,7 +291,7 @@ public function test_crumb_to_link_not_last_element() { $this->assertEquals( $link, - $this->instance->crumb_to_link( $breadcrumb, 0, 2 ) + $this->instance->crumb_to_link( $breadcrumb, 0, 2 ), ); } @@ -322,7 +322,7 @@ public function test_crumb_to_link_filter_applied() { $this->assertEquals( $link, - $this->instance->crumb_to_link( $breadcrumb, 0, 2 ) + $this->instance->crumb_to_link( $breadcrumb, 0, 2 ), ); } @@ -350,7 +350,7 @@ public function test_crumb_to_link_title_is_set() { $this->assertEquals( $link, - $this->instance->crumb_to_link( $breadcrumb, 0, 2 ) + $this->instance->crumb_to_link( $breadcrumb, 0, 2 ), ); } @@ -378,7 +378,7 @@ public function test_crumb_in_editor() { $_GET['context'] = 'edit'; $this->assertEquals( $link, - $this->instance->crumb_to_link( $breadcrumb, 0, 2 ) + $this->instance->crumb_to_link( $breadcrumb, 0, 2 ), ); unset( $_GET['context'] ); } @@ -413,7 +413,7 @@ public function test_crumb_to_link_last_element_bold() { $this->assertEquals( $link, - $this->instance->crumb_to_link( $breadcrumb, 1, 2 ) + $this->instance->crumb_to_link( $breadcrumb, 1, 2 ), ); } @@ -447,7 +447,7 @@ public function test_crumb_to_link_last_element_not_bold() { $this->assertEquals( $link, - $this->instance->crumb_to_link( $breadcrumb, 1, 2 ) + $this->instance->crumb_to_link( $breadcrumb, 1, 2 ), ); } @@ -481,7 +481,7 @@ public function test_crumb_to_link_add_closing_elements() { $this->assertEquals( $link, - $this->instance->crumb_to_link( $breadcrumb, 3, 4 ) + $this->instance->crumb_to_link( $breadcrumb, 3, 4 ), ); } @@ -828,7 +828,7 @@ public function test_get() { $breadcrumb_1, $breadcrumb_2, ], - $this->instance->get() + $this->instance->get(), ); } } diff --git a/tests/Unit/Presenters/Canonical_Presenter_Test.php b/tests/Unit/Presenters/Canonical_Presenter_Test.php index aa0999bc6e8..3a484132fef 100644 --- a/tests/Unit/Presenters/Canonical_Presenter_Test.php +++ b/tests/Unit/Presenters/Canonical_Presenter_Test.php @@ -50,7 +50,7 @@ public function test_present() { $this->assertEquals( '', - $presented_canonical + $presented_canonical, ); } @@ -97,7 +97,7 @@ public function test_present_with_filter() { $this->assertEquals( '', - $instance->present() + $instance->present(), ); } @@ -142,7 +142,7 @@ public function test_present_with_class() { $this->assertEquals( '', - $presented_canonical + $presented_canonical, ); } } diff --git a/tests/Unit/Presenters/Debug/Marker_Close_Presenter_Test.php b/tests/Unit/Presenters/Debug/Marker_Close_Presenter_Test.php index 14dbd11aeb8..cb28e774dbb 100644 --- a/tests/Unit/Presenters/Debug/Marker_Close_Presenter_Test.php +++ b/tests/Unit/Presenters/Debug/Marker_Close_Presenter_Test.php @@ -40,7 +40,7 @@ public function test_present() { $this->assertEquals( '', - $instance->present() + $instance->present(), ); } @@ -64,7 +64,7 @@ public function test_present_disabled_by_filter() { $this->assertEquals( '', - $instance->present() + $instance->present(), ); } diff --git a/tests/Unit/Presenters/Debug/Marker_Open_Presenter_Test.php b/tests/Unit/Presenters/Debug/Marker_Open_Presenter_Test.php index 832076cf64c..4ea0b0fcfb6 100644 --- a/tests/Unit/Presenters/Debug/Marker_Open_Presenter_Test.php +++ b/tests/Unit/Presenters/Debug/Marker_Open_Presenter_Test.php @@ -39,7 +39,7 @@ public function test_present() { $this->assertEquals( '', - $instance->present() + $instance->present(), ); } @@ -63,7 +63,7 @@ public function test_present_disabled_by_filter() { $this->assertEquals( '', - $instance->present() + $instance->present(), ); } @@ -111,7 +111,7 @@ public function test_present_premium() { $expected_version = 'v' . \WPSEO_PREMIUM_VERSION . ' (Yoast SEO v' . \WPSEO_VERSION . ')'; $this->assertEquals( '', - $instance->present() + $instance->present(), ); } } diff --git a/tests/Unit/Presenters/Meta_Description_Presenter_Test.php b/tests/Unit/Presenters/Meta_Description_Presenter_Test.php index 1a8d3f92f6b..f748b1266c8 100644 --- a/tests/Unit/Presenters/Meta_Description_Presenter_Test.php +++ b/tests/Unit/Presenters/Meta_Description_Presenter_Test.php @@ -92,7 +92,7 @@ public function test_present_and_filter_happy_path() { ->andReturnUsing( static function ( $replace_string ) { return $replace_string; - } + }, ); Monkey\Filters\expectApplied( 'wpseo_metadesc' ) @@ -128,7 +128,7 @@ public function test_present_meta_description_not_string() { ->andReturnUsing( static function ( $replace_string ) { return $replace_string; - } + }, ); $this->string @@ -162,7 +162,7 @@ public function test_present_meta_description_not_string_show_notice() { ->andReturnUsing( static function ( $replace_string ) { return $replace_string; - } + }, ); $this->string @@ -198,7 +198,7 @@ public function test_present_and_filter_with_class() { ->andReturnUsing( static function ( $replace_string ) { return $replace_string; - } + }, ); Monkey\Filters\expectApplied( 'wpseo_metadesc' ) diff --git a/tests/Unit/Presenters/Open_Graph/Description_Presenter_Test.php b/tests/Unit/Presenters/Open_Graph/Description_Presenter_Test.php index cb5291cc38f..2d3659278be 100644 --- a/tests/Unit/Presenters/Open_Graph/Description_Presenter_Test.php +++ b/tests/Unit/Presenters/Open_Graph/Description_Presenter_Test.php @@ -76,7 +76,7 @@ protected function set_up() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); $this->presentation->source = []; @@ -87,7 +87,7 @@ static function ( $str ) { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); } diff --git a/tests/Unit/Presenters/Open_Graph/Image_Presenter_Test.php b/tests/Unit/Presenters/Open_Graph/Image_Presenter_Test.php index 360bbbb7f3d..ebb867ced66 100644 --- a/tests/Unit/Presenters/Open_Graph/Image_Presenter_Test.php +++ b/tests/Unit/Presenters/Open_Graph/Image_Presenter_Test.php @@ -87,7 +87,7 @@ public function test_present_with_a_set_image() { $this->assertEquals( '' . \PHP_EOL . "\t" . '' . \PHP_EOL . "\t" . '', - $this->instance->present() + $this->instance->present(), ); } @@ -117,7 +117,7 @@ public function test_filter_wrong_image_url_returned() { 'height' => '', ], ], - $this->instance->get() + $this->instance->get(), ); } @@ -167,7 +167,7 @@ public function test_filter() { 'type' => 'png', ], ], - $this->instance->get() + $this->instance->get(), ); } @@ -224,7 +224,7 @@ public function test_present_with_a_set_image_with_class() { $this->assertEquals( '' . \PHP_EOL . "\t" . '' . \PHP_EOL . "\t" . '', - $this->instance->present() + $this->instance->present(), ); } @@ -264,7 +264,7 @@ public function test_present_with_attachment_page() { $this->assertEquals( '' . \PHP_EOL . "\t" . '' . \PHP_EOL . "\t" . '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Open_Graph/Title_Presenter_Test.php b/tests/Unit/Presenters/Open_Graph/Title_Presenter_Test.php index d8671784436..52a14cad956 100644 --- a/tests/Unit/Presenters/Open_Graph/Title_Presenter_Test.php +++ b/tests/Unit/Presenters/Open_Graph/Title_Presenter_Test.php @@ -77,7 +77,7 @@ protected function set_up() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); } @@ -96,7 +96,7 @@ public function test_present() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Functions\expect( 'is_admin_bar_showing' )->andReturn( false ); @@ -121,7 +121,7 @@ public function test_present_title_is_empty() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); $actual = $this->instance->present(); @@ -145,7 +145,7 @@ public function test_present_filter() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Filters\expectApplied( 'wpseo_opengraph_title' ) @@ -175,7 +175,7 @@ public function test_present_with_class() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Functions\expect( 'is_admin_bar_showing' )->andReturn( true ); diff --git a/tests/Unit/Presenters/Rel_Next_Presenter_Test.php b/tests/Unit/Presenters/Rel_Next_Presenter_Test.php index 62d437c32a2..2755355e41a 100644 --- a/tests/Unit/Presenters/Rel_Next_Presenter_Test.php +++ b/tests/Unit/Presenters/Rel_Next_Presenter_Test.php @@ -55,7 +55,7 @@ public function test_present_empty() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -100,7 +100,7 @@ public function test_present_with_filter() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -123,7 +123,7 @@ public function test_present_with_class() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Rel_Prev_Presenter_Test.php b/tests/Unit/Presenters/Rel_Prev_Presenter_Test.php index 34d4cc89efc..4f76fb8d1b7 100644 --- a/tests/Unit/Presenters/Rel_Prev_Presenter_Test.php +++ b/tests/Unit/Presenters/Rel_Prev_Presenter_Test.php @@ -57,7 +57,7 @@ public function test_present() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -78,7 +78,7 @@ public function test_present_empty() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -123,7 +123,7 @@ public function test_present_with_filter() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -146,7 +146,7 @@ public function test_present_with_class() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Robots_Presenter_Test.php b/tests/Unit/Presenters/Robots_Presenter_Test.php index f737ae45ed5..a0b9baf32ab 100644 --- a/tests/Unit/Presenters/Robots_Presenter_Test.php +++ b/tests/Unit/Presenters/Robots_Presenter_Test.php @@ -99,7 +99,7 @@ public function test_get() { 'index' => 'index', 'follow' => 'nofollow', ], - $this->instance->get() + $this->instance->get(), ); } } diff --git a/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php b/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php index d63a9cfa281..7d57e2d5006 100644 --- a/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php +++ b/tests/Unit/Presenters/Robots_Txt_Presenter_Test.php @@ -75,7 +75,7 @@ public function test_present( $robots_txt_user_agents, $sitemaps, $expected ) { $this->assertSame( $expected, - $this->instance->present() + $this->instance->present(), ); } diff --git a/tests/Unit/Presenters/Slack/Enhanced_Data_Presenter_Test.php b/tests/Unit/Presenters/Slack/Enhanced_Data_Presenter_Test.php index 35c2c6c3c6c..7816e0f66f6 100644 --- a/tests/Unit/Presenters/Slack/Enhanced_Data_Presenter_Test.php +++ b/tests/Unit/Presenters/Slack/Enhanced_Data_Presenter_Test.php @@ -75,7 +75,7 @@ public function test_present() { [ 'get_the_author_meta' => 'Agatha Christie', 'is_singular' => true, - ] + ], ); Functions\expect( 'is_admin_bar_showing' )->andReturn( false ); @@ -84,7 +84,7 @@ public function test_present() { . "\t\n" . "\t\n" . "\t", - $this->instance->present() + $this->instance->present(), ); } @@ -111,14 +111,14 @@ public function test_present_no_post() { [ 'get_the_author_meta' => 'Agatha Christie', 'is_singular' => true, - ] + ], ); Functions\expect( 'is_admin_bar_showing' )->andReturn( false ); $this->assertEquals( "\n" . "\t", - $this->instance->present() + $this->instance->present(), ); } @@ -145,7 +145,7 @@ public function test_present_with_class() { [ 'get_the_author_meta' => 'Agatha Christie', 'is_singular' => true, - ] + ], ); Functions\expect( 'is_admin_bar_showing' )->andReturn( true ); @@ -154,7 +154,7 @@ public function test_present_with_class() { . "\t\n" . "\t\n" . "\t", - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Title_Presenter_Test.php b/tests/Unit/Presenters/Title_Presenter_Test.php index 425291cc9e0..fa8115d9877 100644 --- a/tests/Unit/Presenters/Title_Presenter_Test.php +++ b/tests/Unit/Presenters/Title_Presenter_Test.php @@ -79,14 +79,14 @@ protected function set_up() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Functions\expect( 'wp_get_document_title' ) ->andReturnUsing( function () { return $this->instance->get_title(); - } + }, ); } @@ -105,7 +105,7 @@ public function test_present() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); $expected = 'example_title'; @@ -129,7 +129,7 @@ public function test_present_title_is_empty() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); $actual = $this->instance->present(); @@ -153,7 +153,7 @@ public function test_present_filter() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Filters\expectApplied( 'wpseo_title' ) diff --git a/tests/Unit/Presenters/Twitter/Card_Presenter_Test.php b/tests/Unit/Presenters/Twitter/Card_Presenter_Test.php index 1bfe299c582..f7b36028f5f 100644 --- a/tests/Unit/Presenters/Twitter/Card_Presenter_Test.php +++ b/tests/Unit/Presenters/Twitter/Card_Presenter_Test.php @@ -55,7 +55,7 @@ public function test_present() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -92,7 +92,7 @@ public function test_present_with_class() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Twitter/Creator_Presenter_Test.php b/tests/Unit/Presenters/Twitter/Creator_Presenter_Test.php index 1cd78a2f709..3021e9c056f 100644 --- a/tests/Unit/Presenters/Twitter/Creator_Presenter_Test.php +++ b/tests/Unit/Presenters/Twitter/Creator_Presenter_Test.php @@ -62,7 +62,7 @@ public function test_present() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -108,7 +108,7 @@ public function test_present_with_class() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Twitter/Description_Presenter_Test.php b/tests/Unit/Presenters/Twitter/Description_Presenter_Test.php index 17d998db55d..f033766495d 100644 --- a/tests/Unit/Presenters/Twitter/Description_Presenter_Test.php +++ b/tests/Unit/Presenters/Twitter/Description_Presenter_Test.php @@ -71,7 +71,7 @@ public function test_present() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -117,7 +117,7 @@ public function test_present_with_class() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Twitter/Site_Presenter_Test.php b/tests/Unit/Presenters/Twitter/Site_Presenter_Test.php index 221fe1350d7..ecb8d8bc569 100644 --- a/tests/Unit/Presenters/Twitter/Site_Presenter_Test.php +++ b/tests/Unit/Presenters/Twitter/Site_Presenter_Test.php @@ -80,7 +80,7 @@ public function test_present_with_filter() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -99,7 +99,7 @@ public function test_present_with_get_twitter_id_fixing_url_as_input() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } @@ -170,7 +170,7 @@ public function test_present_with_class() { $this->assertEquals( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Twitter/Title_Presenter_Test.php b/tests/Unit/Presenters/Twitter/Title_Presenter_Test.php index 82ff05a5946..7ca5f7acf1c 100644 --- a/tests/Unit/Presenters/Twitter/Title_Presenter_Test.php +++ b/tests/Unit/Presenters/Twitter/Title_Presenter_Test.php @@ -74,7 +74,7 @@ public function test_present() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Functions\expect( 'is_admin_bar_showing' )->andReturn( false ); @@ -98,7 +98,7 @@ public function test_present_twitter_title_is_empty() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); $actual = $this->instance->present(); @@ -121,7 +121,7 @@ public function test_present_filter() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Filters\expectApplied( 'wpseo_twitter_title' ) @@ -151,7 +151,7 @@ public function test_present_with_class() { ->andReturnUsing( static function ( $str ) { return $str; - } + }, ); Monkey\Functions\expect( 'is_admin_bar_showing' )->andReturn( true ); diff --git a/tests/Unit/Presenters/Webmaster/Baidu_Presenter_Test.php b/tests/Unit/Presenters/Webmaster/Baidu_Presenter_Test.php index e752d31a87d..168e08934b4 100644 --- a/tests/Unit/Presenters/Webmaster/Baidu_Presenter_Test.php +++ b/tests/Unit/Presenters/Webmaster/Baidu_Presenter_Test.php @@ -73,7 +73,7 @@ public function test_present() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -90,7 +90,7 @@ public function test_empty_presentation() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -106,7 +106,7 @@ public function test_get() { $this->assertSame( 'baidu', - $this->instance->get() + $this->instance->get(), ); } @@ -122,7 +122,7 @@ public function test_get_empty() { $this->assertSame( '', - $this->instance->get() + $this->instance->get(), ); } @@ -141,7 +141,7 @@ public function test_present_with_class() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Webmaster/Bing_Presenter_Test.php b/tests/Unit/Presenters/Webmaster/Bing_Presenter_Test.php index 86060c1d76e..853b28b9b6f 100644 --- a/tests/Unit/Presenters/Webmaster/Bing_Presenter_Test.php +++ b/tests/Unit/Presenters/Webmaster/Bing_Presenter_Test.php @@ -73,7 +73,7 @@ public function test_present() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -90,7 +90,7 @@ public function test_empty_present() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -106,7 +106,7 @@ public function test_get() { $this->assertSame( 'bing-ver', - $this->instance->get() + $this->instance->get(), ); } @@ -125,7 +125,7 @@ public function test_present_with_class() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Webmaster/Google_Presenter_Test.php b/tests/Unit/Presenters/Webmaster/Google_Presenter_Test.php index ce551d313ba..c8648be9ea6 100644 --- a/tests/Unit/Presenters/Webmaster/Google_Presenter_Test.php +++ b/tests/Unit/Presenters/Webmaster/Google_Presenter_Test.php @@ -73,7 +73,7 @@ public function test_present() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -90,7 +90,7 @@ public function test_present_empty() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -106,7 +106,7 @@ public function test_get() { $this->assertSame( 'google-ver', - $this->instance->get() + $this->instance->get(), ); } @@ -125,7 +125,7 @@ public function test_present_with_class() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Webmaster/Pinterest_Presenter_Test.php b/tests/Unit/Presenters/Webmaster/Pinterest_Presenter_Test.php index 131e51396e9..f88a0dbbc15 100644 --- a/tests/Unit/Presenters/Webmaster/Pinterest_Presenter_Test.php +++ b/tests/Unit/Presenters/Webmaster/Pinterest_Presenter_Test.php @@ -73,7 +73,7 @@ public function test_present() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -90,7 +90,7 @@ public function test_present_empty() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -106,7 +106,7 @@ public function test_get() { $this->assertSame( 'pinterest-ver', - $this->instance->get() + $this->instance->get(), ); } @@ -125,7 +125,7 @@ public function test_present_with_class() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Presenters/Webmaster/Yandex_Presenter_Test.php b/tests/Unit/Presenters/Webmaster/Yandex_Presenter_Test.php index 7fa1cac1838..6f41bba01c8 100644 --- a/tests/Unit/Presenters/Webmaster/Yandex_Presenter_Test.php +++ b/tests/Unit/Presenters/Webmaster/Yandex_Presenter_Test.php @@ -73,7 +73,7 @@ public function test_present() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -90,7 +90,7 @@ public function test_empty_output() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } @@ -106,7 +106,7 @@ public function test_get() { $this->assertSame( 'yandex-ver', - $this->instance->get() + $this->instance->get(), ); } @@ -125,7 +125,7 @@ public function test_present_with_class() { $this->assertSame( '', - $this->instance->present() + $this->instance->present(), ); } } diff --git a/tests/Unit/Promotions/Application/Fake_Expired_Promotion.php b/tests/Unit/Promotions/Application/Fake_Expired_Promotion.php index e6b66d5d6a0..d7f640a82b4 100644 --- a/tests/Unit/Promotions/Application/Fake_Expired_Promotion.php +++ b/tests/Unit/Promotions/Application/Fake_Expired_Promotion.php @@ -17,7 +17,7 @@ final class Fake_Expired_Promotion extends Abstract_Promotion implements Promoti public function __construct() { parent::__construct( 'fake_expired_promotion', - new Time_Interval( \gmmktime( 00, 00, 00, 01, 01, 1980 ), \gmmktime( 00, 00, 00, 12, 31, 1980 ) ) + new Time_Interval( \gmmktime( 00, 00, 00, 01, 01, 1980 ), \gmmktime( 00, 00, 00, 12, 31, 1980 ) ), ); } } diff --git a/tests/Unit/Promotions/Application/Fake_Promotion.php b/tests/Unit/Promotions/Application/Fake_Promotion.php index 0594dc4eef6..7e12c365805 100644 --- a/tests/Unit/Promotions/Application/Fake_Promotion.php +++ b/tests/Unit/Promotions/Application/Fake_Promotion.php @@ -17,7 +17,7 @@ final class Fake_Promotion extends Abstract_Promotion implements Promotion_Inter public function __construct() { parent::__construct( 'fake_promotion', - new Time_Interval( ( \time() - 10000 ), ( \time() + 10000 ) ) + new Time_Interval( ( \time() - 10_000 ), ( \time() + 10_000 ) ), ); } } diff --git a/tests/Unit/Repositories/Indexable_Cleanup_Repository_Test.php b/tests/Unit/Repositories/Indexable_Cleanup_Repository_Test.php index bf7a00d742e..a9ad160f523 100644 --- a/tests/Unit/Repositories/Indexable_Cleanup_Repository_Test.php +++ b/tests/Unit/Repositories/Indexable_Cleanup_Repository_Test.php @@ -84,7 +84,7 @@ protected function set_up() { $this->taxonomy, $this->post_type, $this->author_archive, - ] + ], )->makePartial(); global $wpdb; @@ -111,7 +111,7 @@ public function test_clean_indexables_with_object_type_and_object_sub_type_mocks 'DELETE FROM wp_yoast_indexable WHERE object_type = %s AND object_sub_type = %s ORDER BY id LIMIT %d', 'post', 'shop_order', - $this->limit + $this->limit, ) ->andReturn( 'prepared_shop_order_delete_query' ); @@ -135,7 +135,7 @@ public function test_clean_indexables_with_post_status_mocks() { ->with( 'DELETE FROM wp_yoast_indexable WHERE object_type = \'post\' AND post_status = %s ORDER BY id LIMIT %d', 'auto-draft', - $this->limit + $this->limit, ) ->andReturn( 'prepared_auto_draft_delete_query' ); @@ -172,7 +172,7 @@ public function test_cleanup_orphaned_from_table( $return_value, $model_name, $c WHERE indexable_table.id IS NULL AND table_to_clean.{$column} IS NOT NULL LIMIT %d", - $this->limit + $this->limit, ) ->andReturn( 'prepared_indexable_hierarchy_select_query' ); @@ -215,7 +215,7 @@ public function test_clean_indexables_for_non_publicly_viewable_post() { 'my_cpt', 'post', 'attachment', - ] + ], ); $this->wpdb->shouldReceive( 'prepare' ) ->once() @@ -225,7 +225,7 @@ public function test_clean_indexables_for_non_publicly_viewable_post() { AND object_sub_type IS NOT NULL AND object_sub_type NOT IN ( %s, %s, %s ) LIMIT %d', - [ 'my_cpt', 'post', 'attachment', $this->limit ] + [ 'my_cpt', 'post', 'attachment', $this->limit ], ) ->andReturn( 'prepared_clean_query' ); @@ -249,7 +249,7 @@ public function test_clean_indexables_for_non_publicly_viewable_taxonomies() { 'category', 'post_tag', 'my_custom_tax', - ] + ], ); $this->wpdb->shouldReceive( 'prepare' ) @@ -260,7 +260,7 @@ public function test_clean_indexables_for_non_publicly_viewable_taxonomies() { AND object_sub_type IS NOT NULL AND object_sub_type NOT IN ( %s, %s, %s ) LIMIT %d', - [ 'category', 'post_tag', 'my_custom_tax', $this->limit ] + [ 'category', 'post_tag', 'my_custom_tax', $this->limit ], ) ->andReturn( 'prepared_clean_query' ); @@ -298,7 +298,7 @@ public function test_clean_indexables_for_non_publicly_viewable_post_type_archiv AND object_sub_type IS NOT NULL AND object_sub_type NOT IN ( %s, %s, %s ) LIMIT %d', - [ 'my_cpt', 'post', 'attachment', $this->limit ] + [ 'my_cpt', 'post', 'attachment', $this->limit ], ) ->andReturn( 'prepared_clean_query' ); @@ -345,7 +345,7 @@ public function test_clean_indexables_for_authors_without_archive() { Monkey\Functions\expect( 'is_post_status_viewable' )->twice()->andReturnUsing( static function ( $value ) { return $value === 'publish'; - } + }, ); $this->wpdb->posts = 'wp_posts'; @@ -360,7 +360,7 @@ static function ( $value ) { WHERE post_type IN ( %s ) AND post_status IN ( %s ) ) LIMIT %d', - [ 'post', 'publish', $this->limit ] + [ 'post', 'publish', $this->limit ], ) ->andReturn( 'prepared_clean_query' ); @@ -395,7 +395,7 @@ public function test_update_indexables_author_to_reassigned() { GROUP BY wp_yoast_indexable.author_id, wp_posts.post_author ORDER BY wp_yoast_indexable.author_id LIMIT %d", - $this->limit + $this->limit, ) ->andReturn( 'prepared_select_query' ); @@ -417,7 +417,7 @@ public function test_update_indexables_author_to_reassigned() { WHERE wp_yoast_indexable.author_id = 1 AND object_type=\'post\' LIMIT %d', - $this->limit + $this->limit, ) ->andReturn( 'prepared_update_query' ); @@ -454,7 +454,7 @@ public function test_clean_indexables_for_object_type_and_source_table( $return_ AND indexable_table.object_id IS NOT NULL AND indexable_table.object_type = '{$object_type}' LIMIT %d", - $this->limit + $this->limit, ) ->andReturn( 'prepared_clean_query' ); @@ -498,7 +498,7 @@ public function test_clean_indexables_for_orphaned_users() { AND indexable_table.object_id IS NOT NULL AND indexable_table.object_type = 'user' LIMIT %d", - $this->limit + $this->limit, ) ->andReturn( 'prepared_clean_query' ); diff --git a/tests/Unit/Repositories/Indexable_Hierarchy_Repository_Test.php b/tests/Unit/Repositories/Indexable_Hierarchy_Repository_Test.php index 3a06e429cbc..7ee355fe356 100644 --- a/tests/Unit/Repositories/Indexable_Hierarchy_Repository_Test.php +++ b/tests/Unit/Repositories/Indexable_Hierarchy_Repository_Test.php @@ -67,7 +67,7 @@ public function test_set_builder() { $this->assertInstanceOf( Indexable_Hierarchy_Builder::class, - $this->getPropertyValue( $this->instance, 'builder' ) + $this->getPropertyValue( $this->instance, 'builder' ), ); } @@ -83,7 +83,7 @@ public function test_set_helper() { $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); } @@ -253,7 +253,7 @@ public function test_add_ancestor() { 'ancestor_id' => 2, 'depth' => 1, 'blog_id' => 1, - ] + ], ) ->andReturn( $hierarchy ); $this->instance->expects( 'query' )->andReturn( $orm_object ); @@ -324,7 +324,7 @@ public function test_find_children() { [ 0 => 2, 1 => 3, - ] + ], ); $this->assertSame( [ 2, 3 ], $this->instance->find_children( $indexable ) ); diff --git a/tests/Unit/Repositories/Indexable_Repository_Test.php b/tests/Unit/Repositories/Indexable_Repository_Test.php index 1c3ffc23a07..59af504c758 100644 --- a/tests/Unit/Repositories/Indexable_Repository_Test.php +++ b/tests/Unit/Repositories/Indexable_Repository_Test.php @@ -97,7 +97,7 @@ protected function set_up() { $this->hierarchy_repository, $this->wpdb, $this->version_manager, - ] + ], )->makePartial(); } @@ -394,7 +394,7 @@ public function test_reset_permalink() { 'permalink' => null, 'permalink_hash' => null, 'version' => 0, - ] + ], ) ->once() ->andReturnSelf(); @@ -428,7 +428,7 @@ public function test_reset_permalink_with_args() { 'permalink' => null, 'permalink_hash' => null, 'version' => 0, - ] + ], ) ->once() ->andReturnSelf(); @@ -472,7 +472,7 @@ public function test_reset_permalink_with_invalid_args() { 'permalink' => null, 'permalink_hash' => null, 'version' => 0, - ] + ], ) ->once() ->andReturnSelf(); diff --git a/tests/Unit/Routes/Alert_Dismissal_Route_Test.php b/tests/Unit/Routes/Alert_Dismissal_Route_Test.php index 61c707425d5..25e9014e94b 100644 --- a/tests/Unit/Routes/Alert_Dismissal_Route_Test.php +++ b/tests/Unit/Routes/Alert_Dismissal_Route_Test.php @@ -57,7 +57,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Alert_Dismissal_Action::class, - $this->getPropertyValue( $this->instance, 'alert_dismissal_action' ) + $this->getPropertyValue( $this->instance, 'alert_dismissal_action' ), ); } @@ -71,7 +71,7 @@ public function test_construct() { public function test_get_conditionals() { $this->assertEquals( [], - Alert_Dismissal_Route::get_conditionals() + Alert_Dismissal_Route::get_conditionals(), ); } @@ -97,7 +97,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ) ->once(); diff --git a/tests/Unit/Routes/First_Time_Configuration_Route_Test.php b/tests/Unit/Routes/First_Time_Configuration_Route_Test.php index 77d452ebb4e..db8ef9c90bf 100644 --- a/tests/Unit/Routes/First_Time_Configuration_Route_Test.php +++ b/tests/Unit/Routes/First_Time_Configuration_Route_Test.php @@ -55,7 +55,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( First_Time_Configuration_Action::class, - $this->getPropertyValue( $this->instance, 'first_time_configuration_action' ) + $this->getPropertyValue( $this->instance, 'first_time_configuration_action' ), ); } @@ -106,7 +106,7 @@ public function test_register_routes() { 'type' => 'string', ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -128,7 +128,7 @@ public function test_register_routes() { 'type' => 'array', ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -144,7 +144,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -161,7 +161,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -178,7 +178,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -191,7 +191,7 @@ public function test_register_routes() { 'callback' => [ $this->instance, 'get_configuration_state' ], 'permission_callback' => [ $this->instance, 'can_manage_options' ], ], - ] + ], ); $this->instance->register_routes(); @@ -239,7 +239,7 @@ public function test_can_edit_user( $can_edit, $expected ) { $this->assertEquals( $expected, - $this->instance->can_edit_user( $request ) + $this->instance->can_edit_user( $request ), ); } diff --git a/tests/Unit/Routes/Importing_Route_Test.php b/tests/Unit/Routes/Importing_Route_Test.php index ebb9e703da2..934721a63e7 100644 --- a/tests/Unit/Routes/Importing_Route_Test.php +++ b/tests/Unit/Routes/Importing_Route_Test.php @@ -60,7 +60,7 @@ protected function set_up() { $this->instance = new Importing_Route( $this->importable_detector, - ...$this->importers + ...$this->importers, ); } @@ -99,7 +99,7 @@ public function test_register_routes() { 'methods' => [ 'POST' ], 'callback' => [ $this->instance, 'execute' ], 'permission_callback' => [ $this->instance, 'is_user_permitted_to_import' ], - ] + ], ); $this->instance->register_routes(); @@ -142,7 +142,7 @@ public function test_execute_import_aioseo_posts( $plugin, $type, $is_enabled, $ [ 'plugin' => $plugin, 'type' => $type, - ] + ], ); $this->assertInstanceOf( $expected_response, $wp_rest_response ); @@ -205,7 +205,7 @@ public function test_execute_non_existent_route() { [ 'plugin' => 'non', 'type' => 'existent', - ] + ], ); $this->assertInstanceOf( WP_Error::class, $response ); diff --git a/tests/Unit/Routes/Indexables_Head_Route_Test.php b/tests/Unit/Routes/Indexables_Head_Route_Test.php index 49d0568b169..1efb074bdec 100644 --- a/tests/Unit/Routes/Indexables_Head_Route_Test.php +++ b/tests/Unit/Routes/Indexables_Head_Route_Test.php @@ -66,7 +66,7 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Indexable_Head_Action::class, - $this->getPropertyValue( $this->instance, 'head_action' ) + $this->getPropertyValue( $this->instance, 'head_action' ), ); } @@ -82,7 +82,7 @@ public function test_get_conditionals() { [ Headless_Rest_Endpoints_Enabled_Conditional::class, ], - Indexables_Head_Route::get_conditionals() + Indexables_Head_Route::get_conditionals(), ); } @@ -108,7 +108,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Routes/Indexing_Route_Test.php b/tests/Unit/Routes/Indexing_Route_Test.php index a078519f3f1..dae2735479d 100644 --- a/tests/Unit/Routes/Indexing_Route_Test.php +++ b/tests/Unit/Routes/Indexing_Route_Test.php @@ -149,7 +149,7 @@ protected function set_up() { $this->post_link_indexing_action, $this->term_link_indexing_action, $this->options_helper, - $this->indexing_helper + $this->indexing_helper, ); } @@ -163,47 +163,47 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Indexable_Post_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'post_indexation_action' ) + $this->getPropertyValue( $this->instance, 'post_indexation_action' ), ); $this->assertInstanceOf( Indexable_Term_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'term_indexation_action' ) + $this->getPropertyValue( $this->instance, 'term_indexation_action' ), ); $this->assertInstanceOf( Indexable_Post_Type_Archive_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'post_type_archive_indexation_action' ) + $this->getPropertyValue( $this->instance, 'post_type_archive_indexation_action' ), ); $this->assertInstanceOf( Indexable_General_Indexation_Action::class, - $this->getPropertyValue( $this->instance, 'general_indexation_action' ) + $this->getPropertyValue( $this->instance, 'general_indexation_action' ), ); $this->assertInstanceOf( Indexable_Indexing_Complete_Action::class, - $this->getPropertyValue( $this->instance, 'indexable_indexing_complete_action' ) + $this->getPropertyValue( $this->instance, 'indexable_indexing_complete_action' ), ); $this->assertInstanceOf( Indexing_Complete_Action::class, - $this->getPropertyValue( $this->instance, 'indexing_complete_action' ) + $this->getPropertyValue( $this->instance, 'indexing_complete_action' ), ); $this->assertInstanceOf( Indexing_Prepare_Action::class, - $this->getPropertyValue( $this->instance, 'prepare_indexing_action' ) + $this->getPropertyValue( $this->instance, 'prepare_indexing_action' ), ); $this->assertInstanceOf( Post_Link_Indexing_Action::class, - $this->getPropertyValue( $this->instance, 'post_link_indexing_action' ) + $this->getPropertyValue( $this->instance, 'post_link_indexing_action' ), ); $this->assertInstanceOf( Term_Link_Indexing_Action::class, - $this->getPropertyValue( $this->instance, 'term_link_indexing_action' ) + $this->getPropertyValue( $this->instance, 'term_link_indexing_action' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Indexing_Helper::class, - $this->getPropertyValue( $this->instance, 'indexing_helper' ) + $this->getPropertyValue( $this->instance, 'indexing_helper' ), ); } @@ -223,7 +223,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'prepare' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -234,7 +234,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'complete' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -245,7 +245,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'index_posts' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -256,7 +256,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'index_terms' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -267,7 +267,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'index_post_type_archives' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -278,7 +278,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'index_general' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -289,7 +289,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'indexables_complete' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -300,7 +300,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'index_post_links' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -311,7 +311,7 @@ public function test_register_routes() { 'methods' => 'POST', 'callback' => [ $this->instance, 'index_term_links' ], 'permission_callback' => [ $this->instance, 'can_index' ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Routes/SEMrush_Route_Test.php b/tests/Unit/Routes/SEMrush_Route_Test.php index 7dc08fe8721..7e3cbbbc036 100644 --- a/tests/Unit/Routes/SEMrush_Route_Test.php +++ b/tests/Unit/Routes/SEMrush_Route_Test.php @@ -75,15 +75,15 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( SEMrush_Login_Action::class, - $this->getPropertyValue( $this->instance, 'login_action' ) + $this->getPropertyValue( $this->instance, 'login_action' ), ); $this->assertInstanceOf( SEMrush_Options_Action::class, - $this->getPropertyValue( $this->instance, 'options_action' ) + $this->getPropertyValue( $this->instance, 'options_action' ), ); $this->assertInstanceOf( SEMrush_Phrases_Action::class, - $this->getPropertyValue( $this->instance, 'phrases_action' ) + $this->getPropertyValue( $this->instance, 'phrases_action' ), ); } @@ -97,7 +97,7 @@ public function test_construct() { public function test_get_conditionals() { $this->assertEquals( [ SEMrush_Enabled_Conditional::class ], - SEMrush_Route::get_conditionals() + SEMrush_Route::get_conditionals(), ); } @@ -123,7 +123,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -140,7 +140,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -160,7 +160,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Routes/Supported_Features_Route_Test.php b/tests/Unit/Routes/Supported_Features_Route_Test.php index 0deb2783d80..337abe32b1d 100644 --- a/tests/Unit/Routes/Supported_Features_Route_Test.php +++ b/tests/Unit/Routes/Supported_Features_Route_Test.php @@ -45,7 +45,7 @@ protected function set_up() { public function test_get_conditionals() { $this->assertEquals( [ Addon_Installation_Conditional::class ], - Supported_Features_Route::get_conditionals() + Supported_Features_Route::get_conditionals(), ); } @@ -65,7 +65,7 @@ public function test_register_routes() { 'methods' => 'GET', 'callback' => [ $this, 'get_supported_features' ], 'permission_callback' => '__return_true', - ] + ], ) ->once(); @@ -86,7 +86,7 @@ public function test_get_supported_features() { $expected = new WP_REST_Response( [ 'addon-installation' => 1, - ] + ], ); $this->assertInstanceOf( WP_REST_Response::class, $actual ); diff --git a/tests/Unit/Routes/Wincher_Route_Test.php b/tests/Unit/Routes/Wincher_Route_Test.php index 29ca4b96bee..7c1cf89e8b7 100644 --- a/tests/Unit/Routes/Wincher_Route_Test.php +++ b/tests/Unit/Routes/Wincher_Route_Test.php @@ -65,7 +65,7 @@ protected function set_up() { $this->instance = new Wincher_Route( $this->login_action, $this->account_action, - $this->keyphrases_action + $this->keyphrases_action, ); } @@ -79,15 +79,15 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( Wincher_Login_Action::class, - $this->getPropertyValue( $this->instance, 'login_action' ) + $this->getPropertyValue( $this->instance, 'login_action' ), ); $this->assertInstanceOf( Wincher_Account_Action::class, - $this->getPropertyValue( $this->instance, 'account_action' ) + $this->getPropertyValue( $this->instance, 'account_action' ), ); $this->assertInstanceOf( Wincher_Keyphrases_Action::class, - $this->getPropertyValue( $this->instance, 'keyphrases_action' ) + $this->getPropertyValue( $this->instance, 'keyphrases_action' ), ); } @@ -101,7 +101,7 @@ public function test_construct() { public function test_get_conditionals() { $this->assertEquals( [ Wincher_Enabled_Conditional::class ], - Wincher_Route::get_conditionals() + Wincher_Route::get_conditionals(), ); } @@ -131,7 +131,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -142,7 +142,7 @@ public function test_register_routes() { 'methods' => 'GET', 'callback' => [ $this->instance, 'get_authorization_url' ], 'permission_callback' => [ $this->instance, 'can_use_wincher' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -158,7 +158,7 @@ public function test_register_routes() { 'required' => true, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -180,7 +180,7 @@ public function test_register_routes() { 'required' => false, ], ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -191,7 +191,7 @@ public function test_register_routes() { 'methods' => 'DELETE', 'callback' => [ $this->instance, 'untrack_keyphrase' ], 'permission_callback' => [ $this->instance, 'can_use_wincher' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -202,7 +202,7 @@ public function test_register_routes() { 'methods' => 'GET', 'callback' => [ $this->instance, 'check_limit' ], 'permission_callback' => [ $this->instance, 'can_use_wincher' ], - ] + ], ); Monkey\Functions\expect( 'register_rest_route' ) @@ -213,7 +213,7 @@ public function test_register_routes() { 'methods' => 'GET', 'callback' => [ $this->instance, 'get_upgrade_campaign' ], 'permission_callback' => [ $this->instance, 'can_use_wincher' ], - ] + ], ); $this->instance->register_routes(); @@ -249,7 +249,7 @@ public function test_is_valid_code_with_valid_code_given() { * @return void */ public function test_is_valid_website_when_valid_id_is_passed() { - $this->assertTrue( $this->instance->has_valid_website_id( 12345 ) ); + $this->assertTrue( $this->instance->has_valid_website_id( 12_345 ) ); } /** @@ -358,7 +358,7 @@ public function test_track_keyphrases() { ->expects( 'track_keyphrases' ) ->with( [ 'seo' ], - $limit_response + $limit_response, ) ->andReturn( (object) [ 'status' => '200' ] ); @@ -396,7 +396,7 @@ public function test_get_tracked_keyphrases() { ->with( [ 'seo' ], 'https://example.com', - '2023-01-01' + '2023-01-01', ) ->andReturn( (object) [ 'status' => '200' ] ); @@ -434,7 +434,7 @@ public function test_get_tracked_keyphrases_without_permalink() { ->with( [ 'seo' ], '', - '2023-01-01' + '2023-01-01', ) ->andReturn( (object) [ 'status' => '200' ] ); @@ -464,7 +464,7 @@ public function test_untrack_keyphrase() { (object) [ 'results' => [], 'status' => '200', - ] + ], ); Mockery::mock( 'overload:' . WP_REST_Response::class ); diff --git a/tests/Unit/Routes/Yoast_Head_REST_Field_Test.php b/tests/Unit/Routes/Yoast_Head_REST_Field_Test.php index 4981a99a7a5..701a8e03b33 100644 --- a/tests/Unit/Routes/Yoast_Head_REST_Field_Test.php +++ b/tests/Unit/Routes/Yoast_Head_REST_Field_Test.php @@ -74,7 +74,7 @@ protected function set_up() { $this->post_type_helper, $this->taxonomy_helper, $this->post_helper, - $this->head_action + $this->head_action, ); } @@ -99,15 +99,15 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); $this->assertInstanceOf( Taxonomy_Helper::class, - $this->getPropertyValue( $this->instance, 'taxonomy_helper' ) + $this->getPropertyValue( $this->instance, 'taxonomy_helper' ), ); $this->assertInstanceOf( Indexable_Head_Action::class, - $this->getPropertyValue( $this->instance, 'head_action' ) + $this->getPropertyValue( $this->instance, 'head_action' ), ); } @@ -134,7 +134,7 @@ public function test_register_routes() { ->with( 'post_type', Yoast_Head_REST_Field::YOAST_HEAD_ATTRIBUTE_NAME, - [ 'get_callback' => [ $this->instance, 'for_post' ] ] + [ 'get_callback' => [ $this->instance, 'for_post' ] ], ); Monkey\Functions\expect( 'register_rest_field' ) @@ -142,7 +142,7 @@ public function test_register_routes() { ->with( 'taxonomy', Yoast_Head_REST_Field::YOAST_HEAD_ATTRIBUTE_NAME, - [ 'get_callback' => [ $this->instance, 'for_term' ] ] + [ 'get_callback' => [ $this->instance, 'for_term' ] ], ); Monkey\Functions\expect( 'register_rest_field' ) @@ -150,7 +150,7 @@ public function test_register_routes() { ->with( 'tag', Yoast_Head_REST_Field::YOAST_HEAD_ATTRIBUTE_NAME, - [ 'get_callback' => [ $this->instance, 'for_term' ] ] + [ 'get_callback' => [ $this->instance, 'for_term' ] ], ); Monkey\Functions\expect( 'register_rest_field' ) @@ -158,7 +158,7 @@ public function test_register_routes() { ->with( 'user', Yoast_Head_REST_Field::YOAST_HEAD_ATTRIBUTE_NAME, - [ 'get_callback' => [ $this->instance, 'for_author' ] ] + [ 'get_callback' => [ $this->instance, 'for_author' ] ], ); Monkey\Functions\expect( 'register_rest_field' ) @@ -166,7 +166,7 @@ public function test_register_routes() { ->with( 'type', Yoast_Head_REST_Field::YOAST_HEAD_ATTRIBUTE_NAME, - [ 'get_callback' => [ $this->instance, 'for_post_type_archive' ] ] + [ 'get_callback' => [ $this->instance, 'for_post_type_archive' ] ], ); $this->instance->register_routes(); @@ -264,7 +264,7 @@ public function test_adding_yoast_head_with_404( $method, $params, $input ) { (object) [ 'status' => 404, 'head' => 'this is the 404 head', - ] + ], ); if ( $method === 'for_post' ) { @@ -293,7 +293,7 @@ public function test_adding_yoast_head_to_posts_page_with_404() { (object) [ 'status' => 404, 'head' => 'this is the 404 head', - ] + ], ); $this->assertNull( $this->instance->for_post_type_archive( [ 'slug' => 'post' ] ) ); diff --git a/tests/Unit/Services/Importing/Aioseo_Social_Images_Provider_Service_Test.php b/tests/Unit/Services/Importing/Aioseo_Social_Images_Provider_Service_Test.php index f8c2ac1822f..9471d27be6e 100644 --- a/tests/Unit/Services/Importing/Aioseo_Social_Images_Provider_Service_Test.php +++ b/tests/Unit/Services/Importing/Aioseo_Social_Images_Provider_Service_Test.php @@ -161,7 +161,7 @@ public function test_get_first_attached_image( $post_type, $attachment_type_time 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', - ] + ], ) ->andReturn( $children ); diff --git a/tests/Unit/Services/Importing/Conflicting_Plugins_Service_Test.php b/tests/Unit/Services/Importing/Conflicting_Plugins_Service_Test.php index 6936f4c2cd5..7da9999dd82 100644 --- a/tests/Unit/Services/Importing/Conflicting_Plugins_Service_Test.php +++ b/tests/Unit/Services/Importing/Conflicting_Plugins_Service_Test.php @@ -70,7 +70,7 @@ public function test_detect_conflicting_plugins() { [ 'xml-sitemaps/xml-sitemaps.php', 'not-conflicting/plugin.php', - ] + ], ); // Act. @@ -98,7 +98,7 @@ public function test_detect_deactivating_conflicting_plugins() { [ 'xml-sitemaps/xml-sitemaps.php', 'not-conflicting/plugin.php', - ] + ], ); Monkey\Functions\expect( 'wp_unslash' ) ->andReturnFirstArg(); @@ -139,7 +139,7 @@ public function test_detect_deactivating_conflicting_plugins_plugin_is_int( $act [ 'xml-sitemaps/xml-sitemaps.php', 'not-conflicting/plugin.php', - ] + ], ); $_GET['action'] = $action; diff --git a/tests/Unit/Services/Importing/Importable_Detector_Service_Test.php b/tests/Unit/Services/Importing/Importable_Detector_Service_Test.php index 65686dc56b0..06f025d33af 100644 --- a/tests/Unit/Services/Importing/Importable_Detector_Service_Test.php +++ b/tests/Unit/Services/Importing/Importable_Detector_Service_Test.php @@ -206,7 +206,7 @@ protected function set_up() { $this->robots_provider, $this->robots_transformer, $this->social_images_provider, - ] + ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->cleanup_action = Mockery::mock( @@ -215,7 +215,7 @@ protected function set_up() { $this->wpdb, $this->options, $this->wpdb_helper, - ] + ], )->makePartial()->shouldAllowMockingProtectedMethods(); $this->instance = new Importable_Detector_Service( $this->importing_action, $this->cleanup_action ); @@ -224,7 +224,7 @@ protected function set_up() { [ $this->importing_action, $this->cleanup_action, - ] + ], )->makePartial()->shouldAllowMockingProtectedMethods(); } @@ -241,7 +241,7 @@ public function test_construct() { $importer = \array_values( self::getPropertyValue( $this->instance, 'importers' ) )[0]; $this->assertInstanceOf( Aioseo_Posts_Importing_Action::class, - $importer + $importer, ); } @@ -457,7 +457,7 @@ public function test_filter_actions_no_filters() { $this->assertTrue( \count( $filtered_importers_no_filters ) === 1 ); $this->assertInstanceOf( Aioseo_Posts_Importing_Action::class, - $filtered_importers_no_filters[0] + $filtered_importers_no_filters[0], ); } @@ -475,7 +475,7 @@ public function test_filter_actions_plugin_filter_only() { $this->assertTrue( \count( $filtered_importers_plugin_filters ) === 1 ); $this->assertInstanceOf( Aioseo_Posts_Importing_Action::class, - $filtered_importers_plugin_filters[0] + $filtered_importers_plugin_filters[0], ); } @@ -493,7 +493,7 @@ public function test_filter_actions_type_filter_only() { $this->assertTrue( \count( $filtered_importers_type_filters ) === 1 ); $this->assertInstanceOf( Aioseo_Posts_Importing_Action::class, - $filtered_importers_type_filters[0] + $filtered_importers_type_filters[0], ); } @@ -511,7 +511,7 @@ public function test_filter_actions_plugin_and_type_filter() { $this->assertTrue( \count( $filtered_importers_plugin_type_filters ) === 1 ); $this->assertInstanceOf( Aioseo_Posts_Importing_Action::class, - $filtered_importers_plugin_type_filters[0] + $filtered_importers_plugin_type_filters[0], ); } diff --git a/tests/Unit/Services/Indexables/Indexable_Version_Manager_Test.php b/tests/Unit/Services/Indexables/Indexable_Version_Manager_Test.php index 9312093f25b..cf0e0931d6b 100644 --- a/tests/Unit/Services/Indexables/Indexable_Version_Manager_Test.php +++ b/tests/Unit/Services/Indexables/Indexable_Version_Manager_Test.php @@ -63,7 +63,7 @@ protected function set_up() { public function test_construct() { self::assertInstanceOf( Indexable_Builder_Versions::class, - self::getPropertyValue( $this->instance, 'indexable_builder_versions' ) + self::getPropertyValue( $this->instance, 'indexable_builder_versions' ), ); } diff --git a/tests/Unit/Surfaces/Meta_Surface_Test.php b/tests/Unit/Surfaces/Meta_Surface_Test.php index e312213d523..0de689f5de2 100644 --- a/tests/Unit/Surfaces/Meta_Surface_Test.php +++ b/tests/Unit/Surfaces/Meta_Surface_Test.php @@ -103,7 +103,7 @@ protected function set_up() { $this->context_memoizer, $this->repository, $this->wp_rewrite_wrapper, - $this->indexable_helper + $this->indexable_helper, ); $this->context->presentation = (object) [ 'test' => 'succeeds' ]; @@ -517,7 +517,7 @@ static function ( $url, $component = -1 ) use ( $page_type, $is_date_archive ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- Test mock. return \parse_url( $url, $component ); } - } + }, ); $this->container->expects( 'get' ) @@ -563,7 +563,7 @@ static function ( $url, $component = -1 ) use ( $page_type, $is_date_archive ) { '([0-9]{4})/page/?([0-9]{1,})/?$' => 'index.php?year=$matches[1]&paged=$matches[2]', '([0-9]{4})/([0-9]{1,2})/?$' => 'index.php?year=$matches[1]&monthnum=$matches[2]', '([0-9]{4})/?$' => 'index.php?year=$matches[1]', - ] + ], ); $this->indexable->object_type = $object_type; @@ -616,7 +616,7 @@ public function test_for_url_with_unexpected_value( $url ) { 'wp_parse_url' => static function ( $url ) { return \parse_url( $url ); }, - ] + ], ); $this->assertFalse( $this->instance->for_url( $url ) ); diff --git a/tests/Unit/Surfaces/Values/Meta_Test.php b/tests/Unit/Surfaces/Values/Meta_Test.php index 16ec9758b83..7ec864a6119 100644 --- a/tests/Unit/Surfaces/Values/Meta_Test.php +++ b/tests/Unit/Surfaces/Values/Meta_Test.php @@ -60,12 +60,12 @@ protected function set_up() { Helpers_Surface::class => $helpers, WPSEO_Replace_Vars::class => $replace_vars, Front_End_Integration::class => $front_end, - ] + ], ); $this->instance = new Meta( $this->context, - $this->container + $this->container, ); } diff --git a/tests/Unit/Task_List/Application/Configuration/Abstract_Task_List_Configuration_Test.php b/tests/Unit/Task_List/Application/Configuration/Abstract_Task_List_Configuration_Test.php index 5330a9a2190..16b1d7d6f8f 100644 --- a/tests/Unit/Task_List/Application/Configuration/Abstract_Task_List_Configuration_Test.php +++ b/tests/Unit/Task_List/Application/Configuration/Abstract_Task_List_Configuration_Test.php @@ -50,7 +50,7 @@ protected function set_up() { $this->instance = new Task_List_Configuration( $this->options_helper, - $this->endpoints_repository + $this->endpoints_repository, ); } } diff --git a/tests/Unit/Task_List/Application/Configuration/Task_List_Configuration_Constructor_Test.php b/tests/Unit/Task_List/Application/Configuration/Task_List_Configuration_Constructor_Test.php index acbe8fb3335..de370a2b4cb 100644 --- a/tests/Unit/Task_List/Application/Configuration/Task_List_Configuration_Constructor_Test.php +++ b/tests/Unit/Task_List/Application/Configuration/Task_List_Configuration_Constructor_Test.php @@ -25,11 +25,11 @@ final class Task_List_Configuration_Constructor_Test extends Abstract_Task_List_ public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Endpoints_Repository::class, - $this->getPropertyValue( $this->instance, 'endpoints_repository' ) + $this->getPropertyValue( $this->instance, 'endpoints_repository' ), ); } } diff --git a/tests/Unit/Task_List/Application/Tasks/Complete_FTC/Complete_FTC_Constructor_Test.php b/tests/Unit/Task_List/Application/Tasks/Complete_FTC/Complete_FTC_Constructor_Test.php index 34dfb79cdf2..6a0dcdac464 100644 --- a/tests/Unit/Task_List/Application/Tasks/Complete_FTC/Complete_FTC_Constructor_Test.php +++ b/tests/Unit/Task_List/Application/Tasks/Complete_FTC/Complete_FTC_Constructor_Test.php @@ -25,7 +25,7 @@ final class Complete_FTC_Constructor_Test extends Abstract_Complete_FTC_Test { public function test_constructor() { $this->assertInstanceOf( First_Time_Configuration_Notice_Helper::class, - $this->getPropertyValue( $this->instance, 'ftc_notice_helper' ) + $this->getPropertyValue( $this->instance, 'ftc_notice_helper' ), ); } } diff --git a/tests/Unit/Task_List/Application/Tasks/Create_New_Content/Create_New_Content_Constructor_Test.php b/tests/Unit/Task_List/Application/Tasks/Create_New_Content/Create_New_Content_Constructor_Test.php index 43f0c630857..b32cf12c91d 100644 --- a/tests/Unit/Task_List/Application/Tasks/Create_New_Content/Create_New_Content_Constructor_Test.php +++ b/tests/Unit/Task_List/Application/Tasks/Create_New_Content/Create_New_Content_Constructor_Test.php @@ -25,7 +25,7 @@ final class Create_New_Content_Constructor_Test extends Abstract_Create_New_Cont public function test_constructor() { $this->assertInstanceOf( Post_Type_Helper::class, - $this->getPropertyValue( $this->instance, 'post_type_helper' ) + $this->getPropertyValue( $this->instance, 'post_type_helper' ), ); } } diff --git a/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Constructor_Test.php b/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Constructor_Test.php index eca27e09b50..a3b2bffaffc 100644 --- a/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Constructor_Test.php +++ b/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Constructor_Test.php @@ -25,7 +25,7 @@ final class Enable_Llms_Txt_Constructor_Test extends Abstract_Enable_Llms_Txt_Te public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Is_Valid_Test.php b/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Is_Valid_Test.php index f1d6ce847a2..356a28afc55 100644 --- a/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Is_Valid_Test.php +++ b/tests/Unit/Task_List/Application/Tasks/Enable_Llms_Txt/Enable_Llms_Txt_Is_Valid_Test.php @@ -26,7 +26,7 @@ public function test_is_valid_on_single_site() { Monkey\Functions\stubs( [ 'is_multisite' => false, - ] + ], ); $this->assertTrue( $this->instance->is_valid() ); @@ -41,7 +41,7 @@ public function test_is_not_valid_on_multisite() { Monkey\Functions\stubs( [ 'is_multisite' => true, - ] + ], ); $this->assertFalse( $this->instance->is_valid() ); diff --git a/tests/Unit/Task_List/Application/Tasks_Repository_Constructor_Test.php b/tests/Unit/Task_List/Application/Tasks_Repository_Constructor_Test.php index 7394c7d17a9..2e1c952b842 100644 --- a/tests/Unit/Task_List/Application/Tasks_Repository_Constructor_Test.php +++ b/tests/Unit/Task_List/Application/Tasks_Repository_Constructor_Test.php @@ -24,7 +24,7 @@ final class Tasks_Repository_Constructor_Test extends Abstract_Tasks_Repository_ public function test_constructor() { $this->assertInstanceOf( Cached_Tasks_Collector::class, - $this->getPropertyValue( $this->instance, 'tasks_collector' ) + $this->getPropertyValue( $this->instance, 'tasks_collector' ), ); } } diff --git a/tests/Unit/Task_List/Infrastructure/Register_Post_Type_Tasks_Integration_Register_Hooks_Test.php b/tests/Unit/Task_List/Infrastructure/Register_Post_Type_Tasks_Integration_Register_Hooks_Test.php index a5294526ecf..e56fdbac560 100644 --- a/tests/Unit/Task_List/Infrastructure/Register_Post_Type_Tasks_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Task_List/Infrastructure/Register_Post_Type_Tasks_Integration_Register_Hooks_Test.php @@ -27,8 +27,8 @@ public function test_register_hooks() { 10, \has_filter( 'wpseo_task_list_tasks', - [ $this->instance, 'register_post_type_tasks' ] - ) + [ $this->instance, 'register_post_type_tasks' ], + ), ); } } diff --git a/tests/Unit/Task_List/Infrastructure/Tasks_Collectors/Cached_Collector/Cached_Tasks_Collector_Constructor_Test.php b/tests/Unit/Task_List/Infrastructure/Tasks_Collectors/Cached_Collector/Cached_Tasks_Collector_Constructor_Test.php index 948292ab364..c2b466f4257 100644 --- a/tests/Unit/Task_List/Infrastructure/Tasks_Collectors/Cached_Collector/Cached_Tasks_Collector_Constructor_Test.php +++ b/tests/Unit/Task_List/Infrastructure/Tasks_Collectors/Cached_Collector/Cached_Tasks_Collector_Constructor_Test.php @@ -25,7 +25,7 @@ final class Cached_Tasks_Collector_Constructor_Test extends Abstract_Cached_Task public function test_constructor() { $this->assertInstanceOf( Tasks_Collector::class, - $this->getPropertyValue( $this->instance, 'tasks_collector' ) + $this->getPropertyValue( $this->instance, 'tasks_collector' ), ); } } diff --git a/tests/Unit/Task_List/User_Interface/Complete_Task/Abstract_Complete_Task_Route_Test.php b/tests/Unit/Task_List/User_Interface/Complete_Task/Abstract_Complete_Task_Route_Test.php index f53feb515dd..b1c71768380 100644 --- a/tests/Unit/Task_List/User_Interface/Complete_Task/Abstract_Complete_Task_Route_Test.php +++ b/tests/Unit/Task_List/User_Interface/Complete_Task/Abstract_Complete_Task_Route_Test.php @@ -62,7 +62,7 @@ protected function set_up() { $this->instance = new Complete_Task_Route( $this->tasks_collector, $this->capability_helper, - $this->action_tracker + $this->action_tracker, ); } diff --git a/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Constructor_Test.php b/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Constructor_Test.php index 88082d70ab3..11318dbe3d3 100644 --- a/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Constructor_Test.php +++ b/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Constructor_Test.php @@ -26,15 +26,15 @@ final class Complete_Task_Route_Constructor_Test extends Abstract_Complete_Task_ public function test_constructor() { $this->assertInstanceOf( Tasks_Collector::class, - $this->getPropertyValue( $this->instance, 'tasks_collector' ) + $this->getPropertyValue( $this->instance, 'tasks_collector' ), ); $this->assertInstanceOf( Capability_Helper::class, - $this->getPropertyValue( $this->instance, 'capability_helper' ) + $this->getPropertyValue( $this->instance, 'capability_helper' ), ); $this->assertInstanceOf( Action_Tracker::class, - $this->getPropertyValue( $this->instance, 'action_tracker' ) + $this->getPropertyValue( $this->instance, 'action_tracker' ), ); } } diff --git a/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Register_Routes_Test.php b/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Register_Routes_Test.php index e25b6acab2d..dab01810345 100644 --- a/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Register_Routes_Test.php +++ b/tests/Unit/Task_List/User_Interface/Complete_Task/Complete_Task_Route_Register_Routes_Test.php @@ -46,7 +46,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Task_List/User_Interface/Get_Tasks/Abstract_Get_Tasks_Route_Test.php b/tests/Unit/Task_List/User_Interface/Get_Tasks/Abstract_Get_Tasks_Route_Test.php index 9a5829ceaf4..cc7313a40a0 100644 --- a/tests/Unit/Task_List/User_Interface/Get_Tasks/Abstract_Get_Tasks_Route_Test.php +++ b/tests/Unit/Task_List/User_Interface/Get_Tasks/Abstract_Get_Tasks_Route_Test.php @@ -60,7 +60,7 @@ protected function set_up() { $this->instance = new Get_Tasks_Route( $this->tasks_repository, $this->capability_helper, - $this->action_tracker + $this->action_tracker, ); } } diff --git a/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Constructor_Test.php b/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Constructor_Test.php index c1bc8757b10..0076c948d07 100644 --- a/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Constructor_Test.php +++ b/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Constructor_Test.php @@ -26,15 +26,15 @@ final class Get_Tasks_Route_Constructor_Test extends Abstract_Get_Tasks_Route_Te public function test_constructor() { $this->assertInstanceOf( Tasks_Repository::class, - $this->getPropertyValue( $this->instance, 'tasks_repository' ) + $this->getPropertyValue( $this->instance, 'tasks_repository' ), ); $this->assertInstanceOf( Capability_Helper::class, - $this->getPropertyValue( $this->instance, 'capability_helper' ) + $this->getPropertyValue( $this->instance, 'capability_helper' ), ); $this->assertInstanceOf( Action_Tracker::class, - $this->getPropertyValue( $this->instance, 'action_tracker' ) + $this->getPropertyValue( $this->instance, 'action_tracker' ), ); } } diff --git a/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Register_Routes_Test.php b/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Register_Routes_Test.php index 2dee1f1d5d8..df98116cba9 100644 --- a/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Register_Routes_Test.php +++ b/tests/Unit/Task_List/User_Interface/Get_Tasks/Get_Tasks_Route_Register_Routes_Test.php @@ -51,7 +51,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/TestCase.php b/tests/Unit/TestCase.php index 61838e58b4a..e03d39886d9 100644 --- a/tests/Unit/TestCase.php +++ b/tests/Unit/TestCase.php @@ -37,7 +37,7 @@ protected function set_up() { [ // Null makes it so the function returns its first argument. 'is_admin' => false, - ] + ], ); Monkey\Functions\expect( 'get_option' ) @@ -87,7 +87,7 @@ protected function create_helper_surface( ContainerInterface $container ) { $container, new Open_Graph_Helpers_Surface( $container ), new Schema_Helpers_Surface( $container ), - new Twitter_Helpers_Surface( $container ) + new Twitter_Helpers_Surface( $container ), ); } diff --git a/tests/Unit/Tracking/Infrastructure/Tracking_Link_Adapter_Test.php b/tests/Unit/Tracking/Infrastructure/Tracking_Link_Adapter_Test.php index b6f4b9a4677..6703ca747df 100644 --- a/tests/Unit/Tracking/Infrastructure/Tracking_Link_Adapter_Test.php +++ b/tests/Unit/Tracking/Infrastructure/Tracking_Link_Adapter_Test.php @@ -66,7 +66,7 @@ public function test_create_tracking_link_for_tasks_valid_url() { 'wpseo_tracked_action' => 'task_first_actioned_on', 'wpseo_tracking_nonce' => $nonce_value, ], - $input_url + $input_url, ) ->once() ->andReturn( $expected_url ); diff --git a/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Abstract_Tracking_On_Page_Load_Integration_Test.php b/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Abstract_Tracking_On_Page_Load_Integration_Test.php index 340693252b9..65674ee324d 100644 --- a/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Abstract_Tracking_On_Page_Load_Integration_Test.php +++ b/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Abstract_Tracking_On_Page_Load_Integration_Test.php @@ -62,7 +62,7 @@ protected function set_up() { $this->instance = new Tracking_On_Page_Load_Integration( $this->action_tracker, $this->capability_helper, - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Constructor_Test.php b/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Constructor_Test.php index 36155201a9e..167ad196bd1 100644 --- a/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Constructor_Test.php +++ b/tests/Unit/Tracking/Infrastructure/Tracking_On_Page_Load/Constructor_Test.php @@ -24,15 +24,15 @@ final class Constructor_Test extends Abstract_Tracking_On_Page_Load_Integration_ public function test_constructor() { $this->assertInstanceOf( Action_Tracker::class, - $this->getPropertyValue( $this->instance, 'action_tracker' ) + $this->getPropertyValue( $this->instance, 'action_tracker' ), ); $this->assertInstanceOf( Capability_Helper::class, - $this->getPropertyValue( $this->instance, 'capability_helper' ) + $this->getPropertyValue( $this->instance, 'capability_helper' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Tracking/User_Interface/Action_Tracking/Abstract_Action_Tracking_Route_Test.php b/tests/Unit/Tracking/User_Interface/Action_Tracking/Abstract_Action_Tracking_Route_Test.php index dc9f9f664af..fd9d077737b 100644 --- a/tests/Unit/Tracking/User_Interface/Action_Tracking/Abstract_Action_Tracking_Route_Test.php +++ b/tests/Unit/Tracking/User_Interface/Action_Tracking/Abstract_Action_Tracking_Route_Test.php @@ -61,7 +61,7 @@ protected function set_up() { $this->instance = new Action_Tracking_Route( $this->action_tracker, $this->capability_helper, - $this->options_helper + $this->options_helper, ); } diff --git a/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Constructor_Test.php b/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Constructor_Test.php index fd89ba793be..7e65216fa09 100644 --- a/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Constructor_Test.php +++ b/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Constructor_Test.php @@ -26,15 +26,15 @@ final class Action_Tracking_Route_Constructor_Test extends Abstract_Action_Track public function test_constructor() { $this->assertInstanceOf( Action_Tracker::class, - $this->getPropertyValue( $this->instance, 'action_tracker' ) + $this->getPropertyValue( $this->instance, 'action_tracker' ), ); $this->assertInstanceOf( Capability_Helper::class, - $this->getPropertyValue( $this->instance, 'capability_helper' ) + $this->getPropertyValue( $this->instance, 'capability_helper' ), ); $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Register_Routes_Test.php b/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Register_Routes_Test.php index 8da3a04aac6..463f00033b0 100644 --- a/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Register_Routes_Test.php +++ b/tests/Unit/Tracking/User_Interface/Action_Tracking/Action_Tracking_Route_Register_Routes_Test.php @@ -40,7 +40,7 @@ public function test_register_routes() { ], ], ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/User_Meta/Application/Additional_Contactmethods_Collector_Test.php b/tests/Unit/User_Meta/Application/Additional_Contactmethods_Collector_Test.php index e635ac1cef0..401dbead15e 100644 --- a/tests/Unit/User_Meta/Application/Additional_Contactmethods_Collector_Test.php +++ b/tests/Unit/User_Meta/Application/Additional_Contactmethods_Collector_Test.php @@ -52,7 +52,7 @@ protected function set_up() { $this->instance = new Additional_Contactmethods_Collector( $this->facebook, - $this->youtube + $this->youtube, ); } diff --git a/tests/Unit/User_Meta/Application/Cleanup_Service_Test.php b/tests/Unit/User_Meta/Application/Cleanup_Service_Test.php index d0b5d935f40..0d030bb240f 100644 --- a/tests/Unit/User_Meta/Application/Cleanup_Service_Test.php +++ b/tests/Unit/User_Meta/Application/Cleanup_Service_Test.php @@ -61,7 +61,7 @@ protected function set_up() { $this->instance = new Cleanup_Service( $this->additional_contactmethods_collector, $this->custom_meta_collector, - $this->cleanup_repository + $this->cleanup_repository, ); } @@ -75,15 +75,15 @@ protected function set_up() { public function test_constructor() { $this->assertInstanceOf( Additional_Contactmethods_Collector::class, - $this->getPropertyValue( $this->instance, 'additional_contactmethods_collector' ) + $this->getPropertyValue( $this->instance, 'additional_contactmethods_collector' ), ); $this->assertInstanceOf( Custom_Meta_Collector::class, - $this->getPropertyValue( $this->instance, 'custom_meta_collector' ) + $this->getPropertyValue( $this->instance, 'custom_meta_collector' ), ); $this->assertInstanceOf( Cleanup_Repository::class, - $this->getPropertyValue( $this->instance, 'cleanup_repository' ) + $this->getPropertyValue( $this->instance, 'cleanup_repository' ), ); } diff --git a/tests/Unit/User_Meta/Application/Custom_Meta_Collector_Test.php b/tests/Unit/User_Meta/Application/Custom_Meta_Collector_Test.php index 9b19b07733c..ceab48402ce 100644 --- a/tests/Unit/User_Meta/Application/Custom_Meta_Collector_Test.php +++ b/tests/Unit/User_Meta/Application/Custom_Meta_Collector_Test.php @@ -51,7 +51,7 @@ protected function set_up() { $this->instance = new Custom_Meta_Collector( $this->author_metadesc, - $this->noindex_author + $this->noindex_author, ); } diff --git a/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Metadesc_Test.php b/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Metadesc_Test.php index 66f7c94b3da..6509efebe9e 100644 --- a/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Metadesc_Test.php +++ b/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Metadesc_Test.php @@ -56,7 +56,7 @@ protected function set_up(): void { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } diff --git a/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Title_Test.php b/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Title_Test.php index aab2dcefd9e..f37fc1615e1 100644 --- a/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Title_Test.php +++ b/tests/Unit/User_Meta/Framework/Custom_Meta/Author_Title_Test.php @@ -56,7 +56,7 @@ protected function set_up(): void { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } diff --git a/tests/Unit/User_Meta/Framework/Custom_Meta/Content_Analysis_Disable_Test.php b/tests/Unit/User_Meta/Framework/Custom_Meta/Content_Analysis_Disable_Test.php index dfe34e07f8c..afdfc2ce9fc 100644 --- a/tests/Unit/User_Meta/Framework/Custom_Meta/Content_Analysis_Disable_Test.php +++ b/tests/Unit/User_Meta/Framework/Custom_Meta/Content_Analysis_Disable_Test.php @@ -56,7 +56,7 @@ protected function set_up(): void { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } diff --git a/tests/Unit/User_Meta/Framework/Custom_Meta/Inclusive_Language_Analysis_Disable_Test.php b/tests/Unit/User_Meta/Framework/Custom_Meta/Inclusive_Language_Analysis_Disable_Test.php index a34f346674a..1c4cc9204e6 100644 --- a/tests/Unit/User_Meta/Framework/Custom_Meta/Inclusive_Language_Analysis_Disable_Test.php +++ b/tests/Unit/User_Meta/Framework/Custom_Meta/Inclusive_Language_Analysis_Disable_Test.php @@ -56,7 +56,7 @@ protected function set_up(): void { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } diff --git a/tests/Unit/User_Meta/Framework/Custom_Meta/Keyword_Analysis_Disable_Test.php b/tests/Unit/User_Meta/Framework/Custom_Meta/Keyword_Analysis_Disable_Test.php index 6b9f63c84e9..3bda5a50bf5 100644 --- a/tests/Unit/User_Meta/Framework/Custom_Meta/Keyword_Analysis_Disable_Test.php +++ b/tests/Unit/User_Meta/Framework/Custom_Meta/Keyword_Analysis_Disable_Test.php @@ -56,7 +56,7 @@ protected function set_up(): void { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } diff --git a/tests/Unit/User_Meta/Framework/Custom_Meta/Noindex_Author_Test.php b/tests/Unit/User_Meta/Framework/Custom_Meta/Noindex_Author_Test.php index d9fa4a073ac..3410a72c5e7 100644 --- a/tests/Unit/User_Meta/Framework/Custom_Meta/Noindex_Author_Test.php +++ b/tests/Unit/User_Meta/Framework/Custom_Meta/Noindex_Author_Test.php @@ -56,7 +56,7 @@ protected function set_up(): void { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } diff --git a/tests/Unit/User_Meta/Infrastructure/Cleanup_Repository_Test.php b/tests/Unit/User_Meta/Infrastructure/Cleanup_Repository_Test.php index 7eb99fb897b..5128a77c609 100644 --- a/tests/Unit/User_Meta/Infrastructure/Cleanup_Repository_Test.php +++ b/tests/Unit/User_Meta/Infrastructure/Cleanup_Repository_Test.php @@ -64,7 +64,7 @@ public function test_delete_empty_usermeta_query() { 'facebook', 'wpseo_noindex_author', 1000, - ] + ], ) ->andReturn( ' @@ -72,7 +72,7 @@ public function test_delete_empty_usermeta_query() { WHERE meta_key IN( "facebook", "wpseo_noindex_author" ) AND meta_value = "" ORDER BY user_id - LIMIT 1000' + LIMIT 1000', ); $wpdb @@ -84,7 +84,7 @@ public function test_delete_empty_usermeta_query() { WHERE meta_key IN( "facebook", "wpseo_noindex_author" ) AND meta_value = "" ORDER BY user_id - LIMIT 1000' + LIMIT 1000', ) ->andReturn( 200 ); diff --git a/tests/Unit/User_Meta/User_Interface/Additional_Contactmethods_Integration_Test.php b/tests/Unit/User_Meta/User_Interface/Additional_Contactmethods_Integration_Test.php index f64c962d133..4c739c67ed8 100644 --- a/tests/Unit/User_Meta/User_Interface/Additional_Contactmethods_Integration_Test.php +++ b/tests/Unit/User_Meta/User_Interface/Additional_Contactmethods_Integration_Test.php @@ -42,7 +42,7 @@ protected function set_up() { $this->additional_contactmethods_collector = Mockery::mock( Additional_Contactmethods_Collector::class ); $this->instance = new Additional_Contactmethods_Integration( - $this->additional_contactmethods_collector + $this->additional_contactmethods_collector, ); } @@ -67,7 +67,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Additional_Contactmethods_Collector::class, - $this->getPropertyValue( $this->instance, 'additional_contactmethods_collector' ) + $this->getPropertyValue( $this->instance, 'additional_contactmethods_collector' ), ); } diff --git a/tests/Unit/User_Meta/User_Interface/Cleanup_Integration_Test.php b/tests/Unit/User_Meta/User_Interface/Cleanup_Integration_Test.php index 7fd3643fc50..061fc183dd5 100644 --- a/tests/Unit/User_Meta/User_Interface/Cleanup_Integration_Test.php +++ b/tests/Unit/User_Meta/User_Interface/Cleanup_Integration_Test.php @@ -42,7 +42,7 @@ protected function set_up() { $this->cleanup_service = Mockery::mock( Cleanup_Service::class ); $this->instance = new Cleanup_Integration( - $this->cleanup_service + $this->cleanup_service, ); } @@ -67,7 +67,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Cleanup_Service::class, - $this->getPropertyValue( $this->instance, 'cleanup_service' ) + $this->getPropertyValue( $this->instance, 'cleanup_service' ), ); } diff --git a/tests/Unit/User_Meta/User_Interface/Custom_Meta_Integration_Test.php b/tests/Unit/User_Meta/User_Interface/Custom_Meta_Integration_Test.php index 431d4073a3d..a8d3de453cb 100644 --- a/tests/Unit/User_Meta/User_Interface/Custom_Meta_Integration_Test.php +++ b/tests/Unit/User_Meta/User_Interface/Custom_Meta_Integration_Test.php @@ -48,7 +48,7 @@ protected function set_up() { $this->custom_meta_collector = Mockery::mock( Custom_Meta_Collector::class ); $this->instance = new Custom_Meta_Integration( - $this->custom_meta_collector + $this->custom_meta_collector, ); } @@ -79,7 +79,7 @@ public function test_get_conditionals() { public function test_constructor() { $this->assertInstanceOf( Custom_Meta_Collector::class, - $this->getPropertyValue( $this->instance, 'custom_meta_collector' ) + $this->getPropertyValue( $this->instance, 'custom_meta_collector' ), ); } diff --git a/tests/Unit/User_Profiles_Additions/User_Interface/User_Profiles_Additions_Ui_Test.php b/tests/Unit/User_Profiles_Additions/User_Interface/User_Profiles_Additions_Ui_Test.php index a8b58f35f30..b001ffb161a 100644 --- a/tests/Unit/User_Profiles_Additions/User_Interface/User_Profiles_Additions_Ui_Test.php +++ b/tests/Unit/User_Profiles_Additions/User_Interface/User_Profiles_Additions_Ui_Test.php @@ -65,11 +65,11 @@ protected function set_up() { public function test_construct() { $this->assertInstanceOf( WPSEO_Admin_Asset_Manager::class, - $this->getPropertyValue( $this->instance, 'asset_manager' ) + $this->getPropertyValue( $this->instance, 'asset_manager' ), ); $this->assertInstanceOf( Product_Helper::class, - $this->getPropertyValue( $this->instance, 'product_helper' ) + $this->getPropertyValue( $this->instance, 'product_helper' ), ); } @@ -83,7 +83,7 @@ public function test_construct() { public function test_get_conditionals() { $this->assertEquals( [ User_Profile_Conditional::class ], - User_Profiles_Additions_Ui::get_conditionals() + User_Profiles_Additions_Ui::get_conditionals(), ); } diff --git a/tests/Unit/Values/Images_Test.php b/tests/Unit/Values/Images_Test.php index 8ac4fc1947c..35a36899b64 100644 --- a/tests/Unit/Values/Images_Test.php +++ b/tests/Unit/Values/Images_Test.php @@ -74,7 +74,7 @@ public function test_add_image() { [ 'image.jpg' => $image, ], - $this->instance->get_images() + $this->instance->get_images(), ); } @@ -101,7 +101,7 @@ public function test_add_image_with_string_given() { 'url' => $image, ], ], - $this->instance->get_images() + $this->instance->get_images(), ); } @@ -153,7 +153,7 @@ public function test_add_image_that_is_added_before() { [ 'image.jpg' => $image1, ], - $this->instance->get_images() + $this->instance->get_images(), ); } @@ -230,7 +230,7 @@ public function test_add_image_by_url_with_no_image_id() { [ 'image.jpg' => $image, ], - $this->instance->get_images() + $this->instance->get_images(), ); } @@ -261,7 +261,7 @@ public function test_add_image_by_id() { 'url' => 'image.jpg', ], ], - $this->instance->get_images() + $this->instance->get_images(), ); } diff --git a/tests/Unit/Values/OAuth/OAuth_Token_Test.php b/tests/Unit/Values/OAuth/OAuth_Token_Test.php index 76b80c34488..40ec55ea98b 100644 --- a/tests/Unit/Values/OAuth/OAuth_Token_Test.php +++ b/tests/Unit/Values/OAuth/OAuth_Token_Test.php @@ -44,7 +44,7 @@ protected function set_up() { * @return void */ public function test_creating_new_instance() { - $instance = new OAuth_Token( '000000', '000001', 604800, false, $this->created_at ); + $instance = new OAuth_Token( '000000', '000001', 604_800, false, $this->created_at ); $this->assertInstanceOf( OAuth_Token::class, $instance ); } @@ -59,7 +59,7 @@ public function test_creating_new_instance() { public function test_creating_new_instance_empty_access_token() { $this->expectException( Empty_Property_Exception::class ); - new OAuth_Token( '', '000001', 604800, true, $this->created_at ); + new OAuth_Token( '', '000001', 604_800, true, $this->created_at ); } /** @@ -72,7 +72,7 @@ public function test_creating_new_instance_empty_access_token() { public function test_creating_new_instance_empty_refresh_token() { $this->expectException( Empty_Property_Exception::class ); - new OAuth_Token( '000000', '', 604800, true, $this->created_at ); + new OAuth_Token( '000000', '', 604_800, true, $this->created_at ); } /** @@ -98,7 +98,7 @@ public function test_creating_new_instance_empty_expires() { public function test_creating_new_instance_empty_has_expired() { $this->expectException( Empty_Property_Exception::class ); - new OAuth_Token( '000000', '000001', 604800, null, $this->created_at ); + new OAuth_Token( '000000', '000001', 604_800, null, $this->created_at ); } /** @@ -109,11 +109,11 @@ public function test_creating_new_instance_empty_has_expired() { * @return void */ public function test_getters() { - $instance = new OAuth_Token( '000000', '000001', ( $this->created_at + 604800 ), false, $this->created_at ); + $instance = new OAuth_Token( '000000', '000001', ( $this->created_at + 604_800 ), false, $this->created_at ); $this->assertEquals( '000000', $instance->access_token ); $this->assertEquals( '000001', $instance->refresh_token ); - $this->assertEquals( ( $this->created_at + 604800 ), $instance->expires ); + $this->assertEquals( ( $this->created_at + 604_800 ), $instance->expires ); $this->assertFalse( $instance->has_expired() ); $this->assertEquals( $this->created_at, $instance->created_at ); $this->assertEquals( 0, $instance->error_count ); @@ -130,21 +130,21 @@ public function test_to_array() { $instance = new OAuth_Token( '000000', '000001', - ( $this->created_at + 604800 ), + ( $this->created_at + 604_800 ), false, - $this->created_at + $this->created_at, ); $this->assertEquals( [ 'access_token' => '000000', 'refresh_token' => '000001', - 'expires' => ( $this->created_at + 604800 ), + 'expires' => ( $this->created_at + 604_800 ), 'has_expired' => false, 'created_at' => $this->created_at, 'error_count' => 0, ], - $instance->to_array() + $instance->to_array(), ); } @@ -162,9 +162,9 @@ public function test_from_response() { [ 'getToken' => '000000', 'getRefreshToken' => '000001', - 'getExpires' => 604800, + 'getExpires' => 604_800, 'hasExpired' => false, - ] + ], ); $instance = OAuth_Token::from_response( $response ); @@ -172,7 +172,7 @@ public function test_from_response() { $this->assertInstanceOf( OAuth_Token::class, $instance ); $this->assertEquals( '000000', $this->getPropertyValue( $instance, 'access_token' ) ); $this->assertEquals( '000001', $this->getPropertyValue( $instance, 'refresh_token' ) ); - $this->assertEquals( 604800, $this->getPropertyValue( $instance, 'expires' ) ); + $this->assertEquals( 604_800, $this->getPropertyValue( $instance, 'expires' ) ); $this->assertEquals( false, $this->getPropertyValue( $instance, 'has_expired' ) ); $this->assertEquals( $this->created_at, $this->getPropertyValue( $instance, 'created_at' ) ); } diff --git a/tests/Unit/Values/Open_Graph/Images_Test.php b/tests/Unit/Values/Open_Graph/Images_Test.php index 391cf787cb2..36fd88b96e6 100644 --- a/tests/Unit/Values/Open_Graph/Images_Test.php +++ b/tests/Unit/Values/Open_Graph/Images_Test.php @@ -60,7 +60,7 @@ protected function set_up() { $this->url = Mockery::mock( Url_Helper::class )->makePartial(); $this->open_graph_image = Mockery::mock( Open_Graph_Image_Helper::class, - [ new Url_Helper(), $this->image ] + [ new Url_Helper(), $this->image ], )->makePartial(); $this->instance = new Images( $this->image, $this->url ); @@ -89,7 +89,7 @@ public function test_add_image_by_id() { 'url' => 'image.jpg', ], ], - $this->instance->get_images() + $this->instance->get_images(), ); } diff --git a/tests/Unit/bootstrap.php b/tests/Unit/bootstrap.php index b7a94f592e8..991bcf2fc87 100644 --- a/tests/Unit/bootstrap.php +++ b/tests/Unit/bootstrap.php @@ -64,7 +64,7 @@ 'WP_Term', 'WP_User', 'wpdb', - ] + ], ); /* ********************* DEFINES DEPENDING ON AUTOLOADED CODE ********************* */ diff --git a/tests/WP/Admin/Asset_Manager_Test.php b/tests/WP/Admin/Asset_Manager_Test.php index d0371e7e15d..cbcc2bb3e37 100644 --- a/tests/WP/Admin/Asset_Manager_Test.php +++ b/tests/WP/Admin/Asset_Manager_Test.php @@ -46,7 +46,7 @@ public function test_DEFAULT_register() { 'register_styles', 'scripts_to_be_registered', 'styles_to_be_registered', - ] + ], ) ->getMock(); @@ -54,14 +54,14 @@ public function test_DEFAULT_register() { ->expects( $this->once() ) ->method( 'scripts_to_be_registered' ) ->willReturn( - [ 'script' ] + [ 'script' ], ); $instance ->expects( $this->once() ) ->method( 'styles_to_be_registered' ) ->willReturn( - [ 'style' ] + [ 'style' ], ); $instance @@ -265,7 +265,7 @@ public function test_register_scripts() { ->method( 'register_script' ) ->withConsecutive( [ $this->equalTo( new WPSEO_Admin_Asset( $asset_args[0] ) ) ], - [ $this->equalTo( new WPSEO_Admin_Asset( $asset_args[1] ) ) ] + [ $this->equalTo( new WPSEO_Admin_Asset( $asset_args[1] ) ) ], ); $class_instance->register_scripts( $asset_args ); @@ -302,7 +302,7 @@ public function test_register_styles() { ->method( 'register_style' ) ->withConsecutive( [ $this->equalTo( new WPSEO_Admin_Asset( $asset_args[0] ) ) ], - [ $this->equalTo( new WPSEO_Admin_Asset( $asset_args[1] ) ) ] + [ $this->equalTo( new WPSEO_Admin_Asset( $asset_args[1] ) ) ], ); $class_instance->register_styles( $asset_args ); diff --git a/tests/WP/Admin/Database_Proxy_Test.php b/tests/WP/Admin/Database_Proxy_Test.php index e3edff4a8e9..e3ba423a728 100644 --- a/tests/WP/Admin/Database_Proxy_Test.php +++ b/tests/WP/Admin/Database_Proxy_Test.php @@ -44,7 +44,7 @@ public static function set_up_before_class() { ], [ 'PRIMARY KEY (id)', - ] + ], ); } @@ -90,7 +90,7 @@ public function test_insert() { 'testkey' => 'key2', 'testval' => 'value2', ], - [ '%s', '%s' ] + [ '%s', '%s' ], ); $this->assertSame( 1, $result ); @@ -109,7 +109,7 @@ public function test_insert_exists() { 'testkey' => 'key2', 'testval' => 'value2', ], - [ '%s', '%s' ] + [ '%s', '%s' ], ); $result = self::$proxy->insert( @@ -118,7 +118,7 @@ public function test_insert_exists() { 'testkey' => 'key2', 'testval' => 'value2', ], - [ '%d', '%s', '%s' ] + [ '%d', '%s', '%s' ], ); $this->assertFalse( $result ); @@ -136,7 +136,7 @@ public function test_insert_invalid() { [ 'testvalue' => 'value2', ], - [ '%s' ] + [ '%s' ], ); $this->assertFalse( $result ); @@ -155,7 +155,7 @@ public function test_update() { 'testkey' => 'key2', 'testval' => 'value2', ], - [ '%s', '%s' ] + [ '%s', '%s' ], ); $result = self::$proxy->update( @@ -166,7 +166,7 @@ public function test_update() { 'testkey' => 'key2', ], [ '%s' ], - [ '%s' ] + [ '%s' ], ); $this->assertSame( 1, $result ); @@ -188,7 +188,7 @@ public function test_update_not_exists() { 'testkey' => 'key2', ], [ '%s' ], - [ '%s' ] + [ '%s' ], ); $this->assertSame( 0, $result ); @@ -210,7 +210,7 @@ public function test_update_invalid() { 'testkey' => 'key1', ], [ '%s' ], - [ '%s' ] + [ '%s' ], ); $this->assertFalse( $result ); @@ -233,7 +233,7 @@ public function test_upsert_new() { [ 'id' => 2, ], - [ '%d', '%s', '%s' ] + [ '%d', '%s', '%s' ], ); $this->assertSame( 1, $result ); @@ -253,7 +253,7 @@ public function test_upsert_existing() { 'testkey' => 'key10', 'testval' => 'value10-1', ], - [ '%d', '%s', '%s' ] + [ '%d', '%s', '%s' ], ); $result = self::$proxy->upsert( @@ -265,7 +265,7 @@ public function test_upsert_existing() { [ 'id' => 10, ], - [ '%d', '%s', '%s' ] + [ '%d', '%s', '%s' ], ); /* @@ -288,7 +288,7 @@ public function test_upsert_existing() { 'testkey' => 'key10', 'testval' => 'value10-2', ], - $results[0] + $results[0], ); } @@ -305,14 +305,14 @@ public function test_delete() { 'testkey' => 'key1', 'testval' => 'value', ], - [ '%s', '%s' ] + [ '%s', '%s' ], ); $result = self::$proxy->delete( [ 'testkey' => 'key1', ], - [ '%s' ] + [ '%s' ], ); $this->assertSame( 1, $result ); @@ -330,7 +330,7 @@ public function test_delete_not_exists() { [ 'testkey' => 'key2', ], - [ '%s' ] + [ '%s' ], ); $this->assertSame( 0, $result ); @@ -348,7 +348,7 @@ public function test_delete_invalid() { [ 'testvalue' => 'key1', ], - [ '%s' ] + [ '%s' ], ); $this->assertFalse( $result ); @@ -369,7 +369,7 @@ public function test_get_results() { 'testkey' => 'key1', 'testval' => 'value', ], - [ '%s', '%s' ] + [ '%s', '%s' ], ); $result = self::$proxy->get_results( "SELECT * FROM $table_name WHERE testkey = 'key1'" ); @@ -406,7 +406,7 @@ public function test_create_table() { ], [ 'PRIMARY KEY (id)', - ] + ], ); $this->assertTrue( $result ); diff --git a/tests/WP/Admin/Editor_Specific_Replace_Vars_Test.php b/tests/WP/Admin/Editor_Specific_Replace_Vars_Test.php index 23f5f94cfc1..9295750910f 100644 --- a/tests/WP/Admin/Editor_Specific_Replace_Vars_Test.php +++ b/tests/WP/Admin/Editor_Specific_Replace_Vars_Test.php @@ -39,7 +39,7 @@ public function set_up() { public function test_add_for_page_types() { $this->class_instance->add_for_page_types( [ 'post' ], - [ 'cf_custom_field' ] + [ 'cf_custom_field' ], ); $actual = $this->class_instance->get(); @@ -94,8 +94,8 @@ public function test_get_shared_replace_vars_filters_editor_specific_replace_var $this->assertEquals( [ 'title' ], $this->class_instance->get_generic( - $replace_vars_list - ) + $replace_vars_list, + ), ); } @@ -326,7 +326,7 @@ private function create_and_get_with_post_type( $post_type = 'post' ) { return self::factory()->post->create_and_get( [ 'post_type' => $post_type, - ] + ], ); } @@ -354,7 +354,7 @@ public function test_editor_specific_replacement_variables_filter() { $this->assertEquals( $expected_replacement_variables, - $this->class_instance->get() + $this->class_instance->get(), ); \remove_filter( 'wpseo_editor_specific_replace_vars', [ $this, 'filter_editor_specific_replacement_variables' ] ); @@ -385,7 +385,7 @@ public function test_editor_specific_replacement_variables_filter_with_wrong_ret $this->assertEquals( $expected_replacement_variables, - $this->class_instance->get() + $this->class_instance->get(), ); \remove_filter( 'wpseo_editor_specific_replace_vars', '__return_false' ); diff --git a/tests/WP/Admin/Exceptions/File_Size_Exception_Test.php b/tests/WP/Admin/Exceptions/File_Size_Exception_Test.php index 538b880765c..d8182623d36 100644 --- a/tests/WP/Admin/Exceptions/File_Size_Exception_Test.php +++ b/tests/WP/Admin/Exceptions/File_Size_Exception_Test.php @@ -22,7 +22,7 @@ public function test_externally_hosted_exception() { $this->assertEquals( 'Cannot get the size of https://external.im/age.jpg because it is hosted externally.', - $expected_exception->getMessage() + $expected_exception->getMessage(), ); } @@ -38,7 +38,7 @@ public function test_unknown_error() { $this->assertEquals( 'Cannot get the size of image.jpg because of unknown reasons.', - $expected_exception->getMessage() + $expected_exception->getMessage(), ); } } diff --git a/tests/WP/Admin/Import/Premium_SEO_Pack_Test.php b/tests/WP/Admin/Import/Premium_SEO_Pack_Test.php index 65532a2fbbc..e3a9ff3d471 100644 --- a/tests/WP/Admin/Import/Premium_SEO_Pack_Test.php +++ b/tests/WP/Admin/Import/Premium_SEO_Pack_Test.php @@ -301,7 +301,7 @@ private function setup_post( $pre_existing_yoast_data = false ) { 'og_media' => 'http://local.wordpress.test/wp-content/uploads/2018/01/actionable-seo.png', 'og_title' => 'OpenGraph AIOSEO title', 'cornerstone' => 1, - ] + ], ); $this->insert_post( $post_id, $blob ); @@ -346,7 +346,7 @@ private function build_data_blob( $data = [] ) { 'patterns' => '', 'sep' => '', ], - $data + $data, ); } @@ -376,8 +376,8 @@ private function insert_post( $post_id, $blob ) { $post_id, \get_permalink( $post_id ), \md5( \get_permalink( $post_id ) ), - \serialize( $blob ) - ) + \serialize( $blob ), + ), ); } @@ -404,7 +404,7 @@ private function create_table() { UNIQUE KEY `url_hash` (`url_hash`) USING BTREE, KEY `post_id` (`post_id`) USING BTREE, KEY `blog_id_url_hash` (`blog_id`,`url_hash`) USING BTREE - ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8" + ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8", ); } } diff --git a/tests/WP/Admin/Import/RankMath_Test.php b/tests/WP/Admin/Import/RankMath_Test.php index 9b23196d9be..d3db7249e53 100644 --- a/tests/WP/Admin/Import/RankMath_Test.php +++ b/tests/WP/Admin/Import/RankMath_Test.php @@ -206,7 +206,7 @@ private function setup_options() { 'homepage_title' => 'Test homepage title', 'homepage_description' => 'Test homepage description', 'pt_post_title' => 'Test post title template %sep% %sitename%', - ] + ], ); } } diff --git a/tests/WP/Admin/Import/Squirrly_Test.php b/tests/WP/Admin/Import/Squirrly_Test.php index 1a6b0d2c828..7b248136abd 100644 --- a/tests/WP/Admin/Import/Squirrly_Test.php +++ b/tests/WP/Admin/Import/Squirrly_Test.php @@ -337,7 +337,7 @@ private function setup_post( $pre_existing_yoast_data = false ) { 'og_media' => 'http://local.wordpress.test/wp-content/uploads/2018/01/actionable-seo.png', 'og_title' => 'OpenGraph AIOSEO title', 'cornerstone' => 1, - ] + ], ); $this->insert_post( $post_id, $blob ); \update_post_meta( $post_id, '_sq_post_keyword', '{"keyword":"squirrly test","update":1521207189}' ); @@ -383,7 +383,7 @@ private function build_data_blob( $data = [] ) { 'patterns' => '', 'sep' => '', ], - $data + $data, ); } @@ -413,8 +413,8 @@ private function insert_post( $post_id, $blob ) { $post_id, \get_permalink( $post_id ), \md5( \get_permalink( $post_id ) ), - \serialize( $blob ) - ) + \serialize( $blob ), + ), ); } @@ -441,7 +441,7 @@ private function create_table() { UNIQUE KEY `url_hash` (`url_hash`) USING BTREE, KEY `post_id` (`post_id`) USING BTREE, KEY `blog_id_url_hash` (`blog_id`,`url_hash`) USING BTREE - ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8" + ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8", ); } } diff --git a/tests/WP/Admin/Import/WPSEO_Test.php b/tests/WP/Admin/Import/WPSEO_Test.php index f2105b63da5..b8701ccad97 100644 --- a/tests/WP/Admin/Import/WPSEO_Test.php +++ b/tests/WP/Admin/Import/WPSEO_Test.php @@ -247,7 +247,7 @@ private function create_category_metadata( $name, $desc, $robots ) { [ 'name' => $name, 'taxonomy' => 'category', - ] + ], ); \update_option( 'wpseo_category_' . $term_id, $desc ); \update_option( 'wpseo_category_' . $term_id . '_robots', $robots ); diff --git a/tests/WP/Admin/Input_Select_Test.php b/tests/WP/Admin/Input_Select_Test.php index ba757c27b00..706067783af 100644 --- a/tests/WP/Admin/Input_Select_Test.php +++ b/tests/WP/Admin/Input_Select_Test.php @@ -29,7 +29,7 @@ public function test_html_with_options() { 'foo' => 'bar', 'baz' => 'foo', ], - false + false, ); $html = $select->get_html(); @@ -76,7 +76,7 @@ public function test_html_with_options_and_one_active() { 'foo' => 'bar', 'baz' => 'foo', ], - 'baz' + 'baz', ); $html = $select->get_html(); diff --git a/tests/WP/Admin/Metabox/Metabox_Test.php b/tests/WP/Admin/Metabox/Metabox_Test.php index 00dfda7bd44..19faddb6f07 100644 --- a/tests/WP/Admin/Metabox/Metabox_Test.php +++ b/tests/WP/Admin/Metabox/Metabox_Test.php @@ -133,7 +133,7 @@ public function test_save_postdata() { $meta_fields, WPSEO_Meta::get_meta_field_defs( 'general', $post->post_type ), WPSEO_Meta::get_meta_field_defs( 'advanced' ), - WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ) + WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ), ); // Set $_POST data to be saved. diff --git a/tests/WP/Admin/Recommended_Replace_Vars_Test.php b/tests/WP/Admin/Recommended_Replace_Vars_Test.php index 9011530b5e4..2682ff0a82b 100644 --- a/tests/WP/Admin/Recommended_Replace_Vars_Test.php +++ b/tests/WP/Admin/Recommended_Replace_Vars_Test.php @@ -309,7 +309,7 @@ private function create_and_get_with_post_type( $post_type = 'post' ) { return self::factory()->post->create_and_get( [ 'post_type' => $post_type, - ] + ], ); } } diff --git a/tests/WP/Admin/Watchers/Indexable_Ancestor_Watcher_Test.php b/tests/WP/Admin/Watchers/Indexable_Ancestor_Watcher_Test.php index 21bf8af4e51..51fc9a6a23c 100644 --- a/tests/WP/Admin/Watchers/Indexable_Ancestor_Watcher_Test.php +++ b/tests/WP/Admin/Watchers/Indexable_Ancestor_Watcher_Test.php @@ -95,7 +95,7 @@ public function set_up() { $this->indexable_hierarchy_repository, $this->indexable_helper, $this->permalink_helper, - $this->post_type_helper + $this->post_type_helper, ); } @@ -114,7 +114,7 @@ public function test_get_object_ids_for_term() { [ 'name' => 'test_term', 'taxonomy' => 'category', - ] + ], ); \wp_set_object_terms( $post1->ID, $term_id, 'category' ); diff --git a/tests/WP/Admin/Watchers/Indexable_Post_Watcher_Test.php b/tests/WP/Admin/Watchers/Indexable_Post_Watcher_Test.php index 988fe484f79..9bd7aa5de40 100644 --- a/tests/WP/Admin/Watchers/Indexable_Post_Watcher_Test.php +++ b/tests/WP/Admin/Watchers/Indexable_Post_Watcher_Test.php @@ -88,13 +88,13 @@ public function test_create_post_with_hierarchy() { $parent = $this->factory()->post->create_and_get( [ 'post_type' => 'page', - ] + ], ); $child = $this->factory()->post->create_and_get( [ 'post_type' => 'page', 'post_parent' => $parent->ID, - ] + ], ); $parent_indexable = \current( $this->get_indexables_for( $parent ) ); @@ -120,13 +120,13 @@ public function test_delete_post_with_hierarchy() { $parent = $this->factory()->post->create_and_get( [ 'post_type' => 'page', - ] + ], ); $child = $this->factory()->post->create_and_get( [ 'post_type' => 'page', 'post_parent' => $parent->ID, - ] + ], ); $parent_indexable = \current( $this->get_indexables_for( $parent ) ); diff --git a/tests/WP/Admin/Watchers/Slug_Change_Watcher_Test.php b/tests/WP/Admin/Watchers/Slug_Change_Watcher_Test.php index 1bf245aa051..df0089bb9b2 100644 --- a/tests/WP/Admin/Watchers/Slug_Change_Watcher_Test.php +++ b/tests/WP/Admin/Watchers/Slug_Change_Watcher_Test.php @@ -306,6 +306,6 @@ public function test_detect_term_delete_when_not_exists() { $instance->register_hooks(); - \wp_delete_term( 11111, 'category' ); + \wp_delete_term( 11_111, 'category' ); } } diff --git a/tests/WP/Builders/Indexable_Author_Builder_Test.php b/tests/WP/Builders/Indexable_Author_Builder_Test.php index 9c5c3b68611..cd6b1686452 100644 --- a/tests/WP/Builders/Indexable_Author_Builder_Test.php +++ b/tests/WP/Builders/Indexable_Author_Builder_Test.php @@ -41,7 +41,7 @@ public function set_up(): void { [ 'user_login' => 'user', 'user_pass' => 'password', - ] + ], )->ID; \update_user_meta( $this->user_id, 'wpseo_title', 'Title' ); @@ -54,7 +54,7 @@ public function set_up(): void { \YoastSEO()->helpers->author_archive, \YoastSEO()->classes->get( 'Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions' ), \YoastSEO()->helpers->options, - \YoastSEO()->helpers->post + \YoastSEO()->helpers->post, ); } @@ -72,7 +72,7 @@ public function test_build() { 'post_date' => '1978-09-13 08:50:00', 'post_status' => 'publish', 'post_author' => $this->user_id, - ] + ], ); $indexable = new Indexable(); @@ -124,7 +124,7 @@ public function test_build_when_author_archives_are_disabled() { 'post_date' => '1978-09-13 08:50:00', 'post_status' => 'publish', 'post_author' => $this->user_id, - ] + ], ); \YoastSEO()->helpers->options->set( 'disable-author', true ); @@ -183,7 +183,7 @@ public function test_build_when_author_is_filtered() { 'post_date' => '1978-09-13 08:50:00', 'post_status' => 'publish', 'post_author' => $this->user_id, - ] + ], ); \YoastSEO()->helpers->options->set( 'disable-author', true ); @@ -194,7 +194,7 @@ static function ( $exception, $user_id ) { return new Author_Not_Built_Exception( 'Author not built because of filter.' ); }, 10, - 2 + 2, ); $this->expectException( Author_Not_Built_Exception::class ); $this->expectExceptionMessage( 'Author not built because of filter' ); diff --git a/tests/WP/Builders/Indexable_Date_Archive_Builder_Test.php b/tests/WP/Builders/Indexable_Date_Archive_Builder_Test.php index b4621c078fe..0e86304921b 100644 --- a/tests/WP/Builders/Indexable_Date_Archive_Builder_Test.php +++ b/tests/WP/Builders/Indexable_Date_Archive_Builder_Test.php @@ -31,7 +31,7 @@ public function set_up(): void { $this->instance = new Indexable_Date_Archive_Builder( \YoastSEO()->helpers->options, - \YoastSEO()->classes->get( 'Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions' ) + \YoastSEO()->classes->get( 'Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions' ), ); } diff --git a/tests/WP/Builders/Indexable_Home_Page_Builder_Test.php b/tests/WP/Builders/Indexable_Home_Page_Builder_Test.php index 297fc513924..9973b25da6d 100644 --- a/tests/WP/Builders/Indexable_Home_Page_Builder_Test.php +++ b/tests/WP/Builders/Indexable_Home_Page_Builder_Test.php @@ -34,13 +34,13 @@ public function set_up(): void { \YoastSEO()->helpers->options, \YoastSEO()->helpers->url, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), - \YoastSEO()->helpers->post + \YoastSEO()->helpers->post, ); $this->instance->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); } @@ -146,7 +146,7 @@ public function test_build_when_open_graph_image_is_present() { 'post_parent' => 0, 'post_mime_type' => 'image/jpeg', 'guid' => \home_url() . $fake_image_path, - ] + ], ); $expected_image['id'] = $id; @@ -158,7 +158,7 @@ public function test_build_when_open_graph_image_is_present() { [ 'width' => $fake_image_width, 'height' => $fake_image_height, - ] + ], ); \YoastSEO()->helpers->options->set( 'open_graph_frontpage_image_id', $id ); diff --git a/tests/WP/Builders/Indexable_Post_Type_Archive_Builder_Test.php b/tests/WP/Builders/Indexable_Post_Type_Archive_Builder_Test.php index 60fda177480..63da74d7616 100644 --- a/tests/WP/Builders/Indexable_Post_Type_Archive_Builder_Test.php +++ b/tests/WP/Builders/Indexable_Post_Type_Archive_Builder_Test.php @@ -34,7 +34,7 @@ public function set_up(): void { \YoastSEO()->helpers->options, \YoastSEO()->classes->get( 'Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions' ), \YoastSEO()->helpers->post, - \YoastSEO()->helpers->post_type + \YoastSEO()->helpers->post_type, ); } @@ -54,7 +54,7 @@ public function test_build() { 'has_archive' => true, 'description' => 'a cool post type', 'label' => $post_type, - ] + ], ); $post = [ @@ -98,7 +98,7 @@ public function test_build_when_post_type_not_public() { 'has_archive' => true, 'description' => 'a cool post type', 'label' => $post_type, - ] + ], ); $post = [ diff --git a/tests/WP/Builders/Indexable_Term_Builder_Test.php b/tests/WP/Builders/Indexable_Term_Builder_Test.php index bce7978055e..ffe23e3e331 100644 --- a/tests/WP/Builders/Indexable_Term_Builder_Test.php +++ b/tests/WP/Builders/Indexable_Term_Builder_Test.php @@ -52,14 +52,14 @@ public function set_up(): void { 'post_title' => 'Test post', 'post_date' => '1978-09-13 08:50:00', 'post_status' => 'publish', - ] + ], ); $this->term_id = self::factory()->category->create( [ 'name' => 'test_term', 'taxonomy' => 'category', - ] + ], ); self::factory()->term->add_post_terms( $post_id, $this->term_id, 'category', true ); @@ -82,13 +82,13 @@ public function set_up(): void { $this->instance = new Indexable_Term_Builder( \YoastSEO()->helpers->taxonomy, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), - \YoastSEO()->helpers->post + \YoastSEO()->helpers->post, ); $this->instance->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); } @@ -155,14 +155,14 @@ public function test_build_category_not_indexable() { [ 'public' => false, 'query_var' => false, - ] + ], ); $term_id = self::factory()->term->create( [ 'taxonomy' => 'test_tax', 'name' => 'test_term', - ] + ], ); $indexable = new Indexable(); diff --git a/tests/WP/Content_Type_Visibility/Dismiss_New_Route_Test.php b/tests/WP/Content_Type_Visibility/Dismiss_New_Route_Test.php index dbf3883dae8..1513d6ef572 100644 --- a/tests/WP/Content_Type_Visibility/Dismiss_New_Route_Test.php +++ b/tests/WP/Content_Type_Visibility/Dismiss_New_Route_Test.php @@ -138,13 +138,13 @@ public function test_post_type_dismiss( $new_post_types, $post_type_name, $messa $this->assertInstanceOf( WP_REST_Response::class, $result, - 'post_type_dismiss_returns WP_REST_Response object' + 'post_type_dismiss_returns WP_REST_Response object', ); $this->assertSame( $message, $result->data->message, - 'post_type_dismiss_returns correct message' + 'post_type_dismiss_returns correct message', ); } @@ -192,13 +192,13 @@ public function test_taxonomy_dismiss( $new_taxonomies, $taxonomy_name, $message $this->assertInstanceOf( WP_REST_Response::class, $result, - 'taxonomy_dismiss_returns WP_REST_Response object' + 'taxonomy_dismiss_returns WP_REST_Response object', ); $this->assertSame( $message, $result->data->message, - 'taxonomy_dismiss_returns correct message' + 'taxonomy_dismiss_returns correct message', ); } @@ -238,13 +238,13 @@ public function test_taxonomy_dismiss_fail() { $this->assertInstanceOf( WP_REST_Response::class, $result, - 'taxonomy_dismiss_returns WP_REST_Response object' + 'taxonomy_dismiss_returns WP_REST_Response object', ); $this->assertSame( 'Error: Taxonomy was not removed from new_taxonomies list.', $result->data->message, - 'taxonomy_dismiss_returns correct message' + 'taxonomy_dismiss_returns correct message', ); } @@ -284,13 +284,13 @@ public function test_post_type_dismiss_fail() { $this->assertInstanceOf( WP_REST_Response::class, $result, - 'post_type_dismiss_returns WP_REST_Response object' + 'post_type_dismiss_returns WP_REST_Response object', ); $this->assertSame( 'Error: Post type was not removed from new_post_types list.', $result->data->message, - 'post_type_dismiss_returns correct message' + 'post_type_dismiss_returns correct message', ); } } diff --git a/tests/WP/Dashboard/Application/Filter_Pairs/Filter_Pairs_Repository_Test.php b/tests/WP/Dashboard/Application/Filter_Pairs/Filter_Pairs_Repository_Test.php index 4d161b451b2..a4b9152e28e 100644 --- a/tests/WP/Dashboard/Application/Filter_Pairs/Filter_Pairs_Repository_Test.php +++ b/tests/WP/Dashboard/Application/Filter_Pairs/Filter_Pairs_Repository_Test.php @@ -63,7 +63,7 @@ public function test_get_taxonomy( [ 'public' => $is_public, 'show_in_rest' => $show_in_rest, - ] + ], ); self::assertEquals( $expected, $this->instance->get_taxonomy( $object_type_name ) ); \unregister_taxonomy( $taxonomy_name ); diff --git a/tests/WP/Dashboard/Application/Taxonomies/Taxonomies_Repository_Test.php b/tests/WP/Dashboard/Application/Taxonomies/Taxonomies_Repository_Test.php index 13b321a1d33..86198f93a5d 100644 --- a/tests/WP/Dashboard/Application/Taxonomies/Taxonomies_Repository_Test.php +++ b/tests/WP/Dashboard/Application/Taxonomies/Taxonomies_Repository_Test.php @@ -58,7 +58,7 @@ public function set_up(): void { 'slug' => 'yoast-test-books', ], 'show_in_rest' => true, - ] + ], ); \register_taxonomy( 'alternative-genre', @@ -70,7 +70,7 @@ public function set_up(): void { 'rest_base' => 'alternative_genres', 'rest_namespace' => 'my_custom_namespace/v1', 'rewrite' => [ 'slug' => 'alternative-genre' ], - ] + ], ); \register_taxonomy( @@ -79,7 +79,7 @@ public function set_up(): void { [ 'public' => true, 'show_in_rest' => true, - ] + ], ); } diff --git a/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Construct_Test.php b/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Construct_Test.php index 650486fe716..9380b398156 100644 --- a/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Construct_Test.php +++ b/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Construct_Test.php @@ -25,7 +25,7 @@ final class Analytics_4_Adapter_Construct_Test extends Abstract_Analytics_4_Adap public function test_construct() { $this->assertInstanceOf( Site_Kit_Analytics_4_Api_Call::class, - $this->getPropertyValue( $this->instance, 'site_kit_search_console_api_call' ) + $this->getPropertyValue( $this->instance, 'site_kit_search_console_api_call' ), ); } } diff --git a/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Comparison_Response_Test.php b/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Comparison_Response_Test.php index 37b515d0c3e..0abbafa4465 100644 --- a/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Comparison_Response_Test.php +++ b/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Comparison_Response_Test.php @@ -61,7 +61,7 @@ public function test_validate_response_failed_request() { 'this is an error', [ 'status' => 400, - ] + ], ); $api_response_mock = Mockery::mock( WP_REST_Response::class ); diff --git a/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Daily_Response_Test.php b/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Daily_Response_Test.php index 7fc539e3612..eff66c49b40 100644 --- a/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Daily_Response_Test.php +++ b/tests/WP/Dashboard/Infrastructure/Analytics_4/Analytics_4_Adapter_Validate_Daily_Response_Test.php @@ -61,7 +61,7 @@ public function test_validate_response_failed_request() { 'this is an error', [ 'status' => 400, - ] + ], ); $api_response_mock = Mockery::mock( WP_REST_Response::class ); diff --git a/tests/WP/Dashboard/Infrastructure/Integrations/Is_Site_Kit_On_Boarded_Test.php b/tests/WP/Dashboard/Infrastructure/Integrations/Is_Site_Kit_On_Boarded_Test.php index fe84057b658..c73d7d686aa 100644 --- a/tests/WP/Dashboard/Infrastructure/Integrations/Is_Site_Kit_On_Boarded_Test.php +++ b/tests/WP/Dashboard/Infrastructure/Integrations/Is_Site_Kit_On_Boarded_Test.php @@ -86,7 +86,7 @@ public function test_is_site_kit_onboarded( 'googlesitekit_oauth_secret', static function () use ( $oauth_keys ) { return $oauth_keys; - } + }, ); $this->site_kit_consent_repository->set_site_kit_consent( $is_consent_granted ); @@ -106,7 +106,7 @@ public static function generate_site_kit_onboarded_provider() { 'client_id' => 'client_id', 'client_secret' => 'client_secret', ], - ] + ], ), 'is_consent_granted' => true, 'expected' => true, @@ -118,7 +118,7 @@ public static function generate_site_kit_onboarded_provider() { 'client_id' => 'client_id', 'client_secret' => 'client_secret', ], - ] + ], ), 'is_consent_granted' => false, 'expected' => false, @@ -134,7 +134,7 @@ public static function generate_site_kit_onboarded_provider() { 'web' => [ 'client_id' => 'client_id', ], - ] + ], ), 'is_consent_granted' => true, 'expected' => false, diff --git a/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Construct.php b/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Construct.php index 3ae6955176c..e873b326e8e 100644 --- a/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Construct.php +++ b/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Construct.php @@ -28,7 +28,7 @@ public function test_construct() { $this->assertInstanceOf( Module::class, - $module + $module, ); } } diff --git a/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Comparison_Response_Test.php b/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Comparison_Response_Test.php index 0dc5146a13c..d43223fbbc6 100644 --- a/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Comparison_Response_Test.php +++ b/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Comparison_Response_Test.php @@ -61,7 +61,7 @@ public function test_validate_response_failed_request() { 'this is an error', [ 'status' => 400, - ] + ], ); $api_response_mock = Mockery::mock( WP_REST_Response::class ); $api_response_mock->expects( 'get_data' )->once()->andReturn( 'not an array' ); diff --git a/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Response_Test.php b/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Response_Test.php index bf03d0115ee..521cf343d2e 100644 --- a/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Response_Test.php +++ b/tests/WP/Dashboard/Infrastructure/Search_Console/Search_Console_Adapter_Validate_Response_Test.php @@ -62,7 +62,7 @@ public function test_validate_response_failed_request() { 'this is an error', [ 'status' => 400, - ] + ], ); $api_response_mock = Mockery::mock( WP_REST_Response::class ); diff --git a/tests/WP/Dashboard/User_Interface/Configuration/Site_Kit_Capabilities_Integration_Test.php b/tests/WP/Dashboard/User_Interface/Configuration/Site_Kit_Capabilities_Integration_Test.php index 8886ca45bd7..27428b439b0 100644 --- a/tests/WP/Dashboard/User_Interface/Configuration/Site_Kit_Capabilities_Integration_Test.php +++ b/tests/WP/Dashboard/User_Interface/Configuration/Site_Kit_Capabilities_Integration_Test.php @@ -56,10 +56,10 @@ public function set_up() { * @return void */ public function test_enable_site_kit_capabilities( $current_capabilities, $capability_to_check, $user_roles, $expected ) { - $user_id = self::factory()->user->create_and_get( + $user_id = self::factory()->user->create( [ 'role' => $user_roles, - ] + ], ); \wp_set_current_user( $user_id ); $this->assertSame( $expected, $this->instance->enable_site_kit_capabilities( $current_capabilities, $capability_to_check ) ); diff --git a/tests/WP/Dashboard/User_Interface/Readability_Scores/Get_Scores_Test.php b/tests/WP/Dashboard/User_Interface/Readability_Scores/Get_Scores_Test.php index 292e6057d35..bd211f6c84d 100644 --- a/tests/WP/Dashboard/User_Interface/Readability_Scores/Get_Scores_Test.php +++ b/tests/WP/Dashboard/User_Interface/Readability_Scores/Get_Scores_Test.php @@ -56,7 +56,7 @@ public function test_get_readability_scores( $inserted_posts, $taxonomy_filter, [ 'slug' => 'test-category', ], - ] + ], ); $term_id = (int) $term->term_id; @@ -84,7 +84,7 @@ public function test_get_readability_scores( $inserted_posts, $taxonomy_filter, 'post_type' => 'blog-post', 'post_category' => ( $post['custom_category'] ) ? [ $term_id ] : [ 1 ], 'meta_input' => $meta_input, - ] + ], ); } diff --git a/tests/WP/Dashboard/User_Interface/Readability_Scores/Invalid_Term_Test.php b/tests/WP/Dashboard/User_Interface/Readability_Scores/Invalid_Term_Test.php index d45f8b924d1..e53d154d94d 100644 --- a/tests/WP/Dashboard/User_Interface/Readability_Scores/Invalid_Term_Test.php +++ b/tests/WP/Dashboard/User_Interface/Readability_Scores/Invalid_Term_Test.php @@ -26,7 +26,7 @@ public function test_get_readability_scores_with_invalid_term() { 'post_tag', [ 'slug' => 'test-tag', - ] + ], ); $request = new WP_REST_Request( 'GET', '/yoast/v1/readability_scores' ); diff --git a/tests/WP/Dashboard/User_Interface/SEO_Scores/Get_Scores_Test.php b/tests/WP/Dashboard/User_Interface/SEO_Scores/Get_Scores_Test.php index b624f4c53c0..f4b80e07a49 100644 --- a/tests/WP/Dashboard/User_Interface/SEO_Scores/Get_Scores_Test.php +++ b/tests/WP/Dashboard/User_Interface/SEO_Scores/Get_Scores_Test.php @@ -56,7 +56,7 @@ public function test_get_seo_scores( $inserted_posts, $taxonomy_filter, $expecte [ 'slug' => 'test-category', ], - ] + ], ); $term_id = (int) $term->term_id; @@ -84,7 +84,7 @@ public function test_get_seo_scores( $inserted_posts, $taxonomy_filter, $expecte 'post_type' => 'blog-post', 'post_category' => ( $post['custom_category'] ) ? [ $term_id ] : [ 1 ], 'meta_input' => $meta_input, - ] + ], ); } diff --git a/tests/WP/Dashboard/User_Interface/SEO_Scores/Invalid_Term_Test.php b/tests/WP/Dashboard/User_Interface/SEO_Scores/Invalid_Term_Test.php index 0a423b2a20d..cd7854f233f 100644 --- a/tests/WP/Dashboard/User_Interface/SEO_Scores/Invalid_Term_Test.php +++ b/tests/WP/Dashboard/User_Interface/SEO_Scores/Invalid_Term_Test.php @@ -26,7 +26,7 @@ public function test_get_seo_scores_with_invalid_term() { 'post_tag', [ 'slug' => 'test-tag', - ] + ], ); $request = new WP_REST_Request( 'GET', '/yoast/v1/seo_scores' ); diff --git a/tests/WP/Doubles/Admin/Gutenberg_Compatibility_Double.php b/tests/WP/Doubles/Admin/Gutenberg_Compatibility_Double.php index 74005e4b707..d33abad3ad4 100644 --- a/tests/WP/Doubles/Admin/Gutenberg_Compatibility_Double.php +++ b/tests/WP/Doubles/Admin/Gutenberg_Compatibility_Double.php @@ -17,9 +17,7 @@ class Gutenberg_Compatibility_Double extends WPSEO_Gutenberg_Compatibility { * @return void */ public function set_installed_gutenberg_version( $version = null ) { - if ( $version === null ) { - $version = $this->detect_installed_gutenberg_version(); - } + $version ??= $this->detect_installed_gutenberg_version(); $this->current_version = $version; } diff --git a/tests/WP/Frontend/Front_End_Integration_Test.php b/tests/WP/Frontend/Front_End_Integration_Test.php index eb9468363ff..7a3020b69c6 100644 --- a/tests/WP/Frontend/Front_End_Integration_Test.php +++ b/tests/WP/Frontend/Front_End_Integration_Test.php @@ -99,7 +99,7 @@ public function set_up(): void { $this->helpers, $this->replace_vars, $this->indexable_repository, - $this->permalink_helper + $this->permalink_helper, ); } diff --git a/tests/WP/Frontend/Image_Utils_Test.php b/tests/WP/Frontend/Image_Utils_Test.php index c100a58635c..9afa54f7834 100644 --- a/tests/WP/Frontend/Image_Utils_Test.php +++ b/tests/WP/Frontend/Image_Utils_Test.php @@ -25,7 +25,7 @@ public function test_get_full_image() { [ 'width' => 1000, 'height' => 1000, - ] + ], ); $this->assertEquals( @@ -37,10 +37,10 @@ public function test_get_full_image() { 'size' => 'full', 'id' => $attachment, 'alt' => '', - 'pixels' => 1000000, + 'pixels' => 1_000_000, 'type' => '', ], - WPSEO_Image_Utils::get_image( $attachment, 'full' ) + WPSEO_Image_Utils::get_image( $attachment, 'full' ), ); } @@ -59,7 +59,7 @@ public function test_get_medium_image() { [ 'width' => 1000, 'height' => 1000, - ] + ], ); $this->assertFalse( WPSEO_Image_Utils::get_image( $attachment, 'medium' ) ); @@ -105,7 +105,7 @@ public function test_get_data( $image, $expected, $attachment_id, $message ) { $this->assertEquals( $expected, WPSEO_Image_Utils::get_data( $image, $attachment_id ), - $message + $message, ); } diff --git a/tests/WP/Functions_Test.php b/tests/WP/Functions_Test.php index f1dc66419a8..c1a5c5f124b 100644 --- a/tests/WP/Functions_Test.php +++ b/tests/WP/Functions_Test.php @@ -21,7 +21,7 @@ public function test_wpseo_replace_vars() { [ 'user_login' => 'User_Login', 'display_name' => 'User_Nicename', - ] + ], ); // Create post. @@ -32,7 +32,7 @@ public function test_wpseo_replace_vars() { 'post_excerpt' => 'Post_Excerpt', 'post_author' => $user_id, 'post_date' => \date( 'Y-m-d H:i:s', \strtotime( '2000-01-01 2:30:00' ) ), - ] + ], ); // Get post. @@ -74,7 +74,7 @@ public function test_wpseo_replace_vars_excerpt( $post_data, $locale, $expected, 'locale', static function () use ( $locale ) { return $locale; - } + }, ); $post = null; diff --git a/tests/WP/General/User_Interface/Set_Opt_In_Seen_Test.php b/tests/WP/General/User_Interface/Set_Opt_In_Seen_Test.php index 1120307d289..aa2d00cd397 100644 --- a/tests/WP/General/User_Interface/Set_Opt_In_Seen_Test.php +++ b/tests/WP/General/User_Interface/Set_Opt_In_Seen_Test.php @@ -35,7 +35,7 @@ static function () { $capability_helper = new Capability_Helper(); $opt_in_route = new Opt_In_Route( $user_helper, $capability_helper ); $opt_in_route->register_routes(); - } + }, ); // Trigger the rest_api_init action to register routes. diff --git a/tests/WP/Generators/Schema/Organization_Test.php b/tests/WP/Generators/Schema/Organization_Test.php index 665e8bd1876..628859d6dd3 100644 --- a/tests/WP/Generators/Schema/Organization_Test.php +++ b/tests/WP/Generators/Schema/Organization_Test.php @@ -47,13 +47,13 @@ public function set_up() { \YoastSEO()->helpers->post_type, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), \YoastSEO()->helpers->meta, - \YoastSEO()->helpers->permalink + \YoastSEO()->helpers->permalink, ); $indexable_post_builder->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); $post_type = 'my-custom-post-type'; @@ -64,7 +64,7 @@ public function set_up() { 'has_archive' => true, 'description' => 'a cool post type', 'label' => $post_type, - ] + ], ); $post = [ @@ -83,7 +83,7 @@ public function set_up() { \YoastSEO()->helpers->current_page, \YoastSEO()->classes->get( Indexable_Repository::class ), \YoastSEO()->classes->get( Meta_Tags_Context::class ), - \YoastSEO()->classes->get( Presentation_Memoizer::class ) + \YoastSEO()->classes->get( Presentation_Memoizer::class ), ); $this->context = $meta_tags_context_memoizer->get( $built_indexable, 'page' ); } diff --git a/tests/WP/Generators/Schema/Person_Test.php b/tests/WP/Generators/Schema/Person_Test.php index 3f56f3a8688..066422b1fca 100644 --- a/tests/WP/Generators/Schema/Person_Test.php +++ b/tests/WP/Generators/Schema/Person_Test.php @@ -47,13 +47,13 @@ public function set_up() { \YoastSEO()->helpers->post_type, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), \YoastSEO()->helpers->meta, - \YoastSEO()->helpers->permalink + \YoastSEO()->helpers->permalink, ); $indexable_post_builder->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); $post_type = 'my-custom-post-type'; @@ -64,7 +64,7 @@ public function set_up() { 'has_archive' => true, 'description' => 'a cool post type', 'label' => $post_type, - ] + ], ); $post = [ @@ -83,7 +83,7 @@ public function set_up() { \YoastSEO()->helpers->current_page, \YoastSEO()->classes->get( Indexable_Repository::class ), \YoastSEO()->classes->get( Meta_Tags_Context::class ), - \YoastSEO()->classes->get( Presentation_Memoizer::class ) + \YoastSEO()->classes->get( Presentation_Memoizer::class ), ); $this->context = $meta_tags_context_memoizer->get( $built_indexable, 'page' ); } diff --git a/tests/WP/Generators/Schema/WebPage_Test.php b/tests/WP/Generators/Schema/WebPage_Test.php index 5af98027a43..75a12f1179e 100644 --- a/tests/WP/Generators/Schema/WebPage_Test.php +++ b/tests/WP/Generators/Schema/WebPage_Test.php @@ -59,14 +59,14 @@ public function set_up() { $this->indexable_system_page_builder = new Indexable_System_Page_Builder( \YoastSEO()->helpers->options, - \YoastSEO()->classes->get( Indexable_Builder_Versions::class ) + \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), ); $this->meta_tags_context_memoizer = new Meta_Tags_Context_Memoizer( \YoastSEO()->helpers->blocks, \YoastSEO()->helpers->current_page, \YoastSEO()->classes->get( Indexable_Repository::class ), \YoastSEO()->classes->get( Meta_Tags_Context::class ), - \YoastSEO()->classes->get( Presentation_Memoizer::class ) + \YoastSEO()->classes->get( Presentation_Memoizer::class ), ); } diff --git a/tests/WP/Helpers/First_Time_Configuration_Notice_Helper_Test.php b/tests/WP/Helpers/First_Time_Configuration_Notice_Helper_Test.php index 56fb1fe1701..1cb3b4374ab 100644 --- a/tests/WP/Helpers/First_Time_Configuration_Notice_Helper_Test.php +++ b/tests/WP/Helpers/First_Time_Configuration_Notice_Helper_Test.php @@ -67,14 +67,14 @@ public function set_up(): void { public function test_construct() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); $this->assertInstanceOf( Indexing_Helper::class, - $this->getPropertyValue( $this->instance, 'indexing_helper' ) + $this->getPropertyValue( $this->instance, 'indexing_helper' ), ); $this->assertIsBool( - $this->getPropertyValue( $this->instance, 'show_alternate_message' ) + $this->getPropertyValue( $this->instance, 'show_alternate_message' ), ); } diff --git a/tests/WP/Helpers/Get_Attachment_By_Url_Image_Helper_Test.php b/tests/WP/Helpers/Get_Attachment_By_Url_Image_Helper_Test.php index 98a43e3d1fc..ad56e62b1bb 100644 --- a/tests/WP/Helpers/Get_Attachment_By_Url_Image_Helper_Test.php +++ b/tests/WP/Helpers/Get_Attachment_By_Url_Image_Helper_Test.php @@ -45,7 +45,7 @@ public function set_up(): void { 'target_post_id' => '112', 'target_indexable_id' => '344', 'id' => '113', - ] + ], ); } diff --git a/tests/WP/Inc/Admin_Bar_Menu_Test.php b/tests/WP/Inc/Admin_Bar_Menu_Test.php index f4717f8415f..d285da81e24 100644 --- a/tests/WP/Inc/Admin_Bar_Menu_Test.php +++ b/tests/WP/Inc/Admin_Bar_Menu_Test.php @@ -269,8 +269,8 @@ public function test_meets_requirements() { $first_result = $admin_bar_menu->meets_requirements(); $this->assertFalse( $first_result ); - \add_filter( 'option_wpseo', [ $this, 'filter_enable_admin_bar_menu_true' ], 10000 ); - \add_filter( 'default_option_wpseo', [ $this, 'filter_enable_admin_bar_menu_true' ], 10000 ); + \add_filter( 'option_wpseo', [ $this, 'filter_enable_admin_bar_menu_true' ], 10_000 ); + \add_filter( 'default_option_wpseo', [ $this, 'filter_enable_admin_bar_menu_true' ], 10_000 ); WPSEO_Options::clear_cache(); $second_result = $admin_bar_menu->meets_requirements(); diff --git a/tests/WP/Inc/Meta_Test.php b/tests/WP/Inc/Meta_Test.php index 9875afb758c..10cd3a3c78e 100644 --- a/tests/WP/Inc/Meta_Test.php +++ b/tests/WP/Inc/Meta_Test.php @@ -288,11 +288,11 @@ public function test_validate_meta_robots_adv() { // String should be cleaned. $this->assertEquals( 'noarchive,nosnippet', - WPSEO_Meta::validate_meta_robots_adv( 'noarchive, nosnippet' ) + WPSEO_Meta::validate_meta_robots_adv( 'noarchive, nosnippet' ), ); $this->assertEquals( 'noarchive,nosnippet', - WPSEO_Meta::validate_meta_robots_adv( [ 'noarchive', 'nosnippet' ] ) + WPSEO_Meta::validate_meta_robots_adv( [ 'noarchive', 'nosnippet' ] ), ); } diff --git a/tests/WP/Inc/MyYoast_Api_Request_Test.php b/tests/WP/Inc/MyYoast_Api_Request_Test.php index 01121888a7f..4187ed1f84e 100644 --- a/tests/WP/Inc/MyYoast_Api_Request_Test.php +++ b/tests/WP/Inc/MyYoast_Api_Request_Test.php @@ -206,7 +206,7 @@ public function test_enrich_request_arguments() { ->willReturn( [ 'This is' => 'the request body', - ] + ], ); $instance @@ -215,7 +215,7 @@ public function test_enrich_request_arguments() { ->willReturn( [ 'yoast-seo-wordpress-premium' => '10.0', - ] + ], ); $this->assertEquals( @@ -227,7 +227,7 @@ public function test_enrich_request_arguments() { 'yoast-seo-wordpress-premium-version' => '10.0', ], ], - $instance->enrich_request_arguments( [] ) + $instance->enrich_request_arguments( [] ), ); } @@ -256,7 +256,7 @@ public function test_enrich_request_arguments_with_empty_request_body() { ->willReturn( [ 'yoast-seo-wordpress-premium' => '10.0', - ] + ], ); $this->assertEquals( @@ -265,7 +265,7 @@ public function test_enrich_request_arguments_with_empty_request_body() { 'yoast-seo-wordpress-premium-version' => '10.0', ], ], - $instance->enrich_request_arguments( [] ) + $instance->enrich_request_arguments( [] ), ); } diff --git a/tests/WP/Inc/Options/Taxonomy_Meta_Test.php b/tests/WP/Inc/Options/Taxonomy_Meta_Test.php index 6983edb2849..de37c0ee50f 100644 --- a/tests/WP/Inc/Options/Taxonomy_Meta_Test.php +++ b/tests/WP/Inc/Options/Taxonomy_Meta_Test.php @@ -35,7 +35,7 @@ public function test_get_meta_without_term_when_taxonomy_is_missing() { ->create_and_get( [ 'taxonomy' => null, - ] + ], ); $this->assertFalse( WPSEO_Taxonomy_Meta::get_meta_without_term( 'meta_field' ) ); @@ -54,7 +54,7 @@ public function test_get_meta_with_valid_term() { ->create_and_get( [ 'taxonomy' => 'category', - ] + ], ); $this->assertEquals( '', WPSEO_Taxonomy_Meta::get_meta_without_term( 'meta_field' ) ); @@ -87,7 +87,7 @@ public function test_validate_term_meta_data() { 'keyword' => '\\', 'score' => 'bad', ], - ] + ], ), 'wpseo_keywordsynonyms' => WPSEO_Utils::format_json_encode( [ '""TESTING""', '""""' ] ), 'wpseo_focuskw' => '"double quotes" and \backslashes\.', @@ -124,7 +124,7 @@ public function test_validation_of_term_meta_data() { 'keyword' => '\\', 'score' => 'bad', ], - ] + ], ), 'wpseo_keywordsynonyms' => WPSEO_Utils::format_json_encode( [ '""TESTING""', '""""' ] ), 'wpseo_focuskw' => '"double quotes" and \backslashes\.', @@ -148,7 +148,7 @@ public function test_validation_of_term_meta_data() { 'keyword' => '\\', 'score' => 'bad', ], - ] + ], ), 'wpseo_keywordsynonyms' => WPSEO_Utils::format_json_encode( [ '""TESTING""', '""""' ] ), 'wpseo_focuskw' => ' "double quotes" `><>`<`and \backslashes\. ', diff --git a/tests/WP/Inc/Post_Type_Test.php b/tests/WP/Inc/Post_Type_Test.php index 7be85137b4f..81f765596d6 100644 --- a/tests/WP/Inc/Post_Type_Test.php +++ b/tests/WP/Inc/Post_Type_Test.php @@ -64,7 +64,7 @@ public function test_get_accessible_post_types_with_a_custom_post_type_that_is_n [ 'public' => true, 'publicly_queryable' => false, - ] + ], ); $this->assertNotContains( 'hidden-post-type', WPSEO_Post_Type::get_accessible_post_types() ); @@ -188,8 +188,8 @@ public function test_filter_attachment_post_type() { [ 'post' => 'post', 'attachment' => 'attachment', - ] - ) + ], + ), ); } @@ -222,7 +222,7 @@ public function test_rest_enabled_post_types() { [ 'public' => true, 'show_in_rest' => true, - ] + ], ); $this->assertTrue( WPSEO_Post_Type::is_rest_enabled( 'custom-post-type-api' ) ); diff --git a/tests/WP/Inc/Rank_Test.php b/tests/WP/Inc/Rank_Test.php index c0b4e23d66a..676d80528bb 100644 --- a/tests/WP/Inc/Rank_Test.php +++ b/tests/WP/Inc/Rank_Test.php @@ -30,7 +30,7 @@ public function test_get_rank() { * @return void */ public function test_constructor() { - $rank_non_existant = new WPSEO_Rank( 100000 ); + $rank_non_existant = new WPSEO_Rank( 100_000 ); $this->assertEquals( WPSEO_Rank::BAD, $rank_non_existant->get_rank() ); } diff --git a/tests/WP/Inc/Upgrade_Test.php b/tests/WP/Inc/Upgrade_Test.php index 0f8940f90d4..dfd3a4ec700 100644 --- a/tests/WP/Inc/Upgrade_Test.php +++ b/tests/WP/Inc/Upgrade_Test.php @@ -259,8 +259,8 @@ public function test_upgrade_36() { FROM %i WHERE option_name LIKE %s AND autoload IN ('on', 'yes')", - [ $wpdb->options, 'wpseo_sitemap_%' ] - ) + [ $wpdb->options, 'wpseo_sitemap_%' ], + ), ); $number_of_sitemap_options_no_autoload = $wpdb->query( @@ -269,8 +269,8 @@ public function test_upgrade_36() { FROM %i WHERE option_name LIKE %s AND autoload IN ('off', 'no')", - [ $wpdb->options, 'wpseo_sitemap_%' ] - ) + [ $wpdb->options, 'wpseo_sitemap_%' ], + ), ); $this->assertEquals( 0, $number_of_sitemap_options ); $this->assertEquals( 1, $number_of_sitemap_options_no_autoload ); @@ -288,13 +288,13 @@ public function test_upgrade_49() { [ 'user_login' => 'User_Login', 'display_name' => 'User_Nicename', - ] + ], ); $other_user_id = $this->factory->user->create( [ 'user_login' => 'Other_User_Login', 'display_name' => 'Other_User_Nicename', - ] + ], ); $notifications = [ @@ -371,8 +371,8 @@ public function test_upgrade_50() { 'SELECT * FROM %i WHERE meta_key = "_yst_content_links_processed"', - [ $wpdb->postmeta ] - ) + [ $wpdb->postmeta ], + ), ); $this->assertEquals( 0, $number_of_rows ); @@ -398,8 +398,8 @@ public function test_upgrade_90() { 'SELECT * FROM %i WHERE option_name LIKE %s', - [ $wpdb->options, 'wpseo_sitemap_%' ] - ) + [ $wpdb->options, 'wpseo_sitemap_%' ], + ), ); $this->assertEquals( 0, $number_of_sitemap_options ); @@ -429,7 +429,7 @@ public function test_upgrade_125() { 'id' => 'wpseo-dismiss-wordpress-upgrade', 'capabilities' => 'wpseo_manage_options', 'priority' => 0.8, - ] + ], ); $center = Yoast_Notification_Center::get(); @@ -445,8 +445,8 @@ public function test_upgrade_125() { 'SELECT * FROM %i WHERE meta_key = %s', - [ $wpdb->usermeta, 'wp_yoast_promo_hide_premium_upsell_admin_block' ] - ) + [ $wpdb->usermeta, 'wp_yoast_promo_hide_premium_upsell_admin_block' ], + ), ); $this->assertEquals( 0, $number_of_rows ); @@ -472,13 +472,13 @@ public function test_clean_up_private_taxonomies_for_141() { $term_builder = new Indexable_Term_Builder( \YoastSEO()->helpers->taxonomy, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), - \YoastSEO()->helpers->post + \YoastSEO()->helpers->post, ); $term_builder->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); $indexable = new Indexable(); @@ -493,8 +493,8 @@ public function test_clean_up_private_taxonomies_for_141() { $wpdb->query( $wpdb->prepare( 'UPDATE %i SET is_public = false WHERE object_id = %d', - [ $this->indexables_table, $result->object_id ] - ) + [ $this->indexables_table, $result->object_id ], + ), ); $instance = $this->get_instance(); @@ -505,8 +505,8 @@ public function test_clean_up_private_taxonomies_for_141() { "SELECT id FROM %i WHERE object_type = 'term' AND object_sub_type = %s", - [ $this->indexables_table, $taxonomy ] - ) + [ $this->indexables_table, $taxonomy ], + ), ); $this->assertEmpty( $private_taxonomy_indexables ); @@ -532,8 +532,8 @@ public function test_upgrade_74() { 'SELECT * FROM %i WHERE option_name LIKE %s', - [ $wpdb->options, 'wpseo_sitemap%validator%' ] - ) + [ $wpdb->options, 'wpseo_sitemap%validator%' ], + ), ); $this->assertEquals( 0, $number_of_sitemap_validators ); @@ -556,13 +556,13 @@ public function test_remove_indexable_rows_for_non_public_post_types() { \YoastSEO()->helpers->post_type, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), \YoastSEO()->helpers->meta, - \YoastSEO()->helpers->permalink + \YoastSEO()->helpers->permalink, ); $post_builder->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); $indexable = new Indexable(); @@ -576,16 +576,16 @@ public function test_remove_indexable_rows_for_non_public_post_types() { "UPDATE %i SET object_sub_type = 'attachment' WHERE object_id = %s", - [ $this->indexables_table, $post_id ] - ) + [ $this->indexables_table, $post_id ], + ), ); $indexables_for_non_public_posts = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM %i WHERE object_id = %s', - [ $this->indexables_table, $post_id ] - ) + [ $this->indexables_table, $post_id ], + ), ); $instance = $this->get_instance(); $instance->remove_indexable_rows_for_non_public_post_types(); @@ -595,8 +595,8 @@ public function test_remove_indexable_rows_for_non_public_post_types() { 'SELECT * FROM %i WHERE object_id = %s', - [ $this->indexables_table, $post_id ] - ) + [ $this->indexables_table, $post_id ], + ), ); $this->assertEmpty( $indexables_for_non_public_posts ); @@ -619,13 +619,13 @@ public function test_remove_indexable_rows_for_non_public_post_types_when_no_pub \YoastSEO()->helpers->post_type, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), \YoastSEO()->helpers->meta, - \YoastSEO()->helpers->permalink + \YoastSEO()->helpers->permalink, ); $post_builder->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); $indexable = new Indexable(); @@ -643,8 +643,8 @@ public function test_remove_indexable_rows_for_non_public_post_types_when_no_pub 'SELECT * FROM %i WHERE object_id = %s', - [ $this->indexables_table, $post_id ] - ) + [ $this->indexables_table, $post_id ], + ), ); $this->assertEmpty( $indexables_for_non_public_posts ); @@ -669,13 +669,13 @@ public function test_remove_indexable_rows_for_non_public_taxonomies() { $term_builder = new Indexable_Term_Builder( \YoastSEO()->helpers->taxonomy, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), - \YoastSEO()->helpers->post + \YoastSEO()->helpers->post, ); $term_builder->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); $indexable = new Indexable(); @@ -693,8 +693,8 @@ public function test_remove_indexable_rows_for_non_public_taxonomies() { SET is_public = false WHERE object_type = 'term' AND object_sub_type = %s", - [ $this->indexables_table, $taxonomy ] - ) + [ $this->indexables_table, $taxonomy ], + ), ); $instance = $this->get_instance(); @@ -705,8 +705,8 @@ public function test_remove_indexable_rows_for_non_public_taxonomies() { "SELECT id FROM %i WHERE object_type = 'term' AND object_sub_type = %s", - [ $this->indexables_table, $taxonomy ] - ) + [ $this->indexables_table, $taxonomy ], + ), ); $this->assertEmpty( $private_taxonomy_indexables ); @@ -731,13 +731,13 @@ public function test_remove_indexable_rows_for_non_public_taxonomies_when_no_pub $term_builder = new Indexable_Term_Builder( \YoastSEO()->helpers->taxonomy, \YoastSEO()->classes->get( Indexable_Builder_Versions::class ), - \YoastSEO()->helpers->post + \YoastSEO()->helpers->post, ); $term_builder->set_social_image_helpers( \YoastSEO()->helpers->image, \YoastSEO()->helpers->open_graph->image, - \YoastSEO()->helpers->twitter->image + \YoastSEO()->helpers->twitter->image, ); $indexable = new Indexable(); @@ -757,8 +757,8 @@ public function test_remove_indexable_rows_for_non_public_taxonomies_when_no_pub SET is_public = false WHERE object_type = 'term' AND object_sub_type = %s", - [ $this->indexables_table, $taxonomy ] - ) + [ $this->indexables_table, $taxonomy ], + ), ); $instance = $this->get_instance(); @@ -769,8 +769,8 @@ public function test_remove_indexable_rows_for_non_public_taxonomies_when_no_pub "SELECT id FROM %i WHERE object_type = 'term' AND object_sub_type = %s", - [ $this->indexables_table, $taxonomy ] - ) + [ $this->indexables_table, $taxonomy ], + ), ); $this->assertEmpty( $private_taxonomy_indexables ); @@ -799,8 +799,8 @@ public function test_deduplicate_unindexed_indexable_rows() { (1, 'user', 'unindexed'), (1, 'user', 'unindexed'), (1, 'user', 'unindexed')", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $instance = $this->get_instance(); @@ -813,8 +813,8 @@ public function test_deduplicate_unindexed_indexable_rows() { WHERE object_id = 1 AND object_type = 'post' AND post_status = 'unindexed'", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $terms = $wpdb->query( $wpdb->prepare( @@ -823,8 +823,8 @@ public function test_deduplicate_unindexed_indexable_rows() { WHERE object_id = 1 AND object_type = 'user' AND post_status = 'unindexed'", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $users = $wpdb->query( $wpdb->prepare( @@ -833,8 +833,8 @@ public function test_deduplicate_unindexed_indexable_rows() { WHERE object_id = 1 AND object_type = 'user' AND post_status = 'unindexed'", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $this->assertEquals( 1, $posts ); $this->assertEquals( 1, $terms ); @@ -862,8 +862,8 @@ public function test_clean_unindexed_indexable_rows_with_no_object_id() { (1, 'post', 'unindexed'), (2, 'user', 'draft'), (3, 'system-page', 'unindexed')", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $instance = $this->get_instance(); @@ -876,8 +876,8 @@ public function test_clean_unindexed_indexable_rows_with_no_object_id() { WHERE object_id IS NULL AND object_type IN ( 'post', 'term', 'user' ) AND post_status = 'unindexed'", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $this->assertEquals( 0, $null_ids ); @@ -900,8 +900,8 @@ public function test_remove_indexable_rows_for_disabled_authors_archive() { (1, 'user', 'publish'), (2, 'user', 'publish'), (3, 'user', 'publish')", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $options_helper->set( 'disable-author', true ); @@ -914,8 +914,8 @@ public function test_remove_indexable_rows_for_disabled_authors_archive() { "SELECT * FROM %i WHERE object_type = 'user'", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $this->assertEquals( 0, $user_indexables ); @@ -948,8 +948,8 @@ public function test_get_indexable_deduplication_query_for_type() { (3, 'post', 'unindexed'), (3, 'post', 'unindexed'), (3, 'term', 'publish')", - [ $this->indexables_table ] - ) + [ $this->indexables_table ], + ), ); $duplicates = $wpdb->get_results( @@ -969,9 +969,9 @@ public function test_get_indexable_deduplication_query_for_type() { object_type HAVING count(*) > 1", - [ $this->indexables_table ] + [ $this->indexables_table ], ), - \ARRAY_A + \ARRAY_A, ); $posts_ids = \array_column( @@ -979,18 +979,18 @@ public function test_get_indexable_deduplication_query_for_type() { $duplicates, static function ( $duplicate ) { return $duplicate['object_type'] === 'post'; - } + }, ), - 'newest_id' + 'newest_id', ); $terms_ids = \array_column( \array_filter( $duplicates, static function ( $duplicate ) { return $duplicate['object_type'] === 'term'; - } + }, ), - 'newest_id' + 'newest_id', ); $users_ids = \array_column( @@ -998,9 +998,9 @@ static function ( $duplicate ) { $duplicates, static function ( $duplicate ) { return $duplicate['object_type'] === 'user'; - } + }, ), - 'newest_id' + 'newest_id', ); $instance = $this->get_instance(); $posts_query = $instance->get_indexable_deduplication_query_for_type( 'post', $duplicates, $wpdb ); @@ -1067,7 +1067,7 @@ private function set_option_in_database( $option_name, $option_value ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- Reason: There's no security risk, because users don't interact with tests. 'option_value' => \serialize( $option_value ), ], - [ 'option_name' => $option_name ] + [ 'option_name' => $option_name ], ); } } diff --git a/tests/WP/Llms_Txt/Application/Available_Posts/Available_Posts_Repository_Test.php b/tests/WP/Llms_Txt/Application/Available_Posts/Available_Posts_Repository_Test.php index b5abbb1178e..b78500f89d9 100644 --- a/tests/WP/Llms_Txt/Application/Available_Posts/Available_Posts_Repository_Test.php +++ b/tests/WP/Llms_Txt/Application/Available_Posts/Available_Posts_Repository_Test.php @@ -121,7 +121,7 @@ private function create_pages( $number_of_pages ) { 'post_title' => 'Test Page ' . $i, 'post_type' => 'page', 'post_status' => 'publish', - ] + ], ); } @@ -155,7 +155,7 @@ private function sets_modification_dates( $pages_indexes_sorted_by_desc_modifica 'post_modified' => $date, 'post_modified_gmt' => $date, ], - [ 'ID' => $id_to_update ] + [ 'ID' => $id_to_update ], ); // Clean cache because of direct database tweaks above. diff --git a/tests/WP/Llms_Txt/Infrastructure/Automatic_Post_Collection_Test.php b/tests/WP/Llms_Txt/Infrastructure/Automatic_Post_Collection_Test.php index 57758c95d26..55505bc9a98 100644 --- a/tests/WP/Llms_Txt/Infrastructure/Automatic_Post_Collection_Test.php +++ b/tests/WP/Llms_Txt/Infrastructure/Automatic_Post_Collection_Test.php @@ -51,7 +51,7 @@ public function set_up() { \YoastSEO()->helpers->options, \YoastSEO()->classes->get( Indexable_Repository::class ), \YoastSEO()->meta, - \YoastSEO()->helpers->indexable + \YoastSEO()->helpers->indexable, ); $this->indexable_post_watcher = \YoastSEO()->classes->get( Indexable_Post_Watcher::class ); @@ -129,7 +129,7 @@ private function create_posts( $number_of_posts, $post_type, $posts_created_at ) 'post_type' => $post_type, 'post_status' => 'publish', 'post_date' => \gmdate( 'Y-m-d H:i:s', \strtotime( $posts_created_at ) ), - ] + ], ); } @@ -152,7 +152,7 @@ private function sets_cornerstone_posts( $cornerstone_posts_indexes, $post_ids ) 'meta_input' => [ '_yoast_wpseo_is_cornerstone' => '1', ], - ] + ], ); } } @@ -182,7 +182,7 @@ private function sets_modification_dates( $posts_indexes_sorted_by_desc_modifica 'post_modified' => \get_date_from_gmt( \gmdate( 'Y-m-d H:i:s', ( $now - $counter ) ) ), 'post_modified_gmt' => \get_date_from_gmt( \gmdate( 'Y-m-d H:i:s', ( $now - $counter ) ) ), ], - [ 'ID' => $id_to_update ] + [ 'ID' => $id_to_update ], ); // Clean cache because of direct database tweaks above. diff --git a/tests/WP/Notifications/Yoast_Notification_Center_Test.php b/tests/WP/Notifications/Yoast_Notification_Center_Test.php index 0b7b73b38b8..3087e2268a4 100644 --- a/tests/WP/Notifications/Yoast_Notification_Center_Test.php +++ b/tests/WP/Notifications/Yoast_Notification_Center_Test.php @@ -214,7 +214,7 @@ public function test_update_storage() { $notification = new Yoast_Notification( $message, - $options + $options, ); $subject = $this->get_notification_center(); @@ -499,7 +499,7 @@ public function test_update_nonce_on_re_add_notification() { [ 'nonce' => $old_nonce, 'id' => 'test', - ] + ], ); $new = new Yoast_Notification( 'new', [ 'id' => 'test' ] ); @@ -827,7 +827,7 @@ public function test_remove_notification_by_id_when_notification_is_found() { ->expects( $this->once() ) ->method( 'get_notification_by_id' ) ->willReturn( - new Yoast_Notification( 'message', [ 'id' => 'this-id-exists' ] ) + new Yoast_Notification( 'message', [ 'id' => 'this-id-exists' ] ), ); $notification_center->remove_notification_by_id( 'this-id-exists' ); @@ -882,7 +882,7 @@ public function test_add_notifications_for_multiple_users() { [ 'user_id' => $user_1->ID, 'capabilities' => [ 'wpseo_manage_options' ], - ] + ], ); $notification_for_user_2 = new Yoast_Notification( @@ -890,7 +890,7 @@ public function test_add_notifications_for_multiple_users() { [ 'user_id' => $user_2->ID, 'capabilities' => [ 'wpseo_manage_options' ], - ] + ], ); $instance->add_notification( $notification_for_user_1 ); @@ -926,7 +926,7 @@ public function test_add_notifications_only_once_for_user() { 'id' => 'Yoast_Notification_Test', 'user_id' => $user->ID, 'capabilities' => [ 'wpseo_manage_options' ], - ] + ], ); $instance->add_notification( $notification ); @@ -949,11 +949,11 @@ public function get_sample_notifications() { return [ new Yoast_Notification( 'notification', - [ 'id' => 'some_id' ] + [ 'id' => 'some_id' ], ), new Yoast_Notification( 'notification', - [ 'id' => 'another_id' ] + [ 'id' => 'another_id' ], ), ]; } diff --git a/tests/WP/Notifications/Yoast_Notification_Test.php b/tests/WP/Notifications/Yoast_Notification_Test.php index dbcfdaddc8f..16bc59fb4e2 100644 --- a/tests/WP/Notifications/Yoast_Notification_Test.php +++ b/tests/WP/Notifications/Yoast_Notification_Test.php @@ -75,7 +75,7 @@ public function test_set_defaults() { 'yoast_branding' => false, 'resolve_nonce' => '', ], - $test['options'] + $test['options'], ); } @@ -206,7 +206,7 @@ public function test_match_any_pass() { 'foo', ], 'capability_check' => 'any', - ] + ], ); $this->assertTrue( $subject->display_for_current_user() ); @@ -233,7 +233,7 @@ public function test_match_any_fail() { 'foo', ], 'capability_check' => 'any', - ] + ], ); $this->assertFalse( $subject->display_for_current_user() ); @@ -258,7 +258,7 @@ public function test_match_all_pass() { 'foo', ], 'capability_check' => 'all', - ] + ], ); $this->assertTrue( $subject->display_for_current_user() ); @@ -283,7 +283,7 @@ public function test_match_all_fail() { 'foo', ], 'capability_check' => 'all', - ] + ], ); $this->add_cap( 'bla' ); @@ -317,7 +317,7 @@ public function test_invalid_filter_return_values() { [ 'id' => 'id', 'capabilities' => 'not_an_array', - ] + ], ); $this->assertFalse( $subject->display_for_current_user() ); } diff --git a/tests/WP/Repositories/Primary_Term_Repository_Test.php b/tests/WP/Repositories/Primary_Term_Repository_Test.php index 2ee61ce37f4..a656a34345a 100644 --- a/tests/WP/Repositories/Primary_Term_Repository_Test.php +++ b/tests/WP/Repositories/Primary_Term_Repository_Test.php @@ -39,7 +39,7 @@ public function set_up(): void { 'created_at' => '2024-05-22 10:16:42', 'updated_at' => '2024-05-22 10:16:42', 'blog_id' => '1', - ] + ], ); $this->instance = new Primary_Term_Repository(); diff --git a/tests/WP/Repositories/SEO_Links_Repository_Test.php b/tests/WP/Repositories/SEO_Links_Repository_Test.php index ceeddee7ec8..58cc9c5d17b 100644 --- a/tests/WP/Repositories/SEO_Links_Repository_Test.php +++ b/tests/WP/Repositories/SEO_Links_Repository_Test.php @@ -39,7 +39,7 @@ public function set_up(): void { 'target_post_id' => '112', 'target_indexable_id' => '344', 'id' => '113', - ] + ], ); $this->instance = new SEO_Links_Repository(); @@ -104,7 +104,7 @@ public function test_find_all_by_post_id_with_result() { $this->assertContainsOnlyInstancesOf( SEO_Links::class, $result, - 'The result should only contain SEO_Links instances.' + 'The result should only contain SEO_Links instances.', ); $this->assertCount( 1, $result, 'The result should contain 1 items.' ); @@ -131,7 +131,7 @@ public function test_insert_many() { 'type' => 'external', 'indexable_id' => 1, 'post_id' => $post_id, - ] + ], ); $link_2 = $this->instance->query()->create( [ @@ -139,7 +139,7 @@ public function test_insert_many() { 'type' => 'internal', 'indexable_id' => 2, 'post_id' => $post_id, - ] + ], ); $links = [ $link_1, $link_2 ]; @@ -147,7 +147,7 @@ public function test_insert_many() { $this->instance->insert_many( $links ); $result = $wpdb->get_results( - $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoast_seo_links WHERE post_id = %d", $post_id ) + $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoast_seo_links WHERE post_id = %d", $post_id ), ); $this->assertCount( 2, $result, 'The result should contain 2 items.' ); @@ -225,7 +225,7 @@ public function test_find_all_by_target_post_id() { $this->assertContainsOnlyInstancesOf( SEO_Links::class, $result, - 'The result should only contain SEO_Links instances.' + 'The result should only contain SEO_Links instances.', ); $this->assertCount( 1, $result, 'The result should contain one item.' ); @@ -327,7 +327,7 @@ public function test_delete_all_by_post_id( $post_id, $expected_result ) { 'post_id' => '110', 'target_post_id' => '159', 'id' => '223', - ] + ], ); $result = $this->instance->delete_all_by_post_id( $post_id ); @@ -382,7 +382,7 @@ public function test_delete_all_by_post_id_where_indexable_id_null( $post_id, $e 'post_id' => '110', 'target_post_id' => '154', 'id' => '222', - ] + ], ); $wpdb->insert( $wpdb->prefix . 'yoast_seo_links', @@ -393,7 +393,7 @@ public function test_delete_all_by_post_id_where_indexable_id_null( $post_id, $e 'post_id' => '110', 'target_post_id' => '159', 'id' => '229', - ] + ], ); $result = $this->instance->delete_all_by_post_id_where_indexable_id_null( $post_id ); @@ -447,7 +447,7 @@ public function test_delete_all_by_indexable_id( $indexable_id, $expected_result 'post_id' => '110', 'target_post_id' => '154', 'id' => '222', - ] + ], ); $result = $this->instance->delete_all_by_indexable_id( $indexable_id ); @@ -519,7 +519,7 @@ public function test_get_incoming_link_counts_for_post_ids( $post_ids, $expected 'post_id' => '108', 'target_post_id' => '154', 'id' => '222', - ] + ], ); $result = $this->instance->get_incoming_link_counts_for_post_ids( $post_ids ); @@ -569,7 +569,7 @@ public function test_delete_many_by_id( $ids, $expected_result ) { 'post_id' => '108', 'target_post_id' => '154', 'id' => '222', - ] + ], ); $result = $this->instance->delete_many_by_id( $ids ); @@ -653,7 +653,7 @@ public function test_get_incoming_link_counts_for_indexable_ids( $indexable_ids, 'target_post_id' => '154', 'id' => '222', 'target_indexable_id' => '355', - ] + ], ); $result = $this->instance->get_incoming_link_counts_for_indexable_ids( $indexable_ids ); diff --git a/tests/WP/Routes/Indexables_Head_Route_Test.php b/tests/WP/Routes/Indexables_Head_Route_Test.php index 74fbecb4104..2e561ad05b1 100644 --- a/tests/WP/Routes/Indexables_Head_Route_Test.php +++ b/tests/WP/Routes/Indexables_Head_Route_Test.php @@ -47,13 +47,13 @@ public function test_get_head( $url, $valid_head_data ) { $this->assertInstanceOf( WP_REST_Response::class, $response, - 'get_head WP_REST_Response object' + 'get_head WP_REST_Response object', ); $this->assertEquals( $valid_head_data, \is_object( $response->data ) && \property_exists( $response->data, 'html' ) && \property_exists( $response->data, 'json' ), - 'get_head valid data' + 'get_head valid data', ); } diff --git a/tests/WP/Sitemaps/Cache_Test.php b/tests/WP/Sitemaps/Cache_Test.php index 5736c1f20ab..24d7c0822f9 100644 --- a/tests/WP/Sitemaps/Cache_Test.php +++ b/tests/WP/Sitemaps/Cache_Test.php @@ -69,7 +69,7 @@ public function test_transient_cache_data_object() { * to do so ourselves. * As of PHP 7.4, the new serialization using magic methods is used. */ - if ( \PHP_VERSION_ID < 70400 ) { + if ( \PHP_VERSION_ID < 70_400 ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize -- Reason: There's no security risk, because users don't interact with tests. $result = \unserialize( $result ); } @@ -135,7 +135,7 @@ public function test_retrieving_transient_stored_in_php_lt_74() { static function ( $pre_transient ) { $pre_transient = 'C:24:"WPSEO_Sitemap_Cache_Data":107:{a:2:{s:6:"status";s:2:"ok";s:3:"xml";s:61:"this is a wpseo_sitemap_cache_data object stored in PHP < 7.4";}}'; return \maybe_unserialize( $pre_transient ); - } + }, ); $cache = new WPSEO_Sitemaps_Cache(); @@ -184,13 +184,13 @@ public function test_retrieving_transient_stored_in_php_gte_74() { static function ( $pre_transient ) { $pre_transient = 'O:24:"WPSEO_Sitemap_Cache_Data":2:{s:6:"status";s:2:"ok";s:3:"xml";s:62:"this is a wpseo_sitemap_cache_data object stored in PHP >= 7.4";}'; return \maybe_unserialize( $pre_transient ); - } + }, ); $cache = new WPSEO_Sitemaps_Cache(); $result = $cache->get_sitemap_data( $type, $page ); - if ( \PHP_VERSION_ID >= 70400 ) { + if ( \PHP_VERSION_ID >= 70_400 ) { // PHP 7.4+. $this->assertInstanceOf( WPSEO_Sitemap_Cache_Data::class, $result ); $this->assertSame( $sitemap, $result->get_sitemap() ); @@ -279,7 +279,7 @@ public function test_clear_index_also_cleared() { * difference between the two generations we will end up with the same * cache invalidator, failing this test. */ - \usleep( 10000 ); + \usleep( 10_000 ); // Act. WPSEO_Sitemaps_Cache::clear( [ 'page' ] ); @@ -340,7 +340,7 @@ public function test_register_clear_on_option_update() { // Hook will be added on default priority. $has_action = \has_action( 'update_option', - [ WPSEO_Sitemaps_Cache::class, 'clear_on_option_update' ] + [ WPSEO_Sitemaps_Cache::class, 'clear_on_option_update' ], ); $this->assertEquals( 10, $has_action ); } @@ -399,7 +399,7 @@ public function test_clearing_author_sitemap_by_unknown_userid() { */ public function test_clearing_author_sitemap_by_userid() { $user_id = $this->factory->user->create( - [ 'role' => 'administrator' ] + [ 'role' => 'administrator' ], ); $this->assertTrue( WPSEO_Sitemaps_Cache::invalidate_author( $user_id ) ); @@ -414,7 +414,7 @@ public function test_clearing_author_sitemap_by_userid() { */ public function test_clearing_author_sitemap_by_userid_with_subscriber_role() { $user_id = $this->factory->user->create( - [ 'role' => 'subscriber' ] + [ 'role' => 'subscriber' ], ); $this->assertFalse( WPSEO_Sitemaps_Cache::invalidate_author( $user_id ) ); diff --git a/tests/WP/Sitemaps/Cache_Validator_Test.php b/tests/WP/Sitemaps/Cache_Validator_Test.php index b08e6f14ecc..776551e2713 100644 --- a/tests/WP/Sitemaps/Cache_Validator_Test.php +++ b/tests/WP/Sitemaps/Cache_Validator_Test.php @@ -120,7 +120,7 @@ public function test_base_10_to_base_61() { $this->assertEquals( '32', WPSEO_Sitemaps_Cache_Validator::convert_base10_to_base61( 123 ) ); // Check against PHP_INT_MAX on 32-bit systems. - $this->assertEquals( '3y75pX', WPSEO_Sitemaps_Cache_Validator::convert_base10_to_base61( 2147483647 ) ); + $this->assertEquals( '3y75pX', WPSEO_Sitemaps_Cache_Validator::convert_base10_to_base61( 2_147_483_647 ) ); } /** diff --git a/tests/WP/Sitemaps/Image_Parser_Test.php b/tests/WP/Sitemaps/Image_Parser_Test.php index 431361de713..3572c6dc91c 100644 --- a/tests/WP/Sitemaps/Image_Parser_Test.php +++ b/tests/WP/Sitemaps/Image_Parser_Test.php @@ -42,7 +42,7 @@ public function test_get_images() { $content_src = 'http://example.org/content-image.jpg'; $post_id = $this->factory->post->create( - [ 'post_content' => "jibberish" ] + [ 'post_content' => "jibberish" ], ); $images = self::$class_instance->get_images( \get_post( $post_id ) ); diff --git a/tests/WP/Sitemaps/Post_Type_Sitemap_Provider_Test.php b/tests/WP/Sitemaps/Post_Type_Sitemap_Provider_Test.php index c768615f2a2..8044e09ec4e 100644 --- a/tests/WP/Sitemaps/Post_Type_Sitemap_Provider_Test.php +++ b/tests/WP/Sitemaps/Post_Type_Sitemap_Provider_Test.php @@ -121,7 +121,7 @@ public function test_get_index_links_empty_bucket() { // Expect an empty list to be output. $this->expectOutputContains( - 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\r\n" . '' + 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\r\n" . '', ); // Remove the filter. @@ -331,14 +331,14 @@ public function test_password_protected_post() { $this->factory->post->create( [ 'post_password' => 'secret', - ] + ], ); // Expect the protected post should not be added. $this->assertCount( 0, self::$class_instance->get_sitemap_links( 'post', 100, 0 ), - 'Password protected posts should not be in the sitemap' + 'Password protected posts should not be in the sitemap', ); } @@ -357,7 +357,7 @@ public function test_regular_attachment() { $post_id = $this->factory->post->create( [ 'post_password' => '', - ] + ], ); $this->factory->post->create( @@ -365,7 +365,7 @@ public function test_regular_attachment() { 'post_parent' => $post_id, 'post_type' => 'attachment', 'post_status' => 'inherit', - ] + ], ); // Expect the attchment to be in the list. @@ -389,7 +389,7 @@ public function test_password_protected_post_parent_attachment() { $post_id = $this->factory->post->create( [ 'post_password' => 'secret', - ] + ], ); $this->factory->post->create( @@ -397,7 +397,7 @@ public function test_password_protected_post_parent_attachment() { 'post_parent' => $post_id, 'post_type' => 'attachment', 'post_status' => 'inherit', - ] + ], ); // Expect the attachment not to be added to the list. @@ -437,7 +437,7 @@ public function test_get_first_links() { [ 'post_type' => 'page', 'post_status' => 'publish', - ] + ], ); \update_option( 'page_on_front', $post_id ); diff --git a/tests/WP/Sitemaps/Provider_Overlap_Test.php b/tests/WP/Sitemaps/Provider_Overlap_Test.php index 772fc36bdd6..5168adab048 100644 --- a/tests/WP/Sitemaps/Provider_Overlap_Test.php +++ b/tests/WP/Sitemaps/Provider_Overlap_Test.php @@ -81,7 +81,7 @@ public function test_private_taxonomy_author_overlap() { // Expect the author-sitemap to be present in the index. $this->expectOutputContains( - '' . $url . '' + '' . $url . '', ); } @@ -103,7 +103,7 @@ public function test_private_taxonomy_author_overlap_author_in_sitemap() { // Expect the author-sitemap to be present in the index. $this->expectOutputContains( - '' . \get_author_posts_url( $user_id ) . '' + '' . \get_author_posts_url( $user_id ) . '', ); } } diff --git a/tests/WP/Sitemaps/Sitemaps_Test.php b/tests/WP/Sitemaps/Sitemaps_Test.php index e2cb0707711..bcb36ad57fa 100644 --- a/tests/WP/Sitemaps/Sitemaps_Test.php +++ b/tests/WP/Sitemaps/Sitemaps_Test.php @@ -125,7 +125,7 @@ static function ( $links ) { 'lastmod' => \date( '1' ), ]; return $links; - } + }, ); self::$class_instance->redirect( $GLOBALS['wp_the_query'] ); diff --git a/tests/WP/Statistics/Statistics_Service_Test.php b/tests/WP/Statistics/Statistics_Service_Test.php index b096965d683..b0e22874481 100644 --- a/tests/WP/Statistics/Statistics_Service_Test.php +++ b/tests/WP/Statistics/Statistics_Service_Test.php @@ -37,7 +37,7 @@ public function test_filter_zero_counts() { 'ok' => 10, 'na' => 0, 'bad' => 0, - ] + ], ); $class_instance = new WPSEO_Statistics_Service( $statistics ); @@ -61,7 +61,7 @@ public function test_seo_score_links() { 'ok' => 10, 'na' => 0, 'bad' => 0, - ] + ], ); $class_instance = new WPSEO_Statistics_Service( $statistics ); @@ -70,7 +70,7 @@ public function test_seo_score_links() { $this->assertEquals( \esc_url( \admin_url( 'edit.php?post_status=publish&post_type=post&seo_filter=ok&author=0' ) ), - $response_data['seo_scores'][0]['link'] + $response_data['seo_scores'][0]['link'], ); } @@ -90,7 +90,7 @@ public function test_admin_seo_score_links() { 'ok' => 10, 'na' => 0, 'bad' => 0, - ] + ], ); $class_instance = new WPSEO_Statistics_Service( $statistics ); @@ -99,7 +99,7 @@ public function test_admin_seo_score_links() { $this->assertEquals( \esc_url( \admin_url( 'edit.php?post_status=publish&post_type=post&seo_filter=ok' ) ), - $response_data['seo_scores'][0]['link'] + $response_data['seo_scores'][0]['link'], ); $user->remove_cap( 'edit_others_posts' ); @@ -118,7 +118,7 @@ public function test_page_counts() { 'ok' => 10, 'na' => 0, 'bad' => 0, - ] + ], ); $class_instance = new WPSEO_Statistics_Service( $statistics ); diff --git a/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php b/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php index c65eb8c3a41..c0f09f55cf8 100644 --- a/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php +++ b/tests/WP/Taxonomy/Taxonomy_Fields_Presenter_Test.php @@ -52,7 +52,7 @@ public function test_display_fields() { 'description' => 'this is a test field', 'options' => '', ], - ] + ], ); $expected = '

    this is a test field

    '; @@ -77,7 +77,7 @@ public function test_display_fields_no_label() { 'description' => 'this is a test field', 'options' => '', ], - ] + ], ); $expected = '

    this is a test field

    '; @@ -102,7 +102,7 @@ public function test_display_fields_no_description() { 'description' => '', 'options' => [], ], - ] + ], ); $this->assertEquals( '', $output ); @@ -128,12 +128,12 @@ public function test_display_fields_select() { ], ], ], - ] + ], ); $this->assertStringContainsString( '', - $output + $output, ); } @@ -157,12 +157,12 @@ public function test_display_fields_checkbox() { ], ], ], - ] + ], ); $this->assertStringContainsString( '', - $output + $output, ); } @@ -182,12 +182,12 @@ public function test_display_fields_hidden() { 'description' => '', 'options' => '', ], - ] + ], ); $this->assertStringContainsString( '', - $output + $output, ); } @@ -207,12 +207,12 @@ public function test_display_fields_with_description() { 'description' => 'description for the field', 'options' => '', ], - ] + ], ); $this->assertStringContainsString( '

    description for the field

    ', - $output + $output, ); } } diff --git a/tests/WP/TestCase.php b/tests/WP/TestCase.php index e8bf4ac3003..b8efead3fd8 100644 --- a/tests/WP/TestCase.php +++ b/tests/WP/TestCase.php @@ -40,7 +40,7 @@ public function set_up() { if ( $this->prereq_plugin_include_failed === true ) { $this->markTestSkipped( - "\n" . 'Couldn\'t include the required plugin file(s): ' . $this->prereq_plugin_basename . '. Skipping all tests in class ' . static::class . '.' + "\n" . 'Couldn\'t include the required plugin file(s): ' . $this->prereq_plugin_basename . '. Skipping all tests in class ' . static::class . '.', ); } } diff --git a/tests/WP/bootstrap.php b/tests/WP/bootstrap.php index 29589b717f4..8284a97d95d 100644 --- a/tests/WP/bootstrap.php +++ b/tests/WP/bootstrap.php @@ -88,7 +88,7 @@ function yoast_seo_create_asset_files_for_tests() { */ static function () { require \dirname( __DIR__, 2 ) . '/wp-seo.php'; - } + }, ); // Overwrite the plugin URL to not include the full path. @@ -114,7 +114,7 @@ static function ( $url, $path, $plugin ) { return $url; }, 10, - 3 + 3, ); // Make sure the tests never register as being in development mode. diff --git a/wp-seo-main.php b/wp-seo-main.php index ea4dfda2cd7..88a9b621bbb 100644 --- a/wp-seo-main.php +++ b/wp-seo-main.php @@ -55,12 +55,10 @@ function wpseo_auto_load( $class_name ) { static $classes = null; - if ( $classes === null ) { - $classes = [ - 'wp_list_table' => ABSPATH . 'wp-admin/includes/class-wp-list-table.php', - 'walker_category' => ABSPATH . 'wp-includes/category-template.php', - ]; - } + $classes ??= [ + 'wp_list_table' => ABSPATH . 'wp-admin/includes/class-wp-list-table.php', + 'walker_category' => ABSPATH . 'wp-includes/category-template.php', + ]; $cn = strtolower( $class_name ); @@ -120,7 +118,7 @@ static function () use ( $yoast_autoloader ) { $yoast_autoloader->unregister(); $yoast_autoloader->register( true ); }, - 1 + 1, ); } @@ -566,7 +564,7 @@ function yoast_wpseo_activation_failed_notice( $message ) { $title = sprintf( /* translators: %s: Yoast SEO. */ esc_html__( '%s activation failed', 'wordpress-seo' ), - 'Yoast SEO' + 'Yoast SEO', ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This function is only called in 3 places that are safe. From 7ea6adbadedcfc1a7e7d740ea0cbf4c4f8027b18 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 12:58:48 +0100 Subject: [PATCH 308/319] Fix cs --- ...egate_Site_Schema_Command_Handler_Test.php | 2 +- .../Constructor_Test.php | 6 ++-- ...e_Site_Schema_Map_Command_Handler_Test.php | 2 +- .../Constructor_Test.php | 8 ++--- .../Application/Cache/Constructor_Test.php | 2 +- .../Application/Cache/Invalidate_All_Test.php | 2 +- .../Application/Cache/Invalidate_Test.php | 2 +- .../Application/Cache/Set_Test.php | 2 +- .../Cache/Xml_Manager/Constructor_Test.php | 2 +- .../Cache/Xml_Manager/Set_Test.php | 2 +- ...stract_Schema_Enhancement_Factory_Test.php | 2 +- .../Constructor_Test.php | 4 +-- .../Default_Filter/Constructor_Test.php | 2 +- .../Filtering/Default_Filter/Filter_Test.php | 4 +-- .../Constructor_Test.php | 2 +- ...ct_Schema_Aggregator_Announcement_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Schema_Map_Builder/Build_Test.php | 2 +- .../Schema_Map_Builder/Constructor_Test.php | 2 +- .../Get_Rest_Route_Test.php | 2 +- .../With_Repository_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Indexable_Count_Collection_Test.php | 2 +- .../Domain/Indexable_Count_Test.php | 10 +++--- .../Domain/Page_Controls_Test.php | 6 ++-- .../Domain/Schema_Piece_Collection_Test.php | 24 +++++++------- .../Domain/Schema_Piece_Test.php | 8 ++--- .../Config/Config_Get_Expiration_Test.php | 32 +++++++++---------- ...t_Elements_Context_Map_Repository_Test.php | 2 +- .../Constructor_Test.php | 2 +- .../Indexable_Repository/Constructor_Test.php | 2 +- ...ract_Indexable_Repository_Factory_Test.php | 2 +- .../Constructor_Test.php | 4 +-- .../Constructor_Test.php | 4 +-- ...act_Schema_Aggregator_Conditional_Test.php | 2 +- .../Constructor_Test.php | 2 +- ...bstract_Schema_Aggregator_Watcher_Test.php | 2 +- .../Check_Schema_Aggregator_Enabled_Test.php | 4 +-- .../Constructor_Test.php | 2 +- .../Register_Hooks_Test.php | 4 +-- ...tract_Edd_Schema_Piece_Repository_Test.php | 2 +- .../Constructor_Test.php | 4 +-- .../Abstract_Schema_Piece_Repository_Test.php | 2 +- .../Constructor_Test.php | 16 +++++----- ...tract_Woo_Schema_Piece_Repository_Test.php | 2 +- .../Constructor_Test.php | 2 +- ..._Listener_Integration_Constructor_Test.php | 8 ++--- ...ables_Update_Listener_Integration_Test.php | 2 +- ...ener_Integration_Get_Conditionals_Test.php | 2 +- ...stener_Integration_Register_Hooks_Test.php | 2 +- ...e_Change_Listener_Integration_TestCase.php | 2 +- ...stener_Integration_Register_Hooks_Test.php | 2 +- ...ract_Site_Schema_Aggregator_Route_Test.php | 2 +- .../Constructor_Test.php | 8 ++--- .../Register_Routes_Test.php | 14 ++++---- ..._Site_Schema_Aggregator_Xml_Route_Test.php | 2 +- .../Register_Routes_Test.php | 2 +- ...chema_Response_Header_Integration_Test.php | 2 +- ...onse_Header_Integration_Construct_Test.php | 2 +- ...Header_Integration_Register_Hooks_Test.php | 2 +- ..._Txt_Integration_Get_Conditionals_Test.php | 2 +- ...ts_Txt_Integration_Register_Hooks_Test.php | 2 +- 62 files changed, 128 insertions(+), 128 deletions(-) diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php index 976b9bed5c6..079eaed3b2d 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Abstract_Aggregate_Site_Schema_Command_Handler_Test.php @@ -60,7 +60,7 @@ protected function set_up() { $this->instance = new Aggregate_Site_Schema_Command_Handler( $this->schema_piece_repository, $this->schema_piece_aggregator, - $this->schema_response_composer + $this->schema_response_composer, ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php index 209870c52c6..168db8d7c9d 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Command_Handler/Constructor_Test.php @@ -24,15 +24,15 @@ final class Constructor_Test extends Abstract_Aggregate_Site_Schema_Command_Hand public function test_constructor() { $this->assertInstanceOf( Schema_Piece_Repository::class, - $this->getPropertyValue( $this->instance, 'schema_piece_repository' ) + $this->getPropertyValue( $this->instance, 'schema_piece_repository' ), ); $this->assertInstanceOf( Schema_Pieces_Aggregator::class, - $this->getPropertyValue( $this->instance, 'schema_piece_aggregator' ) + $this->getPropertyValue( $this->instance, 'schema_piece_aggregator' ), ); $this->assertInstanceOf( Schema_Aggregator_Response_Composer::class, - $this->getPropertyValue( $this->instance, 'schema_response_composer' ) + $this->getPropertyValue( $this->instance, 'schema_response_composer' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php index 0aa5519fd6a..c854b2fbad9 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Abstract_Aggregate_Site_Schema_Map_Command_Handler_Test.php @@ -69,7 +69,7 @@ protected function set_up() { $this->schema_map_repository_factory, $this->schema_map_builder, $this->schema_map_xml_renderer, - $this->indexable_helper + $this->indexable_helper, ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php index 0fa3e0af73b..9c28a390c09 100644 --- a/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Aggregate_Site_Schema_Map_Command_Handler/Constructor_Test.php @@ -25,19 +25,19 @@ final class Constructor_Test extends Abstract_Aggregate_Site_Schema_Map_Command_ public function test_constructor() { $this->assertInstanceOf( Schema_Map_Repository_Factory::class, - $this->getPropertyValue( $this->instance, 'schema_map_repository_factory' ) + $this->getPropertyValue( $this->instance, 'schema_map_repository_factory' ), ); $this->assertInstanceOf( Schema_Map_Builder::class, - $this->getPropertyValue( $this->instance, 'schema_map_builder' ) + $this->getPropertyValue( $this->instance, 'schema_map_builder' ), ); $this->assertInstanceOf( Schema_Map_Xml_Renderer::class, - $this->getPropertyValue( $this->instance, 'schema_map_xml_renderer' ) + $this->getPropertyValue( $this->instance, 'schema_map_xml_renderer' ), ); $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php index 7d7a767fe09..fad3c1dc0e5 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Constructor_Test.php @@ -22,7 +22,7 @@ final class Constructor_Test extends Abstract_Manager_Test { public function test_constructor() { $this->assertInstanceOf( Config::class, - $this->getPropertyValue( $this->instance, 'config' ) + $this->getPropertyValue( $this->instance, 'config' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php index 93efb8d706a..5e83990cf57 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_All_Test.php @@ -30,7 +30,7 @@ public function test_invalidate_all_deletes_all_entries() { ->with( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", '_transient_yoast_schema_aggregator_page_%', - '_transient_timeout_yoast_schema_aggregator_page_%' + '_transient_timeout_yoast_schema_aggregator_page_%', ) ->andReturn( 'PREPARED_QUERY' ); diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php index b9742f798ce..87e647df90f 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Invalidate_Test.php @@ -47,7 +47,7 @@ public function test_invalidate_clears_all_per_page_variations_for_page() { ->with( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", '_transient_yoast_schema_aggregator_page_1_per_%', - '_transient_timeout_yoast_schema_aggregator_page_1_per_%' + '_transient_timeout_yoast_schema_aggregator_page_1_per_%', ) ->andReturn( 'PREPARED_QUERY' ); diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php index e0e138eb143..84bcf4d46b4 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Set_Test.php @@ -132,7 +132,7 @@ public static function set_cache_data_provider() { 'page' => 2, 'per_page' => 50, 'data' => \array_fill( 0, 100, 'large_data' ), - 'expiration' => 21600, + 'expiration' => 21_600, 'expected_key' => 'yoast_schema_aggregator_page_2_per_50_type_post_v1', ]; } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php index 0d8ca947a25..36889c7ce5c 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Constructor_Test.php @@ -22,7 +22,7 @@ final class Constructor_Test extends Abstract_Xml_Manager_Test { public function test_constructor() { $this->assertInstanceOf( Config::class, - $this->getPropertyValue( $this->instance, 'config' ) + $this->getPropertyValue( $this->instance, 'config' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php index bae7fc1b622..29ba68080c3 100644 --- a/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Cache/Xml_Manager/Set_Test.php @@ -105,7 +105,7 @@ public static function set_data_provider() { ]; yield 'Large XML, long expiration' => [ 'data' => \str_repeat( 'large content here', 500 ), - 'expiration' => 21600, + 'expiration' => 21_600, 'expected' => true, ]; yield 'Empty string' => [ diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php index 1610fb56504..225ccd783c4 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Abstract_Schema_Enhancement_Factory_Test.php @@ -47,7 +47,7 @@ protected function set_up() { $this->person_enhancer = Mockery::mock( Person_Schema_Enhancer::class ); $this->instance = new Schema_Enhancement_Factory( $this->article_enhancer, - $this->person_enhancer + $this->person_enhancer, ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php index aef2831ccda..0bdd447f7b9 100644 --- a/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Enhancement/Schema_Enhancement_Factory/Constructor_Test.php @@ -23,11 +23,11 @@ final class Constructor_Test extends Abstract_Schema_Enhancement_Factory_Test { public function test_constructor() { $this->assertInstanceOf( Article_Schema_Enhancer::class, - $this->getPropertyValue( $this->instance, 'article_schema_enhancer' ) + $this->getPropertyValue( $this->instance, 'article_schema_enhancer' ), ); $this->assertInstanceOf( Person_Schema_Enhancer::class, - $this->getPropertyValue( $this->instance, 'person_schema_enhancer' ) + $this->getPropertyValue( $this->instance, 'person_schema_enhancer' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php index 387a56713b6..7137b61de88 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Constructor_Test.php @@ -22,7 +22,7 @@ final class Constructor_Test extends Abstract_Default_Filter_Test { public function test_constructor(): void { $this->assertInstanceOf( Elements_Context_Map_Repository::class, - $this->getPropertyValue( $this->instance, 'elements_context_map_repository' ) + $this->getPropertyValue( $this->instance, 'elements_context_map_repository' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php index 51c60340600..7c5bb8ac895 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Default_Filter/Filter_Test.php @@ -57,7 +57,7 @@ public function test_schema_pieces_filter( array $elements_context_map, array $s static function ( $piece ) { return $piece->get_data(); }, - $result->to_array() + $result->to_array(), ); $this->assertSame( $expected_data, $result_data ); @@ -87,7 +87,7 @@ public function test_schema_piece_properties_filter( array $elements_context_map static function ( $piece ) { return $piece->get_data(); }, - $result->to_array() + $result->to_array(), ); $this->assertCount( 1, $result_data ); diff --git a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php index 1bae4e8ceb9..2b14a021c60 100644 --- a/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Filtering/Schema_Node_Filter/WebSite_Schema_Node_Filter/Constructor_Test.php @@ -23,7 +23,7 @@ public function test_constructor() { $this->assertInstanceOf( WordPress_Current_Site_URL_Provider::class, - $this->getPropertyValue( $this->instance, 'current_site_url_provider' ) + $this->getPropertyValue( $this->instance, 'current_site_url_provider' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php index 0dd8f517fc8..5650d7ffb8f 100644 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Abstract_Schema_Aggregator_Announcement_Test.php @@ -43,7 +43,7 @@ protected function set_up() { $this->current_page_helper = Mockery::mock( Current_Page_Helper::class ); $this->instance = new Schema_Aggregator_Announcement( - $this->current_page_helper + $this->current_page_helper, ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php index 82d20a8215e..06d65fa8aba 100644 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Aggregator_Announcement/Constructor_Test.php @@ -25,7 +25,7 @@ final class Constructor_Test extends Abstract_Schema_Aggregator_Announcement_Tes public function test_constructor(): void { $this->assertInstanceOf( Current_Page_Helper::class, - $this->getPropertyValue( $this->instance, 'current_page_helper' ) + $this->getPropertyValue( $this->instance, 'current_page_helper' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php index 70262099784..dcc66ebb027 100644 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Build_Test.php @@ -51,7 +51,7 @@ public function test_build( array $indexable_counts_data, int $per_page, array $ ->andReturnUsing( static function ( $route ) { return 'https://example.com/wp-json/' . $route; - } + }, ); $result = $this->instance->build( $collection ); diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php index 430329c76b5..0136bbb231f 100644 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Constructor_Test.php @@ -24,7 +24,7 @@ final class Constructor_Test extends Abstract_Schema_Map_Builder_Test { public function test_constructor() { $this->assertInstanceOf( Config::class, - $this->getPropertyValue( $this->instance, 'config' ) + $this->getPropertyValue( $this->instance, 'config' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php index 63b6e4df79b..13fc70b4432 100644 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/Get_Rest_Route_Test.php @@ -35,7 +35,7 @@ public function test_get_rest_route( string $post_type, int $page, string $expec ->andReturnUsing( static function ( $route ) { return 'https://example.com/wp-json/' . $route; - } + }, ); $result = $this->instance->get_rest_route( $post_type, $page ); diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php index 967bf2cdbfe..d4a84a19457 100644 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Builder/With_Repository_Test.php @@ -42,7 +42,7 @@ public function test_with_repository_returns_self() { public function test_with_repository_sets_property() { $this->assertInstanceOf( Schema_Map_Repository_Interface::class, - $this->getPropertyValue( $this->instance, 'schema_map_repository' ) + $this->getPropertyValue( $this->instance, 'schema_map_repository' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php index fdf8d9818f4..07835ca002a 100644 --- a/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Application/Schema_Map/Schema_Map_Xml_Renderer/Constructor_Test.php @@ -24,7 +24,7 @@ final class Constructor_Test extends Abstract_Schema_Map_Xml_Renderer_Test { public function test_constructor() { $this->assertInstanceOf( Schema_Map_Config::class, - $this->getPropertyValue( $this->instance, 'config' ) + $this->getPropertyValue( $this->instance, 'config' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php index d67a1c15321..62bc49ae78a 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Collection_Test.php @@ -27,7 +27,7 @@ public function test_constructor() { $this->assertSame( [], - $this->getPropertyValue( $instance, 'indexable_counts' ) + $this->getPropertyValue( $instance, 'indexable_counts' ), ); } diff --git a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php index 85bbe73d51d..19072fcb1e3 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Indexable_Count_Test.php @@ -27,11 +27,11 @@ public function test_constructor() { $this->assertSame( 'post', - $this->getPropertyValue( $instance, 'post_type' ) + $this->getPropertyValue( $instance, 'post_type' ), ); $this->assertSame( 42, - $this->getPropertyValue( $instance, 'count' ) + $this->getPropertyValue( $instance, 'count' ), ); } @@ -66,8 +66,8 @@ public static function count_data_provider() { 'expected' => 0, ]; yield 'Large count' => [ - 'count' => 999999, - 'expected' => 999999, + 'count' => 999_999, + 'expected' => 999_999, ]; yield 'Small count' => [ 'count' => 1, @@ -160,7 +160,7 @@ public static function constructor_values_data_provider() { ]; yield 'Custom post type with large count' => [ 'post_type' => 'product', - 'count' => 500000, + 'count' => 500_000, ]; yield 'Post type with underscore and count' => [ 'post_type' => 'custom_type', diff --git a/tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php b/tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php index 539d0ab9e32..967b7e01865 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Page_Controls_Test.php @@ -28,15 +28,15 @@ public function test_constructor() { $this->assertSame( 1, - $this->getPropertyValue( $instance, 'page' ) + $this->getPropertyValue( $instance, 'page' ), ); $this->assertSame( 20, - $this->getPropertyValue( $instance, 'page_size' ) + $this->getPropertyValue( $instance, 'page_size' ), ); $this->assertSame( 'post', - $this->getPropertyValue( $instance, 'post_type' ) + $this->getPropertyValue( $instance, 'post_type' ), ); } diff --git a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php index 38744c174c8..9d8ca75b5f6 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Collection_Test.php @@ -27,7 +27,7 @@ public function test_constructor() { $this->assertSame( [], - $this->getPropertyValue( $instance, 'pieces' ) + $this->getPropertyValue( $instance, 'pieces' ), ); } @@ -54,7 +54,7 @@ public function test_add_single_schema_piece() { '@type' => 'Article', 'name' => 'Test Article', ], - 'Article' + 'Article', ); $instance->add( $schema_piece ); @@ -77,21 +77,21 @@ public function test_add_multiple_schema_pieces() { '@type' => 'Article', 'name' => 'Article 1', ], - 'Article' + 'Article', ); $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'John Doe', ], - 'Person' + 'Person', ); $piece3 = new Schema_Piece( [ '@type' => 'Organization', 'name' => 'Yoast', ], - 'Organization' + 'Organization', ); $instance->add( $piece1 ); @@ -117,7 +117,7 @@ public function test_to_array_returns_array() { '@type' => 'WebPage', 'name' => 'Test Page', ], - 'WebPage' + 'WebPage', ); $instance->add( $schema_piece ); @@ -140,28 +140,28 @@ public function test_collection_maintains_order() { '@type' => 'Article', 'headline' => 'Article 1', ], - 'Article' + 'Article', ); $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'Person 1', ], - 'Person' + 'Person', ); $piece3 = new Schema_Piece( [ '@type' => 'Organization', 'name' => 'Org 1', ], - 'Organization' + 'Organization', ); $piece4 = new Schema_Piece( [ '@type' => 'WebPage', 'name' => 'Page 1', ], - 'WebPage' + 'WebPage', ); $instance->add( $piece1 ); @@ -188,14 +188,14 @@ public function test_constructor_with_pieces() { '@type' => 'Article', 'headline' => 'Test Article', ], - 'Article' + 'Article', ); $piece2 = new Schema_Piece( [ '@type' => 'Person', 'name' => 'Test Person', ], - 'Person' + 'Person', ); $instance = new Schema_Piece_Collection( [ $piece1, $piece2 ] ); diff --git a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php index 0fb94637179..407ced3adcb 100644 --- a/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php +++ b/tests/Unit/Schema_Aggregator/Domain/Schema_Piece_Test.php @@ -34,11 +34,11 @@ public function test_constructor_with_string_type() { $this->assertSame( $data, - $this->getPropertyValue( $instance, 'data' ) + $this->getPropertyValue( $instance, 'data' ), ); $this->assertSame( $type, - $this->getPropertyValue( $instance, 'type' ) + $this->getPropertyValue( $instance, 'type' ), ); } @@ -54,11 +54,11 @@ public function test_constructor_with_array_type() { $this->assertSame( $data, - $this->getPropertyValue( $instance, 'data' ) + $this->getPropertyValue( $instance, 'data' ), ); $this->assertSame( $type, - $this->getPropertyValue( $instance, 'type' ) + $this->getPropertyValue( $instance, 'type' ), ); } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php index e8cf93c9842..84eb79f2657 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Config/Config_Get_Expiration_Test.php @@ -46,43 +46,43 @@ public function test_get_expiration( $data, $filtered_ttl, $expected ) { */ public static function get_expiration_data() { yield 'Small data (< 100KB) - shorter cache' => [ - 'data' => self::generate_array_of_size( 50000 ), + 'data' => self::generate_array_of_size( 50_000 ), 'filtered_ttl' => 1800, 'expected' => 1800, ]; yield 'Medium data (100KB - 1MB) - default cache' => [ - 'data' => self::generate_array_of_size( 500000 ), + 'data' => self::generate_array_of_size( 500_000 ), 'filtered_ttl' => 3600, 'expected' => 3600, ]; yield 'Large data (> 1MB) - longer cache' => [ - 'data' => self::generate_array_of_size( 1100000 ), - 'filtered_ttl' => 21600, - 'expected' => 21600, + 'data' => self::generate_array_of_size( 1_100_000 ), + 'filtered_ttl' => 21_600, + 'expected' => 21_600, ]; yield 'Filter returns invalid (zero) - falls back to default' => [ - 'data' => self::generate_array_of_size( 500000 ), + 'data' => self::generate_array_of_size( 500_000 ), 'filtered_ttl' => 0, 'expected' => 3600, ]; yield 'Filter returns invalid (negative) - falls back to default' => [ - 'data' => self::generate_array_of_size( 500000 ), + 'data' => self::generate_array_of_size( 500_000 ), 'filtered_ttl' => -100, 'expected' => 3600, ]; yield 'Filter returns non-integer (string) - falls back to default' => [ - 'data' => self::generate_array_of_size( 500000 ), + 'data' => self::generate_array_of_size( 500_000 ), 'filtered_ttl' => 'invalid', 'expected' => 3600, ]; yield 'Filter returns valid positive integer' => [ - 'data' => self::generate_array_of_size( 50000 ), + 'data' => self::generate_array_of_size( 50_000 ), 'filtered_ttl' => 7200, 'expected' => 7200, ]; @@ -94,33 +94,33 @@ public static function get_expiration_data() { ]; yield 'Data just below small boundary' => [ - 'data' => self::generate_array_of_size( 102399 ), + 'data' => self::generate_array_of_size( 102_399 ), 'filtered_ttl' => 1800, 'expected' => 1800, ]; yield 'Data at small boundary (102400 bytes) - uses default' => [ - 'data' => self::generate_array_of_size( 102400 ), + 'data' => self::generate_array_of_size( 102_400 ), 'filtered_ttl' => 3600, 'expected' => 3600, ]; yield 'Data just above small boundary' => [ - 'data' => self::generate_array_of_size( 102401 ), + 'data' => self::generate_array_of_size( 102_401 ), 'filtered_ttl' => 3600, 'expected' => 3600, ]; yield 'Data just below large boundary' => [ - 'data' => self::generate_array_of_size( 1048575 ), + 'data' => self::generate_array_of_size( 1_048_575 ), 'filtered_ttl' => 3600, 'expected' => 3600, ]; yield 'Data just above large boundary (1048577 bytes) - uses large cache' => [ - 'data' => self::generate_array_of_size( 1048577 ), - 'filtered_ttl' => 21600, - 'expected' => 21600, + 'data' => self::generate_array_of_size( 1_048_577 ), + 'filtered_ttl' => 21_600, + 'expected' => 21_600, ]; } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php index 27ac612a848..b31bc8fa7eb 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Abstract_Elements_Context_Map_Repository_Test.php @@ -42,7 +42,7 @@ protected function set_up() { $this->map_loader = Mockery::mock( Map_Loader_Interface::class ); $this->instance = new Elements_Context_Map_Repository( - $this->map_loader + $this->map_loader, ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php index d2b8b1ebd5a..9d244a54b6d 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Elements_Context_Map_Repository/Constructor_Test.php @@ -24,7 +24,7 @@ final class Constructor_Test extends Abstract_Elements_Context_Map_Repository_Te public function test_constructor(): void { $this->assertInstanceOf( Map_Loader_Interface::class, - $this->getPropertyValue( $this->instance, 'map_loader' ) + $this->getPropertyValue( $this->instance, 'map_loader' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php index e8f6d3e26c4..88e9c6bbd48 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Constructor_Test.php @@ -50,7 +50,7 @@ public function setUp(): void { public function test_constructor(): void { $this->assertInstanceOf( Base_Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php index 87fe6f91354..d3361e1addc 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Abstract_Indexable_Repository_Factory_Test.php @@ -46,7 +46,7 @@ public function setUp(): void { $this->wordpress_query_repository = Mockery::mock( WordPress_Query_Repository::class ); $this->instance = new Indexable_Repository_Factory( $this->indexable_repository, - $this->wordpress_query_repository + $this->wordpress_query_repository, ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php index 480b29a90c9..ebf6b0bcd05 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/Indexable_Repository_Factory/Constructor_Test.php @@ -23,12 +23,12 @@ final class Constructor_Test extends Abstract_Indexable_Repository_Factory_Test public function test_constructor(): void { $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'native_repository' ) + $this->getPropertyValue( $this->instance, 'native_repository' ), ); $this->assertInstanceOf( WordPress_Query_Repository::class, - $this->getPropertyValue( $this->instance, 'wordpress_repository' ) + $this->getPropertyValue( $this->instance, 'wordpress_repository' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php index 7393c2209e8..fcb640efcdb 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository/Constructor_Test.php @@ -59,12 +59,12 @@ public function setUp(): void { public function test_constructor(): void { $this->assertInstanceOf( Indexable_Builder::class, - $this->getPropertyValue( $this->instance, 'indexable_builder' ) + $this->getPropertyValue( $this->instance, 'indexable_builder' ), ); $this->assertInstanceOf( Pure_Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php index 18fb1540ad4..84503a5a069 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Abstract_Schema_Aggregator_Conditional_Test.php @@ -40,7 +40,7 @@ protected function set_up() { $this->options = Mockery::mock( Options_Helper::class ); $this->instance = new Schema_Aggregator_Conditional( - $this->options + $this->options, ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php index 64484fc73d1..d678a7941c2 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Conditional/Constructor_Test.php @@ -22,7 +22,7 @@ final class Constructor_Test extends Abstract_Schema_Aggregator_Conditional_Test public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options' ) + $this->getPropertyValue( $this->instance, 'options' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php index cc84920b0c4..d7c9d9ba8cb 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Abstract_Schema_Aggregator_Watcher_Test.php @@ -40,7 +40,7 @@ protected function set_up() { $this->options_helper = Mockery::mock( Options_Helper::class ); $this->instance = new Schema_Aggregator_Watcher( - $this->options_helper + $this->options_helper, ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php index d5a7fbd8afe..fb2d7924f76 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Check_Schema_Aggregator_Enabled_Test.php @@ -77,7 +77,7 @@ public static function data_check_schema_aggregator_enabled() { 'expected' => false, 'should_check_timestamp' => true, 'should_set_timestamp' => false, - 'current_timestamp' => 1234567890, + 'current_timestamp' => 1_234_567_890, ]; yield 'Returns false when already enabled (no transition)' => [ 'old_value' => [ 'enable_schema_aggregation_endpoint' => true ], @@ -174,7 +174,7 @@ public function test_check_schema_aggregator_enabled_does_not_overwrite_existing ->expects( 'get' ) ->once() ->with( 'schema_aggregation_endpoint_enabled_on' ) - ->andReturn( 1234567890 ); + ->andReturn( 1_234_567_890 ); $this->options_helper ->expects( 'set' ) diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php index 35c65e1b47c..500cab4c45a 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Constructor_Test.php @@ -22,7 +22,7 @@ final class Constructor_Test extends Abstract_Schema_Aggregator_Watcher_Test { public function test_constructor() { $this->assertInstanceOf( Options_Helper::class, - $this->getPropertyValue( $this->instance, 'options_helper' ) + $this->getPropertyValue( $this->instance, 'options_helper' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php index aef05d97e8f..287a02886a6 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Aggregator_Watcher/Register_Hooks_Test.php @@ -24,8 +24,8 @@ public function test_register_hooks() { 10, \has_action( 'update_option_wpseo', - [ $this->instance, 'check_schema_aggregator_enabled' ] - ) + [ $this->instance, 'check_schema_aggregator_enabled' ], + ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php index 008a9cc2612..17c71474bf2 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Abstract_Edd_Schema_Piece_Repository_Test.php @@ -52,7 +52,7 @@ protected function set_up() { $this->instance = new Edd_Schema_Piece_Repository( $this->edd_conditional, - $this->meta + $this->meta, ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php index edb5579130d..1a917827ba1 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Constructor_Test.php @@ -25,12 +25,12 @@ final class Constructor_Test extends Abstract_Edd_Schema_Piece_Repository_Test { public function test_constructor(): void { $this->assertInstanceOf( EDD_Conditional::class, - $this->getPropertyValue( $this->instance, 'edd_conditional' ) + $this->getPropertyValue( $this->instance, 'edd_conditional' ), ); $this->assertInstanceOf( Meta_Surface::class, - $this->getPropertyValue( $this->instance, 'meta' ) + $this->getPropertyValue( $this->instance, 'meta' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php index cfb09bc0ff1..89efdddb6bb 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Abstract_Schema_Piece_Repository_Test.php @@ -112,7 +112,7 @@ protected function set_up() { $this->enhancement_factory, $this->indexable_repository_factory, $this->global_state_adapter, - $this->external_repository + $this->external_repository, ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php index f81ab215cd4..71b321065b6 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Constructor_Test.php @@ -31,37 +31,37 @@ final class Constructor_Test extends Abstract_Schema_Piece_Repository_Test { public function test_constructor(): void { $this->assertInstanceOf( Meta_Tags_Context_Memoizer::class, - $this->getPropertyValue( $this->instance, 'memoizer' ) + $this->getPropertyValue( $this->instance, 'memoizer' ), ); $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); $this->assertInstanceOf( Meta_Tags_Context_Memoizer_Adapter::class, - $this->getPropertyValue( $this->instance, 'adapter' ) + $this->getPropertyValue( $this->instance, 'adapter' ), ); $this->assertInstanceOf( Aggregator_Config::class, - $this->getPropertyValue( $this->instance, 'config' ) + $this->getPropertyValue( $this->instance, 'config' ), ); $this->assertInstanceOf( Schema_Enhancement_Factory::class, - $this->getPropertyValue( $this->instance, 'enhancement_factory' ) + $this->getPropertyValue( $this->instance, 'enhancement_factory' ), ); $this->assertInstanceOf( Indexable_Repository_Factory::class, - $this->getPropertyValue( $this->instance, 'indexable_repository_factory' ) + $this->getPropertyValue( $this->instance, 'indexable_repository_factory' ), ); $this->assertInstanceOf( WordPress_Global_State_Adapter::class, - $this->getPropertyValue( $this->instance, 'global_state_adapter' ) + $this->getPropertyValue( $this->instance, 'global_state_adapter' ), ); $external_repositories = $this->getPropertyValue( $this->instance, 'external_repositories' ); @@ -69,7 +69,7 @@ public function test_constructor(): void { $this->assertCount( 1, $external_repositories ); $this->assertInstanceOf( External_Schema_Piece_Repository_Interface::class, - $external_repositories[0] + $external_repositories[0], ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php index e996f10d3d4..58cb225ca95 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Abstract_Woo_Schema_Piece_Repository_Test.php @@ -42,7 +42,7 @@ protected function set_up() { $this->woocommerce_conditional = Mockery::mock( WooCommerce_Conditional::class ); $this->instance = new Woo_Schema_Piece_Repository( - $this->woocommerce_conditional + $this->woocommerce_conditional, ); } } diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php index 58226a0b374..857880ccd7f 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Constructor_Test.php @@ -24,7 +24,7 @@ final class Constructor_Test extends Abstract_Woo_Schema_Piece_Repository_Test { public function test_constructor(): void { $this->assertInstanceOf( WooCommerce_Conditional::class, - $this->getPropertyValue( $this->instance, 'woocommerce_conditional' ) + $this->getPropertyValue( $this->instance, 'woocommerce_conditional' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php index 85967787e92..4db31ea03ae 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Abstract_Cache_Listener_Integration/Abstract_Cache_Listener_Integration_Constructor_Test.php @@ -71,19 +71,19 @@ public static function get_conditionals(): array { public function test_constructor() { $this->assertInstanceOf( Indexable_Repository::class, - $this->getPropertyValue( $this->instance, 'indexable_repository' ) + $this->getPropertyValue( $this->instance, 'indexable_repository' ), ); $this->assertInstanceOf( Config::class, - $this->getPropertyValue( $this->instance, 'config' ) + $this->getPropertyValue( $this->instance, 'config' ), ); $this->assertInstanceOf( Manager::class, - $this->getPropertyValue( $this->instance, 'manager' ) + $this->getPropertyValue( $this->instance, 'manager' ), ); $this->assertInstanceOf( Xml_Manager::class, - $this->getPropertyValue( $this->instance, 'xml_manager' ) + $this->getPropertyValue( $this->instance, 'xml_manager' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php index 598ac2d59ad..6688b1ded2f 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Abstract_Indexables_Update_Listener_Integration_Test.php @@ -70,7 +70,7 @@ protected function set_up() { $this->indexable_repository, $this->config, $this->manager, - $this->xml_manager + $this->xml_manager, ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php index 3045c6722df..61efc0f1903 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Get_Conditionals_Test.php @@ -26,7 +26,7 @@ final class Indexables_Update_Listener_Integration_Get_Conditionals_Test extends public function test_get_conditionals() { $this->assertEquals( [ Schema_Aggregator_Conditional::class ], - Indexables_Update_Listener_Integration::get_conditionals() + Indexables_Update_Listener_Integration::get_conditionals(), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php index 62cea7f9aea..d995313f22a 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/Indexables_Update_Listener_Integration/Indexables_Update_Listener_Integration_Register_Hooks_Test.php @@ -26,7 +26,7 @@ public function test_register_hooks() { $this->instance->register_hooks(); $this->assertNotFalse( - Monkey\Actions\has( 'wpseo_save_indexable', [ $this->instance, 'reset_cache' ] ) + Monkey\Actions\has( 'wpseo_save_indexable', [ $this->instance, 'reset_cache' ] ), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php index 5c7c809f28d..2f18054af49 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/Abstract_WooCommerce_Product_Type_Change_Listener_Integration_TestCase.php @@ -70,7 +70,7 @@ protected function set_up() { $this->indexable_repository, $this->config, $this->manager, - $this->xml_manager + $this->xml_manager, ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php index e01f4769e96..81e0a596e07 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Cache/WooCommerce_Product_Type_Change_Listener_Integration/WooCommerce_Product_Type_Change_Listener_Integration_Register_Hooks_Test.php @@ -26,7 +26,7 @@ public function test_register_hooks() { $this->instance->register_hooks(); $this->assertNotFalse( - Monkey\Actions\has( 'woocommerce_product_type_changed', [ $this->instance, 'reset_cache' ] ) + Monkey\Actions\has( 'woocommerce_product_type_changed', [ $this->instance, 'reset_cache' ] ), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php index 3c293e2a121..c673281099b 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php @@ -72,7 +72,7 @@ protected function set_up() { $this->config, $this->capability_helper, $this->command_handler, - $this->cache_manager + $this->cache_manager, ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php index 88bf7282b50..73bdd0f53a7 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php @@ -27,22 +27,22 @@ final class Constructor_Test extends Abstract_Site_Schema_Aggregator_Route_Test public function test_constructor(): void { $this->assertInstanceOf( Config::class, - $this->getPropertyValue( $this->instance, 'config' ) + $this->getPropertyValue( $this->instance, 'config' ), ); $this->assertInstanceOf( Capability_Helper::class, - $this->getPropertyValue( $this->instance, 'capability_helper' ) + $this->getPropertyValue( $this->instance, 'capability_helper' ), ); $this->assertInstanceOf( Aggregate_Site_Schema_Command_Handler::class, - $this->getPropertyValue( $this->instance, 'aggregate_site_schema_command_handler' ) + $this->getPropertyValue( $this->instance, 'aggregate_site_schema_command_handler' ), ); $this->assertInstanceOf( Manager::class, - $this->getPropertyValue( $this->instance, 'cache_manager' ) + $this->getPropertyValue( $this->instance, 'cache_manager' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php index 8db4b8393b5..dfe35513af9 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Register_Routes_Test.php @@ -28,7 +28,7 @@ public function test_register_routes() { ->with( 'yoast/v1', Mockery::type( 'string' ), - Mockery::type( 'array' ) + Mockery::type( 'array' ), ); $this->instance->register_routes(); @@ -51,8 +51,8 @@ public function test_register_routes_registers_post_type_route() { static function ( $config ) use ( &$captured_config ) { $captured_config = $config; return true; - } - ) + }, + ), ); Functions\expect( 'register_rest_route' ) @@ -60,7 +60,7 @@ static function ( $config ) use ( &$captured_config ) { ->with( 'yoast/v1', 'schema-aggregator/get-schema/(?P[a-z0-9_-]+)/(?P\d+)', - Mockery::type( 'array' ) + Mockery::type( 'array' ), ); $this->instance->register_routes(); @@ -85,7 +85,7 @@ public function test_register_routes_registers_paginated_route() { ->with( 'yoast/v1', 'schema-aggregator/get-schema/(?P[a-z0-9_-]+)', - Mockery::type( 'array' ) + Mockery::type( 'array' ), ); Functions\expect( 'register_rest_route' ) @@ -97,8 +97,8 @@ public function test_register_routes_registers_paginated_route() { static function ( $config ) use ( &$captured_config ) { $captured_config = $config; return true; - } - ) + }, + ), ); $this->instance->register_routes(); diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php index a8477a384e9..8766b576bab 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Abstract_Site_Schema_Aggregator_Xml_Route_Test.php @@ -62,7 +62,7 @@ protected function set_up() { $this->instance = new Site_Schema_Aggregator_Xml_Route( $this->command_handler, $this->xml_cache_manager, - $this->aggregator_config + $this->aggregator_config, ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php index 3f985e5605e..9930e2c9ae7 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_XML_Route/Register_Routes_Test.php @@ -31,7 +31,7 @@ public function test_register_routes() { 'methods' => 'GET', 'callback' => [ $this->instance, 'render_schema_xml' ], 'permission_callback' => [ $this->instance, 'get_permission_callback' ], - ] + ], ); $this->instance->register_routes(); diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php index 4ab172ee96c..e66389371dd 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Abstract_Site_Schema_Response_Header_Integration_Test.php @@ -40,7 +40,7 @@ protected function set_up() { $this->schema_map_header_adapter = Mockery::mock( Schema_Map_Header_Adapter::class ); $this->instance = new Site_Schema_Response_Header_Integration( - $this->schema_map_header_adapter + $this->schema_map_header_adapter, ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php index 70dc4cd3595..fecaa6bc171 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Construct_Test.php @@ -26,7 +26,7 @@ public function test_construct() { $this->assertInstanceOf( Site_Schema_Response_Header_Integration::class, $this->instance ); $this->assertInstanceOf( Schema_Map_Header_Adapter::class, - $this->getPropertyValue( $this->instance, 'schema_map_header_adapter' ) + $this->getPropertyValue( $this->instance, 'schema_map_header_adapter' ), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php index 8b0d34f2167..d1e003309d7 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Response_Header_Integration/Site_Schema_Response_Header_Integration_Register_Hooks_Test.php @@ -25,7 +25,7 @@ public function test_register_hooks() { $this->instance->register_hooks(); $this->assertNotFalse( - Monkey\Filters\has( 'rest_pre_serve_request', [ $this->instance, 'serve_custom_response' ] ) + Monkey\Filters\has( 'rest_pre_serve_request', [ $this->instance, 'serve_custom_response' ] ), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php index 34d2945ce10..bb17a686c83 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test.php @@ -26,7 +26,7 @@ final class Site_Schema_Robots_Txt_Integration_Get_Conditionals_Test extends Abs public function test_get_conditionals() { $this->assertEquals( [ Schema_Aggregator_Conditional::class ], - Site_Schema_Robots_Txt_Integration::get_conditionals() + Site_Schema_Robots_Txt_Integration::get_conditionals(), ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php index 5d4565ec84d..9afdf4a0b2d 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Robots_Txt_Integration/Site_Schema_Robots_Txt_Integration_Register_Hooks_Test.php @@ -26,7 +26,7 @@ public function test_register_hooks() { $this->instance->register_hooks(); $this->assertNotFalse( - Monkey\Actions\has( 'Yoast\WP\SEO\register_robots_rules', [ $this->instance, 'maybe_add_xml_schema_map' ] ) + Monkey\Actions\has( 'Yoast\WP\SEO\register_robots_rules', [ $this->instance, 'maybe_add_xml_schema_map' ] ), ); } } From c9774119f9ab09e499fef38d372cd119bb7a3f6a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 13:13:18 +0100 Subject: [PATCH 309/319] Fix cs --- .../aggregate-site-schema-command-handler.php | 2 +- src/schema-aggregator/application/cache/manager.php | 10 +++++----- .../application/cache/xml-manager.php | 2 +- .../enhancement/article-schema-enhancer.php | 2 +- .../application/properties-merger.php | 2 +- .../schema-aggregator-response-composer.php | 2 +- .../elements-context-map-repository.php | 4 +--- .../elements-context-map/filtered-map-loader.php | 4 ++-- .../indexable-repository/indexable-repository.php | 2 +- .../wordpress-query-repository.php | 2 +- .../schema_map/schema-map-indexable-repository.php | 4 ++-- .../schema_map/schema-map-wordpress-repository.php | 4 ++-- .../site-schema-aggregator-cache-cli-command.php | 4 ++-- .../site-schema-aggregator-cli-command.php | 2 +- .../user-interface/site-schema-aggregator-route.php | 2 +- 15 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php index 626456dbe46..04d169f22e9 100644 --- a/src/schema-aggregator/application/aggregate-site-schema-command-handler.php +++ b/src/schema-aggregator/application/aggregate-site-schema-command-handler.php @@ -60,7 +60,7 @@ public function handle( Aggregate_Site_Schema_Command $command ): array { $schema_pieces = $this->schema_piece_repository->get( $command->get_page_controls()->get_page(), $command->get_page_controls()->get_page_size(), - $command->get_page_controls()->get_post_type() + $command->get_page_controls()->get_post_type(), ); $aggregated_schema_pieces = $this->schema_piece_aggregator->aggregate( $schema_pieces ); diff --git a/src/schema-aggregator/application/cache/manager.php b/src/schema-aggregator/application/cache/manager.php index ca36462669d..8f545c58bb8 100644 --- a/src/schema-aggregator/application/cache/manager.php +++ b/src/schema-aggregator/application/cache/manager.php @@ -140,8 +140,8 @@ public function invalidate( string $post_type, ?int $page = null, ?int $per_page $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $pattern, - $timeout_pattern - ) + $timeout_pattern, + ), ); return $deleted !== false; @@ -170,8 +170,8 @@ public function invalidate_all(): bool { $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $pattern, - $timeout_pattern - ) + $timeout_pattern, + ), ); if ( $deleted === false ) { @@ -202,7 +202,7 @@ private function get_cache_key( string $post_type, int $page, int $per_page ): s $page, $per_page, $post_type, - self::CACHE_VERSION + self::CACHE_VERSION, ); } } diff --git a/src/schema-aggregator/application/cache/xml-manager.php b/src/schema-aggregator/application/cache/xml-manager.php index 3e0f72b0f2c..7a848d42308 100644 --- a/src/schema-aggregator/application/cache/xml-manager.php +++ b/src/schema-aggregator/application/cache/xml-manager.php @@ -111,7 +111,7 @@ private function get_cache_key(): string { return \sprintf( '%s_xml_sitemap_v%d', self::CACHE_PREFIX, - self::CACHE_VERSION + self::CACHE_VERSION, ); } } diff --git a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php index 581b5f1ff5a..e6ebad11d15 100644 --- a/src/schema-aggregator/application/enhancement/article-schema-enhancer.php +++ b/src/schema-aggregator/application/enhancement/article-schema-enhancer.php @@ -54,7 +54,7 @@ public function enhance( Schema_Piece $schema_piece, Indexable $indexable ): Sch 'NewsArticle', 'BlogPosting', ], - true + true, ) ) { $schema_data = $this->enhance_schema_piece( $schema_data, $indexable ); } diff --git a/src/schema-aggregator/application/properties-merger.php b/src/schema-aggregator/application/properties-merger.php index 5fb1f0cb71e..7be7f4d438e 100644 --- a/src/schema-aggregator/application/properties-merger.php +++ b/src/schema-aggregator/application/properties-merger.php @@ -53,7 +53,7 @@ private function merge_properties( array $entity1, array $entity2 ): array { if ( $key === '@type' ) { $merged['@type'] = $this->merge_types( ( $merged['@type'] ?? null ), - $value + $value, ); continue; } diff --git a/src/schema-aggregator/application/schema-aggregator-response-composer.php b/src/schema-aggregator/application/schema-aggregator-response-composer.php index 73a62b5b132..2fd5518d1d5 100644 --- a/src/schema-aggregator/application/schema-aggregator-response-composer.php +++ b/src/schema-aggregator/application/schema-aggregator-response-composer.php @@ -26,7 +26,7 @@ public function compose( Schema_Piece_Collection $schema_pieces, bool $is_debug [ '@context' => 'https://schema.org', ], - $piece->get_data() + $piece->get_data(), ); } if ( $is_debug ) { diff --git a/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php index bfd57fc3184..8e3af171ece 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/elements-context-map-repository.php @@ -36,9 +36,7 @@ public function __construct( Map_Loader_Interface $map_loader ) { * @return array> The elements context-map. */ public function get_map(): array { - if ( $this->map === null ) { - $this->map = $this->map_loader->load(); - } + $this->map ??= $this->map_loader->load(); return $this->map; } diff --git a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php index 349efd58f31..e1d27c7a5f8 100644 --- a/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php +++ b/src/schema-aggregator/infrastructure/elements-context-map/filtered-map-loader.php @@ -72,13 +72,13 @@ private function validate_main_map_lightweight( $map ): void { if ( ! \is_string( $first_key ) ) { throw new InvalidArgumentException( - 'Filter "wpseo_schema_aggregator_elements_context_map" must return an array with string keys (context names).' + 'Filter "wpseo_schema_aggregator_elements_context_map" must return an array with string keys (context names).', ); } if ( ! \is_array( $first_value ) ) { throw new InvalidArgumentException( - 'Filter "wpseo_schema_aggregator_elements_context_map" must return an array with array values (element lists).' + 'Filter "wpseo_schema_aggregator_elements_context_map" must return an array with array values (element lists).', ); } } diff --git a/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php index 1bd3dd371f6..426f8fae66f 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/indexable-repository.php @@ -40,7 +40,7 @@ public function get( int $page, int $page_size, string $post_type ): array { return $this->indexable_repository->find_all_public_paginated( $page, $page_size, - $post_type + $post_type, ); } } diff --git a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php index 87ee30fedfb..f83c2e425cb 100644 --- a/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php +++ b/src/schema-aggregator/infrastructure/indexable-repository/wordpress-query-repository.php @@ -57,7 +57,7 @@ public function get( int $page, int $page_size, string $post_type ): array { 'paged' => $page, 'fields' => 'ids', 'no_found_rows' => false, - ] + ], ); if ( ! $query instanceof WP_Query ) { diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php index d27550f2ef8..c3961736924 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-indexable-repository.php @@ -123,8 +123,8 @@ public function get_lastmod_for_post_type( string $post_type, int $page, int $pe ", $post_type, $per_page, - $offset - ) + $offset, + ), ); // Convert to ISO 8601 format or use current time if no posts. if ( $lastmod && ! empty( $lastmod ) ) { diff --git a/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php b/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php index e62afdb9c78..e51ba13f265 100644 --- a/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php +++ b/src/schema-aggregator/infrastructure/schema_map/schema-map-wordpress-repository.php @@ -96,8 +96,8 @@ public function get_lastmod_for_post_type( string $post_type, int $page, int $pe ) AS posts_range", $post_type, $per_page, - $offset - ) + $offset, + ), ); // phpcs:enable // Convert to ISO 8601 format or use current time if no posts. diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php index 52a740c41cc..269fdbf3333 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-cache-cli-command.php @@ -87,7 +87,7 @@ public function aggregate_site_schema_clear_cache( $args = null, $assoc_args = n $this->cache_manager->invalidate( $assoc_args['post_type'], $assoc_args['page'] ); $this->xml_manager->invalidate(); WP_CLI::log( - \__( 'The site schema cache has been cleared successfully.', 'wordpress-seo' ) + \__( 'The site schema cache has been cleared successfully.', 'wordpress-seo' ), ); return; @@ -96,7 +96,7 @@ public function aggregate_site_schema_clear_cache( $args = null, $assoc_args = n $this->xml_manager->invalidate(); WP_CLI::log( - \__( 'All site schema cache has been cleared successfully.', 'wordpress-seo' ) + \__( 'All site schema cache has been cleared successfully.', 'wordpress-seo' ), ); } } diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php index f923a7b0219..0630d896255 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-cli-command.php @@ -105,7 +105,7 @@ public function aggregate_site_schema( $args = null, $assoc_args = null ) { $output = WPSEO_Utils::format_json_encode( $result ); $output = \str_replace( "\n", \PHP_EOL . "\t", $output ); WP_CLI::log( - $output + $output, ); } } diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 0ebdda56bc2..8a074f45c05 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -161,7 +161,7 @@ public function aggregate_site_schema( WP_REST_Request $request ) { return new WP_Error( 'wpseo_aggregate_site_schema_error', $exception->getMessage(), - (object) [] + (object) [], ); } } From 3a87adbcc3717d84a442d423cd6cdb911c9ddccb Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 13:21:10 +0100 Subject: [PATCH 310/319] Fix cs --- .../Article_Schema_Enhancer_Test.php | 24 ++++++++-------- .../Person_Schema_Enhancer_Test.php | 28 +++++++++---------- .../WordPress_Query_Repository_Test.php | 6 ++-- .../Collect_Test.php | 6 ++-- .../Schema_Piece_Repository/Get_Test.php | 12 ++++---- .../Collect_Test.php | 6 ++-- 6 files changed, 41 insertions(+), 41 deletions(-) diff --git a/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php index 5c203a0a10e..b1d03d8b1b0 100644 --- a/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php +++ b/tests/WP/Schema_Aggregator/Application/Enhancement/Article_Schema_Enhancer_Test.php @@ -85,7 +85,7 @@ public function test_enhance_adds_description_from_excerpt_for_article() { 'post_status' => 'publish', 'post_excerpt' => 'This is a test excerpt for the article.', 'post_content' => 'This is the full article content.', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -136,7 +136,7 @@ public function test_enhance_adds_article_body_when_no_excerpt() { 'post_status' => 'publish', 'post_excerpt' => 'Test excerpt', 'post_content' => 'This is the full article content that should appear as articleBody.', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -169,7 +169,7 @@ public function test_enhance_adds_keywords_from_tags() { 'post_title' => 'Test Article', 'post_type' => 'post', 'post_status' => 'publish', - ] + ], ); // Create and assign tags. @@ -206,7 +206,7 @@ public function test_enhance_adds_keywords_from_categories_when_enabled() { 'post_title' => 'Test Article', 'post_type' => 'post', 'post_status' => 'publish', - ] + ], ); // Create and assign category. @@ -243,7 +243,7 @@ public function test_enhance_works_with_news_article_type() { 'post_type' => 'post', 'post_status' => 'publish', 'post_excerpt' => 'Breaking news excerpt.', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -273,7 +273,7 @@ public function test_enhance_works_with_blog_posting_type() { 'post_type' => 'post', 'post_status' => 'publish', 'post_excerpt' => 'Blog post excerpt.', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -303,7 +303,7 @@ public function test_enhance_works_with_article_in_type_array() { 'post_type' => 'post', 'post_status' => 'publish', 'post_excerpt' => 'Article with multiple types.', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -333,7 +333,7 @@ public function test_enhance_does_not_override_existing_description() { 'post_type' => 'post', 'post_status' => 'publish', 'post_excerpt' => 'This should not be used.', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -363,7 +363,7 @@ public function test_enhance_does_not_override_existing_article_body() { 'post_type' => 'post', 'post_status' => 'publish', 'post_content' => 'This should not be used.', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -392,7 +392,7 @@ public function test_enhance_does_not_override_existing_keywords() { 'post_title' => 'Test Article', 'post_type' => 'post', 'post_status' => 'publish', - ] + ], ); // Create and assign tags. @@ -425,7 +425,7 @@ public function test_enhance_returns_unchanged_when_no_enhancements_possible() { 'post_title' => 'Test Article', 'post_type' => 'post', 'post_status' => 'publish', - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -460,7 +460,7 @@ public function test_enhance_respects_disabled_enhancements() { 'post_status' => 'publish', 'post_excerpt' => 'This should not be added.', 'post_content' => 'This should not be added.', - ] + ], ); // Create and assign tags. diff --git a/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php b/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php index 3020fb2c46c..d077ea40fc9 100644 --- a/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php +++ b/tests/WP/Schema_Aggregator/Application/Enhancement/Person_Schema_Enhancer_Test.php @@ -81,7 +81,7 @@ public function test_enhance_adds_job_title_from_user_meta() { [ 'user_login' => 'testauthor', 'role' => 'author', - ] + ], ); \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); @@ -92,7 +92,7 @@ public function test_enhance_adds_job_title_from_user_meta() { 'post_type' => 'post', 'post_status' => 'publish', 'post_author' => $user_id, - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -120,7 +120,7 @@ public function test_enhance_does_not_override_existing_job_title() { [ 'user_login' => 'testauthor', 'role' => 'author', - ] + ], ); \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); @@ -131,7 +131,7 @@ public function test_enhance_does_not_override_existing_job_title() { 'post_type' => 'post', 'post_status' => 'publish', 'post_author' => $user_id, - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -159,7 +159,7 @@ public function test_enhance_does_not_add_job_title_when_empty() { [ 'user_login' => 'testauthor', 'role' => 'author', - ] + ], ); // Set empty job title. @@ -171,7 +171,7 @@ public function test_enhance_does_not_add_job_title_when_empty() { 'post_type' => 'post', 'post_status' => 'publish', 'post_author' => $user_id, - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -198,7 +198,7 @@ public function test_enhance_does_not_add_job_title_when_meta_not_exists() { [ 'user_login' => 'testauthor', 'role' => 'author', - ] + ], ); $post = $this->factory()->post->create_and_get( @@ -207,7 +207,7 @@ public function test_enhance_does_not_add_job_title_when_meta_not_exists() { 'post_type' => 'post', 'post_status' => 'publish', 'post_author' => $user_id, - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -234,7 +234,7 @@ public function test_enhance_trims_whitespace_from_job_title() { [ 'user_login' => 'testauthor', 'role' => 'author', - ] + ], ); \update_user_meta( $user_id, 'job_title', ' Senior Developer ' ); @@ -245,7 +245,7 @@ public function test_enhance_trims_whitespace_from_job_title() { 'post_type' => 'post', 'post_status' => 'publish', 'post_author' => $user_id, - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -273,7 +273,7 @@ public function test_enhance_ignores_non_person_types() { [ 'user_login' => 'testauthor', 'role' => 'author', - ] + ], ); \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); @@ -284,7 +284,7 @@ public function test_enhance_ignores_non_person_types() { 'post_type' => 'post', 'post_status' => 'publish', 'post_author' => $user_id, - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); @@ -314,7 +314,7 @@ public function test_enhance_respects_disabled_enhancement() { [ 'user_login' => 'testauthor', 'role' => 'author', - ] + ], ); \update_user_meta( $user_id, 'job_title', 'Senior Developer' ); @@ -325,7 +325,7 @@ public function test_enhance_respects_disabled_enhancement() { 'post_type' => 'post', 'post_status' => 'publish', 'post_author' => $user_id, - ] + ], ); $indexable = \current( $this->get_indexables_for( $post ) ); diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php index 102cbe8d463..da22ddb309e 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Indexable_Repository/WordPress_Query_Repository_Test.php @@ -115,7 +115,7 @@ public function test_get_pagination_returns_different_results(): void { $this->assertNotEquals( ( $page_1[0]->object_id ?? null ), ( $page_2[0]->object_id ?? null ), - 'Different pages should return different posts' + 'Different pages should return different posts', ); } @@ -183,7 +183,7 @@ private function create_test_content(): void { 'post_title' => 'Test Post', 'post_status' => 'publish', 'post_type' => 'post', - ] + ], ); $this->created_posts = \array_merge( $this->created_posts, $post_ids ); @@ -193,7 +193,7 @@ private function create_test_content(): void { 'post_title' => 'Test Page', 'post_status' => 'publish', 'post_type' => 'page', - ] + ], ); $this->created_posts = \array_merge( $this->created_posts, $page_ids ); } diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php index 61beca13013..e39454f82c4 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Edd_Schema_Piece_Repository/Collect_Test.php @@ -92,7 +92,7 @@ public function test_collect_returns_product_schema(): void { 'post_status' => 'publish', 'post_type' => 'download', 'post_excerpt' => 'A test digital download.', - ] + ], ); $this->created_posts[] = $post_id; @@ -122,7 +122,7 @@ public function test_collect_returns_empty_for_non_download_post(): void { 'post_title' => 'Regular Post', 'post_status' => 'publish', 'post_type' => 'post', - ] + ], ); $this->created_posts[] = $post_id; @@ -138,7 +138,7 @@ public function test_collect_returns_empty_for_non_download_post(): void { * @return void */ public function test_collect_returns_empty_for_non_existent_post(): void { - $result = $this->instance->collect( 999999 ); + $result = $this->instance->collect( 999_999 ); $this->assertIsArray( $result ); $this->assertEmpty( $result, 'Expected empty array for a non-existent post ID.' ); diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php index 34b7e73156e..b4d5b894094 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php @@ -100,7 +100,7 @@ public function set_up(): void { $indexable_repository_factory, $wordpress_global_state_adapter, $edd_schema_piece_repository, - $woo_schema_piece_repository + $woo_schema_piece_repository, ); // Delete all indexables before each test to ensure a clean slate. @@ -158,7 +158,7 @@ public function test_get_with_results( $this->assertGreaterThanOrEqual( $min_expected_pieces, \count( $pieces ), - "Should return at least {$min_expected_pieces} schema pieces." + "Should return at least {$min_expected_pieces} schema pieces.", ); foreach ( $pieces as $piece ) { @@ -220,13 +220,13 @@ public function test_get_pagination_returns_different_schema_pieces( bool $enabl static function ( Schema_Piece $piece ) { return $piece->get_data(); }, - $page_1_pieces + $page_1_pieces, ); $page_2_data = \array_map( static function ( Schema_Piece $piece ) { return $piece->get_data(); }, - $page_2_pieces + $page_2_pieces, ); $this->assertNotEquals( $page_1_data, $page_2_data, 'Different pages should return different schema pieces.' ); @@ -350,7 +350,7 @@ private function create_test_content(): void { 'post_status' => 'publish', 'post_type' => 'post', 'post_content' => 'Test post content for schema aggregation.', - ] + ], ); $this->created_posts = \array_merge( $this->created_posts, $post_ids ); @@ -361,7 +361,7 @@ private function create_test_content(): void { 'post_status' => 'publish', 'post_type' => 'page', 'post_content' => 'Test page content for schema aggregation.', - ] + ], ); $this->created_posts = \array_merge( $this->created_posts, $page_ids ); } diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php index 8af458c3c8a..4a7565756cd 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Woo_Schema_Piece_Repository/Collect_Test.php @@ -66,7 +66,7 @@ public function set_up(): void { 'woocommerce_structured_data_product', static function ( $markup ) { return \apply_filters( 'wpseo_schema_product', $markup ); - } + }, ); $this->instance = new Woo_Schema_Piece_Repository( new WooCommerce_Conditional() ); @@ -125,7 +125,7 @@ public function test_collect_returns_empty_for_non_product_post(): void { 'post_title' => 'Regular Post', 'post_status' => 'publish', 'post_type' => 'post', - ] + ], ); $this->created_posts[] = $post_id; @@ -141,7 +141,7 @@ public function test_collect_returns_empty_for_non_product_post(): void { * @return void */ public function test_collect_returns_empty_for_non_existent_post(): void { - $result = $this->instance->collect( 999999 ); + $result = $this->instance->collect( 999_999 ); $this->assertIsArray( $result ); $this->assertEmpty( $result, 'Expected empty array for a non-existent post ID.' ); From 64359d741b8d0d8a4b131eed4defddec79365333 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 13:23:59 +0100 Subject: [PATCH 311/319] Fix cs --- src/schema-aggregator/infrastructure/config.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schema-aggregator/infrastructure/config.php b/src/schema-aggregator/infrastructure/config.php index ee97b1d13de..300020ae114 100644 --- a/src/schema-aggregator/infrastructure/config.php +++ b/src/schema-aggregator/infrastructure/config.php @@ -90,12 +90,12 @@ public function get_expiration( array $data ): int { $size = \strlen( $serialized ); // Large payloads: cache longer. - if ( $size > 1048576 ) { + if ( $size > 1_048_576 ) { $cache_ttl = ( 6 * \HOUR_IN_SECONDS ); } // Small payloads: cache shorter. - if ( $size < 102400 ) { + if ( $size < 102_400 ) { $cache_ttl = ( 30 * \MINUTE_IN_SECONDS ); } From 4f805f709b3a76f36dc9209c0b415a3d1e8b8fc6 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 16:41:00 +0100 Subject: [PATCH 312/319] Do not expose endpoints if the post type is set to noindex Also avoid listing that endpoint in the schemamap --- .../infrastructure/aggregator-config.php | 9 ++++++++ .../site-schema-aggregator-route.php | 22 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/schema-aggregator/infrastructure/aggregator-config.php b/src/schema-aggregator/infrastructure/aggregator-config.php index d1e81c9ad0f..e2fc7b06e90 100644 --- a/src/schema-aggregator/infrastructure/aggregator-config.php +++ b/src/schema-aggregator/infrastructure/aggregator-config.php @@ -57,6 +57,15 @@ public function __construct( WooCommerce_Conditional $woocommerce_conditional, P public function get_allowed_post_types(): array { $default_post_types = $this->post_type_helper->get_indexable_post_types(); + foreach ( $default_post_types as $key => $post_type ) { + if ( ! $this->post_type_helper->is_indexable( $post_type ) ) { + unset( $default_post_types[ $key ] ); + } + } + + // Reindex the array to avoid gaps. + $default_post_types = \array_values( $default_post_types ); + $post_types = \apply_filters( 'wpseo_schema_aggregator_post_types', $default_post_types ); if ( ! \is_array( $post_types ) ) { diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index 8a074f45c05..ad0625073f2 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -7,6 +7,7 @@ use WP_REST_Request; use WP_REST_Response; use Yoast\WP\SEO\Helpers\Capability_Helper; +use Yoast\WP\SEO\Helpers\Post_Type_Helper; use Yoast\WP\SEO\Main; use Yoast\WP\SEO\Routes\Route_Interface; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command; @@ -63,6 +64,13 @@ class Site_Schema_Aggregator_Route implements Route_Interface { */ private $cache_manager; + /** + * The post type helper instance. + * + * @var Post_Type_Helper + */ + private $post_type_helper; + /** * Returns the conditional for this route. * @@ -79,17 +87,20 @@ public static function get_conditionals() { * @param Capability_Helper $capability_helper The capability helper. * @param Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler The command handler. * @param Manager $cache_manager The cache manager. + * @param Post_Type_Helper $post_type_helper The post type helper. */ public function __construct( Config $config, Capability_Helper $capability_helper, Aggregate_Site_Schema_Command_Handler $aggregate_site_schema_command_handler, - Manager $cache_manager + Manager $cache_manager, + Post_Type_Helper $post_type_helper ) { $this->config = $config; $this->capability_helper = $capability_helper; $this->aggregate_site_schema_command_handler = $aggregate_site_schema_command_handler; $this->cache_manager = $cache_manager; + $this->post_type_helper = $post_type_helper; } /** @@ -144,6 +155,15 @@ public function get_permission_callback(): bool { */ public function aggregate_site_schema( WP_REST_Request $request ) { $post_type = $request->get_param( 'post_type' ); + + if ( ! $this->post_type_helper->is_indexable( $post_type ) ) { + return new WP_Error( + 'wpseo_post_type_not_indexable', + \sprintf( 'The post type "%s" is excluded from search results.', $post_type ), + [ 'status' => 404 ], + ); + } + $is_debug = (bool) $request->get_param( 'debug' ); $page = ( $request->get_param( 'page' ) ?? 1 ); $per_page = $this->config->get_per_page( $post_type ); From fd2236c00f5c76e8196103d7de8579ac617fed59 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 16:41:29 +0100 Subject: [PATCH 313/319] Update tests --- ...tor_Config_Get_Allowed_Post_Types_Test.php | 85 +++++++++++++++---- ...ract_Site_Schema_Aggregator_Route_Test.php | 10 +++ .../Aggregate_Site_Schema_Test.php | 52 ++++++++++++ .../Constructor_Test.php | 6 ++ 4 files changed, 137 insertions(+), 16 deletions(-) create mode 100644 tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Aggregate_Site_Schema_Test.php diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php index 898f5f6dd4b..16df5ae908d 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php @@ -24,21 +24,30 @@ final class Aggregator_Config_Get_Allowed_Post_Types_Test extends Abstract_Aggre * * @dataProvider get_allowed_post_types_data * - * @param array $default_post_types The default post types from the helper. - * @param mixed $filtered_value The value returned by the filter. - * @param array $expected The expected result. + * @param array $default_post_types The default post types from the helper. + * @param array $is_indexable_map Map of post type to is_indexable return value. + * @param array $indexable_post_types The post types after is_indexable filtering. + * @param mixed $filtered_value The value returned by the filter. + * @param array $expected The expected result. * * @return void */ - public function test_get_allowed_post_types( $default_post_types, $filtered_value, $expected ) { + public function test_get_allowed_post_types( $default_post_types, $is_indexable_map, $indexable_post_types, $filtered_value, $expected ) { $this->post_type_helper ->expects( 'get_indexable_post_types' ) ->once() ->andReturn( $default_post_types ); + foreach ( $is_indexable_map as $post_type => $is_indexable ) { + $this->post_type_helper + ->expects( 'is_indexable' ) + ->with( $post_type ) + ->andReturn( $is_indexable ); + } + Functions\expect( 'apply_filters' ) ->once() - ->with( 'wpseo_schema_aggregator_post_types', $default_post_types ) + ->with( 'wpseo_schema_aggregator_post_types', $indexable_post_types ) ->andReturn( $filtered_value ); $this->assertEquals( $expected, $this->instance->get_allowed_post_types() ); @@ -51,63 +60,107 @@ public function test_get_allowed_post_types( $default_post_types, $filtered_valu */ public static function get_allowed_post_types_data() { yield 'Filter returns valid array - uses filtered value' => [ - 'default_post_types' => [ 'post', 'page' ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'indexable_post_types' => [ 'post', 'page' ], 'filtered_value' => [ 'post', 'page', 'custom' ], 'expected' => [ 'post', 'page', 'custom' ], ]; yield 'Filter returns same as default - uses default value' => [ - 'default_post_types' => [ 'post', 'page', 'product' ], + 'default_post_types' => [ 'post', 'page', 'product' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true, 'product' => true ], + 'indexable_post_types' => [ 'post', 'page', 'product' ], 'filtered_value' => [ 'post', 'page', 'product' ], 'expected' => [ 'post', 'page', 'product' ], ]; yield 'Filter returns empty array - uses empty array' => [ - 'default_post_types' => [ 'post', 'page' ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'indexable_post_types' => [ 'post', 'page' ], 'filtered_value' => [], 'expected' => [], ]; yield 'Filter returns string - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'indexable_post_types' => [ 'post', 'page' ], 'filtered_value' => 'invalid_string', 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns null - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'indexable_post_types' => [ 'post', 'page' ], 'filtered_value' => null, 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns integer - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'indexable_post_types' => [ 'post', 'page' ], 'filtered_value' => 123, 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns boolean false - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'indexable_post_types' => [ 'post', 'page' ], 'filtered_value' => false, 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns object - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'indexable_post_types' => [ 'post', 'page' ], 'filtered_value' => new stdClass(), 'expected' => [ 'post', 'page' ], ]; yield 'Single post type from helper' => [ - 'default_post_types' => [ 'post' ], + 'default_post_types' => [ 'post' ], + 'is_indexable_map' => [ 'post' => true ], + 'indexable_post_types' => [ 'post' ], 'filtered_value' => [ 'post' ], 'expected' => [ 'post' ], ]; yield 'Many post types including custom' => [ - 'default_post_types' => [ 'post', 'page', 'product', 'event', 'recipe' ], + 'default_post_types' => [ 'post', 'page', 'product', 'event', 'recipe' ], + 'is_indexable_map' => [ 'post' => true, 'page' => true, 'product' => true, 'event' => true, 'recipe' => true ], + 'indexable_post_types' => [ 'post', 'page', 'product', 'event', 'recipe' ], 'filtered_value' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], 'expected' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], ]; + + yield 'Some post types are noindex - only indexable ones are included' => [ + 'default_post_types' => [ 'post', 'page', 'product' ], + 'is_indexable_map' => [ 'post' => true, 'page' => false, 'product' => true ], + 'indexable_post_types' => [ 'post', 'product' ], + 'filtered_value' => [ 'post', 'product' ], + 'expected' => [ 'post', 'product' ], + ]; + + yield 'All post types are noindex - empty result' => [ + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ 'post' => false, 'page' => false ], + 'indexable_post_types' => [], + 'filtered_value' => [], + 'expected' => [], + ]; + + yield 'Noindex post types with invalid filter - falls back to filtered defaults' => [ + 'default_post_types' => [ 'post', 'page', 'product' ], + 'is_indexable_map' => [ 'post' => true, 'page' => false, 'product' => true ], + 'indexable_post_types' => [ 'post', 'product' ], + 'filtered_value' => null, + 'expected' => [ 'post', 'product' ], + ]; } -} +} \ No newline at end of file diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php index c673281099b..71bf1c7fd7d 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Abstract_Site_Schema_Aggregator_Route_Test.php @@ -5,6 +5,7 @@ use Mockery; use Yoast\WP\SEO\Helpers\Capability_Helper; +use Yoast\WP\SEO\Helpers\Post_Type_Helper; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Manager; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; @@ -55,6 +56,13 @@ abstract class Abstract_Site_Schema_Aggregator_Route_Test extends TestCase { */ protected $cache_manager; + /** + * Holds the Post_Type_Helper mock. + * + * @var Mockery\MockInterface|Post_Type_Helper + */ + protected $post_type_helper; + /** * Sets up the test fixtures. * @@ -67,12 +75,14 @@ protected function set_up() { $this->capability_helper = Mockery::mock( Capability_Helper::class ); $this->command_handler = Mockery::mock( Aggregate_Site_Schema_Command_Handler::class ); $this->cache_manager = Mockery::mock( Manager::class ); + $this->post_type_helper = Mockery::mock( Post_Type_Helper::class ); $this->instance = new Site_Schema_Aggregator_Route( $this->config, $this->capability_helper, $this->command_handler, $this->cache_manager, + $this->post_type_helper, ); } } diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Aggregate_Site_Schema_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Aggregate_Site_Schema_Test.php new file mode 100644 index 00000000000..5e090aaf24c --- /dev/null +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Aggregate_Site_Schema_Test.php @@ -0,0 +1,52 @@ +expects( 'get_param' ) + ->with( 'post_type' ) + ->andReturn( 'custom_post' ); + + $this->post_type_helper + ->expects( 'is_indexable' ) + ->with( 'custom_post' ) + ->andReturn( false ); + + $result = $this->instance->aggregate_site_schema( $request ); + + $this->assertInstanceOf( WP_Error::class, $result ); + } +} diff --git a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php index 73bdd0f53a7..4512b5c31fc 100644 --- a/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php +++ b/tests/Unit/Schema_Aggregator/User_Interface/Site_Schema_Aggregator_Route/Constructor_Test.php @@ -4,6 +4,7 @@ namespace Yoast\WP\SEO\Tests\Unit\Schema_Aggregator\User_Interface\Site_Schema_Aggregator_Route; use Yoast\WP\SEO\Helpers\Capability_Helper; +use Yoast\WP\SEO\Helpers\Post_Type_Helper; use Yoast\WP\SEO\Schema_Aggregator\Application\Aggregate_Site_Schema_Command_Handler; use Yoast\WP\SEO\Schema_Aggregator\Application\Cache\Manager; use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Config; @@ -44,5 +45,10 @@ public function test_constructor(): void { Manager::class, $this->getPropertyValue( $this->instance, 'cache_manager' ), ); + + $this->assertInstanceOf( + Post_Type_Helper::class, + $this->getPropertyValue( $this->instance, 'post_type_helper' ), + ); } } From 29c255aab93255fdefc84c6256869a36fd6bc9ea Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 16:42:03 +0100 Subject: [PATCH 314/319] Do not retrieve a post if it is set to robots_noindex --- .../infrastructure/schema-pieces/schema-piece-repository.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index 0143938ce61..e4aa4f7b0fd 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -121,6 +121,10 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec $schema_pieces = []; foreach ( $indexables as $indexable ) { + if ( $indexable->is_robots_noindex === true ) { + continue; + } + if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { continue; } From 694bda09eb55c5c0285349dd57f265866c3ab373 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 16:42:18 +0100 Subject: [PATCH 315/319] Add integration test --- .../Schema_Piece_Repository/Get_Test.php | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php index b4d5b894094..1227b70b78a 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php @@ -232,6 +232,61 @@ static function ( Schema_Piece $piece ) { $this->assertNotEquals( $page_1_data, $page_2_data, 'Different pages should return different schema pieces.' ); } + /** + * Tests that posts marked as noindex are excluded from schema pieces. + * + * @dataProvider enabled_indexables_data + * + * @param bool $enabled_indexables Whether indexables are enabled. + * + * @return void + */ + public function test_get_excludes_noindex_posts( bool $enabled_indexables ): void { + if ( ! $enabled_indexables ) { + \add_filter( 'Yoast\WP\SEO\should_index_indexables', '__return_false' ); + } + + // Create a noindex post. + $noindex_post_id = self::factory()->post->create( + [ + 'post_title' => 'Noindex Post', + 'post_status' => 'publish', + 'post_type' => 'post', + 'post_content' => 'This post should be excluded from schema aggregation.', + ], + ); + $this->created_posts[] = $noindex_post_id; + + // Mark the post as noindex. + \update_post_meta( $noindex_post_id, '_yoast_wpseo_meta-robots-noindex', '1' ); + + // Rebuild the indexable so is_robots_noindex is set. + $indexable_builder = \YoastSEO()->classes->get( Indexable_Builder::class ); + $indexable_repo = \YoastSEO()->classes->get( Pure_Indexable_Repository::class ); + $indexable = $indexable_repo->find_by_id_and_type( $noindex_post_id, 'post' ); + $indexable_builder->build( $indexable ); + + // Fetch all posts with a large page size to include all posts. + $result = $this->instance->get( 1, 100, 'post' ); + $pieces = $result->to_array(); + + // Verify the noindex post's schema pieces are not in the result. + $noindex_post_url = \get_permalink( $noindex_post_id ); + foreach ( $pieces as $piece ) { + $data = $piece->get_data(); + if ( isset( $data['@id'] ) ) { + $this->assertStringNotContainsString( + $noindex_post_url, + $data['@id'], + 'Schema pieces for noindex posts should be excluded.', + ); + } + } + + // Verify that regular posts still have schema pieces. + $this->assertNotEmpty( $pieces, 'Regular posts should still return schema pieces.' ); + } + /** * Data provider for test_get_with_results. * From bf7f762579c3b991b41140e136acfbf998c82b07 Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 16:42:37 +0100 Subject: [PATCH 316/319] Do not open the link in new page --- .../components/modals/schema-aggregator-announcement.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js b/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js index 58a6580fa5e..0e6c8bb215e 100644 --- a/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js +++ b/packages/js/src/introductions/components/modals/schema-aggregator-announcement.js @@ -54,7 +54,6 @@ const SchemaAggregatorAnnouncementContent = ( { size="extra-large" variant="primary" href={ buttonLink } - target="_blank" ref={ initialFocus } > { __( "Enable Schema aggregation endpoint", "wordpress-seo" ) } From 9d98f59fb360975a8909927f4010f4893dc5065a Mon Sep 17 00:00:00 2001 From: "Paolo L. Scala" Date: Mon, 16 Feb 2026 16:44:19 +0100 Subject: [PATCH 317/319] Fix cs --- .../site-schema-aggregator-route.php | 6 +- ...tor_Config_Get_Allowed_Post_Types_Test.php | 158 +++++++++++------- .../Schema_Piece_Repository/Get_Test.php | 2 +- 3 files changed, 104 insertions(+), 62 deletions(-) diff --git a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php index ad0625073f2..7aab969dcff 100644 --- a/src/schema-aggregator/user-interface/site-schema-aggregator-route.php +++ b/src/schema-aggregator/user-interface/site-schema-aggregator-route.php @@ -164,9 +164,9 @@ public function aggregate_site_schema( WP_REST_Request $request ) { ); } - $is_debug = (bool) $request->get_param( 'debug' ); - $page = ( $request->get_param( 'page' ) ?? 1 ); - $per_page = $this->config->get_per_page( $post_type ); + $is_debug = (bool) $request->get_param( 'debug' ); + $page = ( $request->get_param( 'page' ) ?? 1 ); + $per_page = $this->config->get_per_page( $post_type ); $output = $this->cache_manager->get( $post_type, $page, $per_page ); if ( $is_debug ) { diff --git a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php index 16df5ae908d..3c9f1b5c876 100644 --- a/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php +++ b/tests/Unit/Schema_Aggregator/Infrastructure/Aggregator_Config/Aggregator_Config_Get_Allowed_Post_Types_Test.php @@ -24,11 +24,11 @@ final class Aggregator_Config_Get_Allowed_Post_Types_Test extends Abstract_Aggre * * @dataProvider get_allowed_post_types_data * - * @param array $default_post_types The default post types from the helper. - * @param array $is_indexable_map Map of post type to is_indexable return value. - * @param array $indexable_post_types The post types after is_indexable filtering. - * @param mixed $filtered_value The value returned by the filter. - * @param array $expected The expected result. + * @param array $default_post_types The default post types from the helper. + * @param array $is_indexable_map Map of post type to is_indexable return value. + * @param array $indexable_post_types The post types after is_indexable filtering. + * @param mixed $filtered_value The value returned by the filter. + * @param array $expected The expected result. * * @return void */ @@ -60,107 +60,149 @@ public function test_get_allowed_post_types( $default_post_types, $is_indexable_ */ public static function get_allowed_post_types_data() { yield 'Filter returns valid array - uses filtered value' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + ], 'indexable_post_types' => [ 'post', 'page' ], - 'filtered_value' => [ 'post', 'page', 'custom' ], - 'expected' => [ 'post', 'page', 'custom' ], + 'filtered_value' => [ 'post', 'page', 'custom' ], + 'expected' => [ 'post', 'page', 'custom' ], ]; yield 'Filter returns same as default - uses default value' => [ - 'default_post_types' => [ 'post', 'page', 'product' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true, 'product' => true ], + 'default_post_types' => [ 'post', 'page', 'product' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + 'product' => true, + ], 'indexable_post_types' => [ 'post', 'page', 'product' ], - 'filtered_value' => [ 'post', 'page', 'product' ], - 'expected' => [ 'post', 'page', 'product' ], + 'filtered_value' => [ 'post', 'page', 'product' ], + 'expected' => [ 'post', 'page', 'product' ], ]; yield 'Filter returns empty array - uses empty array' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + ], 'indexable_post_types' => [ 'post', 'page' ], - 'filtered_value' => [], - 'expected' => [], + 'filtered_value' => [], + 'expected' => [], ]; yield 'Filter returns string - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + ], 'indexable_post_types' => [ 'post', 'page' ], - 'filtered_value' => 'invalid_string', - 'expected' => [ 'post', 'page' ], + 'filtered_value' => 'invalid_string', + 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns null - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + ], 'indexable_post_types' => [ 'post', 'page' ], - 'filtered_value' => null, - 'expected' => [ 'post', 'page' ], + 'filtered_value' => null, + 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns integer - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + ], 'indexable_post_types' => [ 'post', 'page' ], - 'filtered_value' => 123, - 'expected' => [ 'post', 'page' ], + 'filtered_value' => 123, + 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns boolean false - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + ], 'indexable_post_types' => [ 'post', 'page' ], - 'filtered_value' => false, - 'expected' => [ 'post', 'page' ], + 'filtered_value' => false, + 'expected' => [ 'post', 'page' ], ]; yield 'Filter returns object - falls back to default' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + ], 'indexable_post_types' => [ 'post', 'page' ], - 'filtered_value' => new stdClass(), - 'expected' => [ 'post', 'page' ], + 'filtered_value' => new stdClass(), + 'expected' => [ 'post', 'page' ], ]; yield 'Single post type from helper' => [ - 'default_post_types' => [ 'post' ], - 'is_indexable_map' => [ 'post' => true ], + 'default_post_types' => [ 'post' ], + 'is_indexable_map' => [ 'post' => true ], 'indexable_post_types' => [ 'post' ], - 'filtered_value' => [ 'post' ], - 'expected' => [ 'post' ], + 'filtered_value' => [ 'post' ], + 'expected' => [ 'post' ], ]; yield 'Many post types including custom' => [ - 'default_post_types' => [ 'post', 'page', 'product', 'event', 'recipe' ], - 'is_indexable_map' => [ 'post' => true, 'page' => true, 'product' => true, 'event' => true, 'recipe' => true ], + 'default_post_types' => [ 'post', 'page', 'product', 'event', 'recipe' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => true, + 'product' => true, + 'event' => true, + 'recipe' => true, + ], 'indexable_post_types' => [ 'post', 'page', 'product', 'event', 'recipe' ], - 'filtered_value' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], - 'expected' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], + 'filtered_value' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], + 'expected' => [ 'post', 'page', 'product', 'event', 'recipe', 'custom_type' ], ]; yield 'Some post types are noindex - only indexable ones are included' => [ - 'default_post_types' => [ 'post', 'page', 'product' ], - 'is_indexable_map' => [ 'post' => true, 'page' => false, 'product' => true ], + 'default_post_types' => [ 'post', 'page', 'product' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => false, + 'product' => true, + ], 'indexable_post_types' => [ 'post', 'product' ], - 'filtered_value' => [ 'post', 'product' ], - 'expected' => [ 'post', 'product' ], + 'filtered_value' => [ 'post', 'product' ], + 'expected' => [ 'post', 'product' ], ]; yield 'All post types are noindex - empty result' => [ - 'default_post_types' => [ 'post', 'page' ], - 'is_indexable_map' => [ 'post' => false, 'page' => false ], + 'default_post_types' => [ 'post', 'page' ], + 'is_indexable_map' => [ + 'post' => false, + 'page' => false, + ], 'indexable_post_types' => [], - 'filtered_value' => [], - 'expected' => [], + 'filtered_value' => [], + 'expected' => [], ]; yield 'Noindex post types with invalid filter - falls back to filtered defaults' => [ - 'default_post_types' => [ 'post', 'page', 'product' ], - 'is_indexable_map' => [ 'post' => true, 'page' => false, 'product' => true ], + 'default_post_types' => [ 'post', 'page', 'product' ], + 'is_indexable_map' => [ + 'post' => true, + 'page' => false, + 'product' => true, + ], 'indexable_post_types' => [ 'post', 'product' ], - 'filtered_value' => null, - 'expected' => [ 'post', 'product' ], + 'filtered_value' => null, + 'expected' => [ 'post', 'product' ], ]; } -} \ No newline at end of file +} diff --git a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php index 1227b70b78a..74bc8a37de0 100644 --- a/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php +++ b/tests/WP/Schema_Aggregator/Infrastructure/Schema_Pieces/Schema_Piece_Repository/Get_Test.php @@ -247,7 +247,7 @@ public function test_get_excludes_noindex_posts( bool $enabled_indexables ): voi } // Create a noindex post. - $noindex_post_id = self::factory()->post->create( + $noindex_post_id = self::factory()->post->create( [ 'post_title' => 'Noindex Post', 'post_status' => 'publish', From d4bcccb5cca8fc34c0d56c146de350278c5b4d9d Mon Sep 17 00:00:00 2001 From: Leonidas Milosis Date: Tue, 17 Feb 2026 11:39:29 +0200 Subject: [PATCH 318/319] Fix PHPCS --- .../indexables-disabled/indexables-disabled-alert.php | 4 ++-- .../Abstract_Indexables_Disabled_Alert_Test.php | 2 +- .../Indexables_Disabled_Alert_Add_Notifications_Test.php | 2 +- .../Indexables_Disabled_Alert_Constructor_Test.php | 6 +++--- .../Indexables_Disabled_Alert_Register_Hooks_Test.php | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/alerts/application/indexables-disabled/indexables-disabled-alert.php b/src/alerts/application/indexables-disabled/indexables-disabled-alert.php index 19ff67cc52e..9c56539395e 100644 --- a/src/alerts/application/indexables-disabled/indexables-disabled-alert.php +++ b/src/alerts/application/indexables-disabled/indexables-disabled-alert.php @@ -103,7 +103,7 @@ private function get_indexables_disabled_notification(): Yoast_Notification { 'id' => self::NOTIFICATION_ID, 'type' => Yoast_Notification::WARNING, 'capabilities' => [ 'wpseo_manage_options' ], - ] + ], ); } @@ -120,7 +120,7 @@ private function get_message(): string { \esc_html__( '%1$s indexables are disabled because your site is in a non-production environment or custom code is blocking them. This may affect your SEO features. %2$sLearn more about this%3$s.', 'wordpress-seo' ), 'Yoast', '', - '' + '', ); return $message; diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php index 302586da498..7239965d0bf 100644 --- a/tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Abstract_Indexables_Disabled_Alert_Test.php @@ -63,7 +63,7 @@ protected function set_up() { $this->instance = new Indexables_Disabled_Alert( $this->notification_center, $this->indexable_helper, - $this->short_link_helper + $this->short_link_helper, ); } } diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php index 845def76fb2..bd4dae8358a 100644 --- a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Add_Notifications_Test.php @@ -71,7 +71,7 @@ public function test_add_notifications( static function ( $notification ) use ( $expected_message ) { $notification_array = $notification->to_array(); return $notification_array['message'] === $expected_message; - } + }, ); $this->instance->add_notifications(); diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php index bb9fb10f318..18171dde9b3 100644 --- a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Constructor_Test.php @@ -26,15 +26,15 @@ final class Indexables_Disabled_Alert_Constructor_Test extends Abstract_Indexabl public function test_constructor() { $this->assertInstanceOf( Yoast_Notification_Center::class, - $this->getPropertyValue( $this->instance, 'notification_center' ) + $this->getPropertyValue( $this->instance, 'notification_center' ), ); $this->assertInstanceOf( Indexable_Helper::class, - $this->getPropertyValue( $this->instance, 'indexable_helper' ) + $this->getPropertyValue( $this->instance, 'indexable_helper' ), ); $this->assertInstanceOf( Short_Link_Helper::class, - $this->getPropertyValue( $this->instance, 'short_link_helper' ) + $this->getPropertyValue( $this->instance, 'short_link_helper' ), ); } } diff --git a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php index 64b55f04026..1b8707ee129 100644 --- a/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php +++ b/tests/Unit/Alerts/Application/Indexables_Disabled/Indexables_Disabled_Alert_Register_Hooks_Test.php @@ -26,8 +26,8 @@ public function test_register_hooks() { 10, \has_action( 'admin_init', - [ $this->instance, 'add_notifications' ] - ) + [ $this->instance, 'add_notifications' ], + ), ); } } From f85c06354153736ffc8c465e5e295e8d4f138c7d Mon Sep 17 00:00:00 2001 From: Thijs van der heijden Date: Tue, 17 Feb 2026 11:19:32 +0100 Subject: [PATCH 319/319] Add the is_robots check to the initial query instead of a php filter. --- src/repositories/indexable-repository.php | 2 +- .../infrastructure/schema-pieces/schema-piece-repository.php | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/repositories/indexable-repository.php b/src/repositories/indexable-repository.php index 76ea78a3542..0fb78c43b94 100644 --- a/src/repositories/indexable-repository.php +++ b/src/repositories/indexable-repository.php @@ -229,7 +229,7 @@ public function find_all_with_type_and_sub_type( $object_type, $object_sub_type public function find_all_public_paginated( int $page, int $page_size, string $post_type ): array { $offset = ( ( $page - 1 ) * $page_size ); - $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 )' ); + $query = $this->query()->where_raw( '( is_public IS NULL OR is_public = 1 ) AND ( is_robots_noindex IS NULL OR is_robots_noindex = 0 )' ); $query->where( 'object_sub_type', $post_type ); $query->where( 'post_status', 'publish' ); diff --git a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php index e4aa4f7b0fd..0143938ce61 100644 --- a/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php +++ b/src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php @@ -121,10 +121,6 @@ public function get( int $page, int $page_size, string $post_type ): Schema_Piec $schema_pieces = []; foreach ( $indexables as $indexable ) { - if ( $indexable->is_robots_noindex === true ) { - continue; - } - if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) { continue; }