PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
28.6 28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 All 130 releases
wordpress-seo / src / schema-aggregator / infrastructure / schema-pieces / schema-piece-repository.php

schema-piece-repository.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI trunk, at src/schema-aggregator/infrastructure/schema-pieces/schema-piece-repository.php

216 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3 namespace Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Schema_Pieces;
4
5 use Throwable;
6 use Yoast\WP\SEO\Helpers\Indexable_Helper;
7 use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
8 use Yoast\WP\SEO\Schema_Aggregator\Application\Enhancement\Schema_Enhancement_Factory;
9 use Yoast\WP\SEO\Schema_Aggregator\Domain\External_Schema_Piece_Repository_Interface;
10 use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece;
11 use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Collection;
12 use Yoast\WP\SEO\Schema_Aggregator\Domain\Schema_Piece_Repository_Interface;
13 use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Aggregator_Config;
14 use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Indexable_Repository\Indexable_Repository_Factory;
15 use Yoast\WP\SEO\Schema_Aggregator\Infrastructure\Meta_Tags_Context_Memoizer_Adapter;
16 use YoastSEO_Vendor\Psr\Log\LoggerAwareInterface;
17 use YoastSEO_Vendor\Psr\Log\LoggerAwareTrait;
18 use YoastSEO_Vendor\Psr\Log\NullLogger;
19
20 /**
21 * The Schema_Piece repository.
22 */
23 class Schema_Piece_Repository implements Schema_Piece_Repository_Interface, LoggerAwareInterface {
24 use LoggerAwareTrait;
25
26 /**
27 * The meta tags context memoizer.
28 *
29 * @var Meta_Tags_Context_Memoizer
30 */
31 private $memoizer;
32
33 /**
34 * The indexable helper.
35 *
36 * @var Indexable_Helper
37 */
38 private $indexable_helper;
39
40 /**
41 * The meta tags context adapter factory.
42 *
43 * @var Meta_Tags_Context_Memoizer_Adapter
44 */
45 private $adapter;
46
47 /**
48 * Configuration provider.
49 *
50 * @var Aggregator_Config
51 */
52 private $config;
53
54 /**
55 * The schema enhancement factory.
56 *
57 * @var Schema_Enhancement_Factory
58 */
59 private $enhancement_factory;
60
61 /**
62 * The indexable repository factory.
63 *
64 * @var Indexable_Repository_Factory
65 */
66 private $indexable_repository_factory;
67
68 /**
69 * The WordPress global state adapter.
70 *
71 * @var WordPress_Global_State_Adapter
72 */
73 private $global_state_adapter;
74
75 /**
76 * External schema piece repositories.
77 *
78 * @var array<External_Schema_Piece_Repository_Interface>
79 */
80 private $external_repositories;
81
82 /**
83 * Constructor.
84 *
85 * @param Meta_Tags_Context_Memoizer $memoizer The meta tags context memoizer.
86 * @param Indexable_Helper $indexable_helper The indexable helper.
87 * @param Meta_Tags_Context_Memoizer_Adapter $adapter The adapter factory.
88 * @param Aggregator_Config $config The configuration provider.
89 * @param Schema_Enhancement_Factory $enhancement_factory The schema enhancement factory.
90 * @param Indexable_Repository_Factory $indexable_repository_factory The indexable repository factory.
91 * @param WordPress_Global_State_Adapter $global_state_adapter The global state adapter.
92 * @param External_Schema_Piece_Repository_Interface ...$external_repositories The external schema piece repositories.
93 */
94 public function __construct(
95 Meta_Tags_Context_Memoizer $memoizer,
96 Indexable_Helper $indexable_helper,
97 Meta_Tags_Context_Memoizer_Adapter $adapter,
98 Aggregator_Config $config,
99 Schema_Enhancement_Factory $enhancement_factory,
100 Indexable_Repository_Factory $indexable_repository_factory,
101 WordPress_Global_State_Adapter $global_state_adapter,
102 External_Schema_Piece_Repository_Interface ...$external_repositories
103 ) {
104 $this->memoizer = $memoizer;
105 $this->indexable_helper = $indexable_helper;
106 $this->adapter = $adapter;
107 $this->config = $config;
108 $this->enhancement_factory = $enhancement_factory;
109 $this->indexable_repository_factory = $indexable_repository_factory;
110 $this->global_state_adapter = $global_state_adapter;
111 $this->external_repositories = $external_repositories;
112 $this->logger = new NullLogger();
113 }
114
115 /**
116 * Gets the indexables to be aggregated.
117 *
118 * @param int $page The page number (1-based).
119 * @param int $page_size The number of items per page.
120 * @param string $post_type The post type to filter by.
121 *
122 * @return Schema_Piece_Collection The aggregated schema.
123 */
124 public function get( int $page, int $page_size, string $post_type ): Schema_Piece_Collection {
125 $indexable_repository = $this->indexable_repository_factory->get_repository( $this->indexable_helper->should_index_indexables() );
126 $indexables = $indexable_repository->get( $page, $page_size, $post_type );
127 $schema_pieces = [];
128
129 foreach ( $indexables as $indexable ) {
130 if ( ! \in_array( $indexable->object_sub_type, $this->config->get_allowed_post_types(), true ) ) {
131 continue;
132 }
133
134 $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
135 $context = $this->memoizer->get( $indexable, $page_type );
136
137 $this->global_state_adapter->set_global_state( $indexable, $context );
138 try {
139 $context_array = $this->adapter->meta_tags_context_to_array( $context );
140 $pieces_data = $context_array['@graph'];
141
142 $pieces_data = $this->collect_external_schema( $pieces_data, $post_type, $indexable->object_id );
143
144 foreach ( $pieces_data as $piece_data ) {
145 $schema_piece = new Schema_Piece( $piece_data, $piece_data['@type'] );
146 $enhancer = $this->enhancement_factory->get_enhancer( $this->get_all_schema_types( $context_array['@graph'] ) );
147 if ( $enhancer !== null ) {
148 $schema_piece = $enhancer->enhance( $schema_piece, $indexable );
149 }
150 $schema_pieces[] = $schema_piece;
151 }
152 } catch ( Throwable $e ) {
153 $this->logger->warning(
154 'Schema aggregation failed for indexable #{indexable_id} ({object_type}/{object_sub_type}): {message}',
155 [
156 'indexable_id' => $indexable->id,
157 'object_type' => $indexable->object_type,
158 'object_sub_type' => $indexable->object_sub_type,
159 'message' => $e->getMessage(),
160 ],
161 );
162 } finally {
163 $this->global_state_adapter->reset_global_state();
164 }
165 }
166
167 return new Schema_Piece_Collection( $schema_pieces );
168 }
169
170 /**
171 * Collects external schema pieces from all supporting repositories.
172 *
173 * @param array<array<string,string|int|bool|array>> $pieces_data The existing schema pieces.
174 * @param string $post_type The post type.
175 * @param int $post_id The post ID.
176 *
177 * @return array<array<string,string|int|bool|array>> The schema pieces with external pieces added.
178 */
179 private function collect_external_schema( array $pieces_data, string $post_type, int $post_id ): array {
180 foreach ( $this->external_repositories as $repository ) {
181 if ( $repository->supports( $post_type ) ) {
182 $external_pieces = $repository->collect( $post_id );
183 $pieces_data = \array_merge( $pieces_data, $external_pieces );
184 }
185 }
186
187 return $pieces_data;
188 }
189
190 /**
191 * All schema types present in the schema piece.
192 *
193 * @param array<array<string>> $graph The current graph.
194 *
195 * @return array<string>
196 */
197 private function get_all_schema_types( array $graph ): array {
198 $schema_types = [];
199 foreach ( $graph as $schema_values ) {
200 foreach ( $schema_values as $key => $value ) {
201 if ( $key === '@type' ) {
202 if ( \is_array( $value ) ) {
203 foreach ( $value as $type_value ) {
204 $schema_types[ $type_value ] = $type_value;
205 }
206 continue;
207 }
208 $schema_types[ $value ] = $value;
209 }
210 }
211 }
212
213 return $schema_types;
214 }
215 }
216