• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 6987097851

25 Nov 2023 04:49AM UTC coverage: 49.206% (-0.1%) from 49.302%
6987097851

push

github

web-flow
Merge pull request #20878 from Yoast/JRF/ghactions-minor-tweak

GH Actions: update a few links in inline comments

15305 of 31104 relevant lines covered (49.21%)

4.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

20.48
/src/loader.php
1
<?php
2

3
namespace Yoast\WP\SEO;
4

5
use Throwable;
6
use WP_CLI;
7
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
8

9
/**
10
 * Class that manages loading integrations if and only if all their conditionals are met.
11
 */
12
class Loader {
13

14
        /**
15
         * The registered integrations.
16
         *
17
         * @var string[]
18
         */
19
        protected $integrations = [];
20

21
        /**
22
         * The registered integrations.
23
         *
24
         * @var string[]
25
         */
26
        protected $initializers = [];
27

28
        /**
29
         * The registered routes.
30
         *
31
         * @var string[]
32
         */
33
        protected $routes = [];
34

35
        /**
36
         * The registered commands.
37
         *
38
         * @var string[]
39
         */
40
        protected $commands = [];
41

42
        /**
43
         * The registered migrations.
44
         *
45
         * @var string[]
46
         */
47
        protected $migrations = [];
48

49
        /**
50
         * The dependency injection container.
51
         *
52
         * @var ContainerInterface
53
         */
54
        protected $container;
55

56
        /**
57
         * Loader constructor.
58
         *
59
         * @param ContainerInterface $container The dependency injection container.
60
         */
61
        public function __construct( ContainerInterface $container ) {
16✔
62
                $this->container = $container;
16✔
63
        }
8✔
64

65
        /**
66
         * Registers an integration.
67
         *
68
         * @param string $integration_class The class name of the integration to be loaded.
69
         *
70
         * @return void
71
         */
72
        public function register_integration( $integration_class ) {
8✔
73
                $this->integrations[] = $integration_class;
8✔
74
        }
4✔
75

76
        /**
77
         * Registers an initializer.
78
         *
79
         * @param string $initializer_class The class name of the initializer to be loaded.
80
         *
81
         * @return void
82
         */
83
        public function register_initializer( $initializer_class ) {
8✔
84
                $this->initializers[] = $initializer_class;
8✔
85
        }
4✔
86

87
        /**
88
         * Registers a route.
89
         *
90
         * @param string $route_class The class name of the route to be loaded.
91
         *
92
         * @return void
93
         */
94
        public function register_route( $route_class ) {
×
95
                $this->routes[] = $route_class;
×
96
        }
97

98
        /**
99
         * Registers a command.
100
         *
101
         * @param string $command_class The class name of the command to be loaded.
102
         *
103
         * @return void
104
         */
105
        public function register_command( $command_class ) {
×
106
                $this->commands[] = $command_class;
×
107
        }
108

109
        /**
110
         * Registers a migration.
111
         *
112
         * @param string $plugin          The plugin the migration belongs to.
113
         * @param string $version         The version of the migration.
114
         * @param string $migration_class The class name of the migration to be loaded.
115
         *
116
         * @return void
117
         */
118
        public function register_migration( $plugin, $version, $migration_class ) {
×
119
                if ( ! \array_key_exists( $plugin, $this->migrations ) ) {
×
120
                        $this->migrations[ $plugin ] = [];
×
121
                }
122

123
                $this->migrations[ $plugin ][ $version ] = $migration_class;
×
124
        }
125

126
        /**
127
         * Loads all registered classes if their conditionals are met.
128
         *
129
         * @return void
130
         */
131
        public function load() {
20✔
132
                $this->load_initializers();
20✔
133

134
                if ( ! \did_action( 'init' ) ) {
20✔
135
                        \add_action( 'init', [ $this, 'load_integrations' ] );
10✔
136
                }
137
                else {
138
                        $this->load_integrations();
10✔
139
                }
140

141
                \add_action( 'rest_api_init', [ $this, 'load_routes' ] );
20✔
142

143
                if ( \defined( 'WP_CLI' ) && \WP_CLI ) {
20✔
144
                        $this->load_commands();
×
145
                }
146
        }
10✔
147

148
        /**
149
         * Returns all registered migrations.
150
         *
151
         * @param string $plugin The plugin to get the migrations for.
152
         *
153
         * @return string[]|false The registered migrations. False if no migrations were registered.
154
         */
155
        public function get_migrations( $plugin ) {
×
156
                if ( ! \array_key_exists( $plugin, $this->migrations ) ) {
×
157
                        return false;
×
158
                }
159

160
                return $this->migrations[ $plugin ];
×
161
        }
162

163
        /**
164
         * Loads all registered commands.
165
         *
166
         * @return void
167
         */
168
        protected function load_commands() {
×
169
                foreach ( $this->commands as $class ) {
×
170
                        $command = $this->get_class( $class );
×
171

172
                        if ( $command === null ) {
×
173
                                continue;
×
174
                        }
175

176
                        WP_CLI::add_command( $class::get_namespace(), $command );
×
177
                }
178
        }
179

180
        /**
181
         * Loads all registered initializers if their conditionals are met.
182
         *
183
         * @return void
184
         */
185
        protected function load_initializers() {
×
186
                foreach ( $this->initializers as $class ) {
×
187
                        if ( ! $this->conditionals_are_met( $class ) ) {
×
188
                                continue;
×
189
                        }
190

191
                        $initializer = $this->get_class( $class );
×
192

193
                        if ( $initializer === null ) {
×
194
                                continue;
×
195
                        }
196

197
                        $initializer->initialize();
×
198
                }
199
        }
200

201
        /**
202
         * Loads all registered integrations if their conditionals are met.
203
         *
204
         * @return void
205
         */
206
        public function load_integrations() {
×
207
                foreach ( $this->integrations as $class ) {
×
208
                        if ( ! $this->conditionals_are_met( $class ) ) {
×
209
                                continue;
×
210
                        }
211

212
                        $integration = $this->get_class( $class );
×
213

214
                        if ( $integration === null ) {
×
215
                                continue;
×
216
                        }
217

218
                        $integration->register_hooks();
×
219
                }
220
        }
221

222
        /**
223
         * Loads all registered routes if their conditionals are met.
224
         *
225
         * @return void
226
         */
227
        public function load_routes() {
×
228
                foreach ( $this->routes as $class ) {
×
229
                        if ( ! $this->conditionals_are_met( $class ) ) {
×
230
                                continue;
×
231
                        }
232

233
                        $route = $this->get_class( $class );
×
234

235
                        if ( $route === null ) {
×
236
                                continue;
×
237
                        }
238

239
                        $route->register_routes();
×
240
                }
241
        }
242

243
        /**
244
         * Checks if all conditionals of a given loadable are met.
245
         *
246
         * @param string $loadable_class The class name of the loadable.
247
         *
248
         * @return bool Whether all conditionals of the loadable are met.
249
         */
250
        protected function conditionals_are_met( $loadable_class ) {
×
251
                // In production environments do not fatal if the class does not exist but log and fail gracefully.
252
                if ( \YOAST_ENVIRONMENT === 'production' && ! \class_exists( $loadable_class ) ) {
×
253
                        if ( \defined( 'WP_DEBUG' ) && \WP_DEBUG ) {
×
254
                                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
255
                                \error_log(
×
256
                                        \sprintf(
×
257
                                                /* translators: %1$s expands to Yoast SEO, %2$s expands to the name of the class that could not be found. */
258
                                                \__( '%1$s attempted to load the class %2$s but it could not be found.', 'wordpress-seo' ),
×
259
                                                'Yoast SEO',
×
260
                                                $loadable_class
×
261
                                        )
262
                                );
263
                        }
264
                        return false;
×
265
                }
266

267
                $conditionals = $loadable_class::get_conditionals();
×
268
                foreach ( $conditionals as $class ) {
×
269
                        $conditional = $this->get_class( $class );
×
270
                        if ( $conditional === null || ! $conditional->is_met() ) {
×
271
                                return false;
×
272
                        }
273
                }
274

275
                return true;
×
276
        }
277

278
        /**
279
         * Gets a class from the container.
280
         *
281
         * @param string $class_name The class name.
282
         *
283
         * @return object|null The class or, in production environments, null if it does not exist.
284
         *
285
         * @throws Throwable If the class does not exist in development environments.
286
         */
287
        protected function get_class( $class_name ) {
×
288
                try {
289
                        return $this->container->get( $class_name );
×
290
                } catch ( Throwable $e ) {
×
291
                        // In production environments do not fatal if the class could not be constructed but log and fail gracefully.
292
                        if ( \YOAST_ENVIRONMENT === 'production' ) {
×
293
                                if ( \defined( 'WP_DEBUG' ) && \WP_DEBUG ) {
×
294
                                        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
295
                                        \error_log( $e->getMessage() );
×
296
                                }
297
                                return null;
×
298
                        }
299
                        throw $e;
×
300
                }
301
        }
302
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc