PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
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 19.0 All 129 releases
← All changes | src/loader.php +85 -11 18.628.5 View file →
@@ -1,8 +1,9 @@
1 1 <?php
2 2
3 3 namespace Yoast\WP\SEO;
4 4
5 +use Throwable;
5 6 use WP_CLI;
6 7 use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
7 8
8 9 /**
@@ -161,14 +162,27 @@
161 162
162 163 /**
163 164 * Loads all registered commands.
164 165 *
166 + * Commands that opt in to conditional loading by implementing
167 + * Loadable_Interface are skipped when their conditionals are not met.
168 + *
165 169 * @return void
166 170 */
167 171 protected function load_commands() {
168 172 foreach ( $this->commands as $class ) {
169 - $command = $this->container->get( $class );
173 + if ( \is_subclass_of( $class, Loadable_Interface::class )
174 + && ! $this->conditionals_are_met( $class )
175 + ) {
176 + continue;
177 + }
170 178
179 + $command = $this->get_class( $class );
180 +
181 + if ( $command === null ) {
182 + continue;
183 + }
184 +
171 185 WP_CLI::add_command( $class::get_namespace(), $command );
172 186 }
173 187 }
174 188
@@ -182,9 +196,15 @@
182 196 if ( ! $this->conditionals_are_met( $class ) ) {
183 197 continue;
184 198 }
185 199
186 - $this->container->get( $class )->initialize();
200 + $initializer = $this->get_class( $class );
201 +
202 + if ( $initializer === null ) {
203 + continue;
204 + }
205 +
206 + $initializer->initialize();
187 207 }
188 208 }
189 209
190 210 /**
@@ -197,9 +217,15 @@
197 217 if ( ! $this->conditionals_are_met( $class ) ) {
198 218 continue;
199 219 }
200 220
201 - $this->container->get( $class )->register_hooks();
221 + $integration = $this->get_class( $class );
222 +
223 + if ( $integration === null ) {
224 + continue;
225 + }
226 +
227 + $integration->register_hooks();
202 228 }
203 229 }
204 230
205 231 /**
@@ -212,26 +238,74 @@
212 238 if ( ! $this->conditionals_are_met( $class ) ) {
213 239 continue;
214 240 }
215 241
216 - $this->container->get( $class )->register_routes();
242 + $route = $this->get_class( $class );
243 +
244 + if ( $route === null ) {
245 + continue;
246 + }
247 +
248 + $route->register_routes();
217 249 }
218 250 }
219 251
220 252 /**
221 - * Checks if all conditionals of a given integration are met.
253 + * Checks if all conditionals of a given loadable are met.
222 254 *
223 - * @param Loadable_Interface $integration_class The class name of the integration.
255 + * @param string $loadable_class The class name of the loadable.
224 256 *
225 - * @return bool Whether or not all conditionals of the integration are met.
257 + * @return bool Whether all conditionals of the loadable are met.
226 258 */
227 - protected function conditionals_are_met( $integration_class ) {
228 - $conditionals = $integration_class::get_conditionals();
229 - foreach ( $conditionals as $conditional ) {
230 - if ( ! $this->container->get( $conditional )->is_met() ) {
259 + protected function conditionals_are_met( $loadable_class ) {
260 + // In production environments do not fatal if the class does not exist but log and fail gracefully.
261 + if ( \YOAST_ENVIRONMENT === 'production' && ! \class_exists( $loadable_class ) ) {
262 + if ( \defined( 'WP_DEBUG' ) && \WP_DEBUG ) {
263 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
264 + \error_log(
265 + \sprintf(
266 + /* translators: %1$s expands to Yoast SEO, %2$s expands to the name of the class that could not be found. */
267 + \__( '%1$s attempted to load the class %2$s but it could not be found.', 'wordpress-seo' ),
268 + 'Yoast SEO',
269 + $loadable_class,
270 + ),
271 + );
272 + }
273 + return false;
274 + }
275 +
276 + $conditionals = $loadable_class::get_conditionals();
277 + foreach ( $conditionals as $class ) {
278 + $conditional = $this->get_class( $class );
279 + if ( $conditional === null || ! $conditional->is_met() ) {
231 280 return false;
232 281 }
233 282 }
234 283
235 284 return true;
285 + }
286 +
287 + /**
288 + * Gets a class from the container.
289 + *
290 + * @param string $class_name The class name.
291 + *
292 + * @return object|null The class or, in production environments, null if it does not exist.
293 + *
294 + * @throws Throwable If the class does not exist in development environments.
295 + */
296 + protected function get_class( $class_name ) {
297 + try {
298 + return $this->container->get( $class_name );
299 + } catch ( Throwable $e ) {
300 + // In production environments do not fatal if the class could not be constructed but log and fail gracefully.
301 + if ( \YOAST_ENVIRONMENT === 'production' ) {
302 + if ( \defined( 'WP_DEBUG' ) && \WP_DEBUG ) {
303 + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
304 + \error_log( $e->getMessage() );
305 + }
306 + return null;
307 + }
308 + throw $e;
309 + }
236 310 }
237 311 }