*/ 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 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, Indexable_Helper $indexable_helper, Meta_Tags_Context_Memoizer_Adapter $adapter, Aggregator_Config $config, Schema_Enhancement_Factory $enhancement_factory, Indexable_Repository_Factory $indexable_repository_factory, WordPress_Global_State_Adapter $global_state_adapter, External_Schema_Piece_Repository_Interface ...$external_repositories ) { $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; $this->global_state_adapter = $global_state_adapter; $this->external_repositories = $external_repositories; $this->logger = new NullLogger(); } /** * 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 string $post_type The post type to filter by. * * @return Schema_Piece_Collection The aggregated schema. */ 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 = []; foreach ( $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 ); $this->global_state_adapter->set_global_state( $indexable, $context ); try { $context_array = $this->adapter->meta_tags_context_to_array( $context ); $pieces_data = $context_array['@graph']; $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'] ); $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; } } catch ( Throwable $e ) { $this->logger->warning( 'Schema aggregation failed for indexable #{indexable_id} ({object_type}/{object_sub_type}): {message}', [ 'indexable_id' => $indexable->id, 'object_type' => $indexable->object_type, 'object_sub_type' => $indexable->object_sub_type, 'message' => $e->getMessage(), ], ); } finally { $this->global_state_adapter->reset_global_state(); } } 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. * * @param array> $graph The current graph. * * @return array */ private function get_all_schema_types( array $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; } }