• 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

72.53
/src/surfaces/meta-surface.php
1
<?php
2

3
namespace Yoast\WP\SEO\Surfaces;
4

5
use Yoast\WP\SEO\Context\Meta_Tags_Context;
6
use Yoast\WP\SEO\Helpers\Indexable_Helper;
7
use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
8
use Yoast\WP\SEO\Models\Indexable;
9
use Yoast\WP\SEO\Repositories\Indexable_Repository;
10
use Yoast\WP\SEO\Surfaces\Values\Meta;
11
use Yoast\WP\SEO\Wrappers\WP_Rewrite_Wrapper;
12
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
13

14
/**
15
 * Meta_Surface class.
16
 *
17
 * Surface for the indexables.
18
 */
19
class Meta_Surface {
20

21
        /**
22
         * The container.
23
         *
24
         * @var ContainerInterface
25
         */
26
        private $container;
27

28
        /**
29
         * The memoizer for the meta tags context.
30
         *
31
         * @var Meta_Tags_Context_Memoizer
32
         */
33
        private $context_memoizer;
34

35
        /**
36
         * The indexable repository.
37
         *
38
         * @var Indexable_Repository
39
         */
40
        private $repository;
41

42
        /**
43
         * Holds the WP rewrite wrapper instance.
44
         *
45
         * @var WP_Rewrite_Wrapper
46
         */
47
        private $wp_rewrite_wrapper;
48

49
        /**
50
         * The indexable helper.
51
         *
52
         * @var Indexable_Helper
53
         */
54
        private $indexable_helper;
55

56
        /**
57
         * Meta_Surface constructor.
58
         *
59
         * @param ContainerInterface         $container            The DI container.
60
         * @param Meta_Tags_Context_Memoizer $context_memoizer     The meta tags context memoizer.
61
         * @param Indexable_Repository       $indexable_repository The indexable repository.
62
         * @param WP_Rewrite_Wrapper         $wp_rewrite_wrapper   The WP rewrite wrapper.
63
         * @param Indexable_Helper           $indexable_helper     The indexable helper.
64
         */
65
        public function __construct(
×
66
                ContainerInterface $container,
67
                Meta_Tags_Context_Memoizer $context_memoizer,
68
                Indexable_Repository $indexable_repository,
69
                WP_Rewrite_Wrapper $wp_rewrite_wrapper,
70
                Indexable_Helper $indexable_helper
71
        ) {
72
                $this->container          = $container;
×
73
                $this->context_memoizer   = $context_memoizer;
×
74
                $this->repository         = $indexable_repository;
×
75
                $this->wp_rewrite_wrapper = $wp_rewrite_wrapper;
×
76
                $this->indexable_helper   = $indexable_helper;
×
77
        }
78

79
        /**
80
         * Returns the meta tags context for the current page.
81
         *
82
         * @return Meta The meta values.
83
         */
84
        public function for_current_page() {
2✔
85
                return $this->build_meta( $this->context_memoizer->for_current_page() );
2✔
86
        }
87

88
        /**
89
         * Returns the meta tags context for the home page.
90
         *
91
         * @return Meta|false The meta values. False if none could be found.
92
         */
93
        public function for_home_page() {
10✔
94
                $front_page_id = (int) \get_option( 'page_on_front' );
10✔
95
                if ( \get_option( 'show_on_front' ) === 'page' && $front_page_id !== 0 ) {
10✔
96
                        $indexable = $this->repository->find_by_id_and_type( $front_page_id, 'post' );
4✔
97

98
                        if ( ! $indexable ) {
4✔
99
                                return false;
2✔
100
                        }
101

102
                        return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Home_Page' ) );
2✔
103
                }
104

105
                $indexable = $this->repository->find_for_home_page();
6✔
106

107
                if ( ! $indexable ) {
6✔
108
                        return false;
2✔
109
                }
110

111
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) );
4✔
112
        }
113

114
        /**
115
         * Returns the meta tags context for the posts page.
116
         *
117
         * @return Meta|false The meta values. False if none could be found.
118
         */
119
        public function for_posts_page() {
8✔
120
                $posts_page_id = (int) \get_option( 'page_for_posts' );
8✔
121
                if ( $posts_page_id !== 0 ) {
8✔
122
                        $indexable = $this->repository->find_by_id_and_type( $posts_page_id, 'post' );
4✔
123

124
                        if ( ! $indexable ) {
4✔
125
                                return false;
2✔
126
                        }
127

128
                        return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Posts_Page' ) );
2✔
129
                }
130

131
                $indexable = $this->repository->find_for_home_page();
4✔
132

133
                if ( ! $indexable ) {
4✔
134
                        return false;
2✔
135
                }
136

137
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) );
2✔
138
        }
139

140
        /**
141
         * Returns the meta tags context for a post type archive.
142
         *
143
         * @param string|null $post_type Optional. The post type to get the archive meta for. Defaults to the current post type.
144
         *
145
         * @return Meta|false The meta values. False if none could be found.
146
         */
147
        public function for_post_type_archive( $post_type = null ) {
4✔
148
                if ( $post_type === null ) {
4✔
149
                        $post_type = \get_post_type();
×
150
                }
151

152
                $indexable = $this->repository->find_for_post_type_archive( $post_type );
4✔
153

154
                if ( ! $indexable ) {
4✔
155
                        return false;
2✔
156
                }
157

158
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type_Archive' ) );
2✔
159
        }
160

161
        /**
162
         * Returns the meta tags context for the search result page.
163
         *
164
         * @return Meta|false The meta values. False if none could be found.
165
         */
166
        public function for_search_result() {
4✔
167
                $indexable = $this->repository->find_for_system_page( 'search-result' );
4✔
168

169
                if ( ! $indexable ) {
4✔
170
                        return false;
2✔
171
                }
172

173
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Search_Result_Page' ) );
2✔
174
        }
175

176
        /**
177
         * Returns the meta tags context for the search result page.
178
         *
179
         * @return Meta|false The meta values. False if none could be found.
180
         */
181
        public function for_404() {
4✔
182
                $indexable = $this->repository->find_for_system_page( '404' );
4✔
183

184
                if ( ! $indexable ) {
4✔
185
                        return false;
2✔
186
                }
187

188
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Error_Page' ) );
2✔
189
        }
190

191
        /**
192
         * Returns the meta tags context for a post.
193
         *
194
         * @param int $id The ID of the post.
195
         *
196
         * @return Meta|false The meta values. False if none could be found.
197
         */
198
        public function for_post( $id ) {
4✔
199
                $indexable = $this->repository->find_by_id_and_type( $id, 'post' );
4✔
200

201
                if ( ! $indexable ) {
4✔
202
                        return false;
2✔
203
                }
204

205
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) );
2✔
206
        }
207

208
        /**
209
         * Returns the meta tags context for a number of posts.
210
         *
211
         * @param int[] $ids The IDs of the posts.
212
         *
213
         * @return Meta[]|false The meta values. False if none could be found.
214
         */
215
        public function for_posts( $ids ) {
2✔
216
                $indexables = $this->repository->find_by_multiple_ids_and_type( $ids, 'post' );
2✔
217

218
                if ( empty( $indexables ) ) {
2✔
219
                        return false;
×
220
                }
221

222
                // Remove all false values.
223
                $indexables = \array_filter( $indexables );
2✔
224

225
                return \array_map(
2✔
226
                        function( $indexable ) {
1✔
227
                                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) );
2✔
228
                        },
2✔
229
                        $indexables
1✔
230
                );
1✔
231
        }
232

233
        /**
234
         * Returns the meta tags context for a term.
235
         *
236
         * @param int $id The ID of the term.
237
         *
238
         * @return Meta|false The meta values. False if none could be found.
239
         */
240
        public function for_term( $id ) {
2✔
241
                $indexable = $this->repository->find_by_id_and_type( $id, 'term' );
242

243
                if ( ! $indexable ) {
2✔
244
                        return false;
245
                }
246

247
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Term_Archive' ) );
248
        }
249

250
        /**
251
         * Returns the meta tags context for an author.
252
         *
253
         * @param int $id The ID of the author.
254
         *
255
         * @return Meta|false The meta values. False if none could be found.
256
         */
257
        public function for_author( $id ) {
2✔
258
                $indexable = $this->repository->find_by_id_and_type( $id, 'user' );
259

260
                if ( ! $indexable ) {
2✔
261
                        return false;
262
                }
263

264
                return $this->build_meta( $this->context_memoizer->get( $indexable, 'Author_Archive' ) );
265
        }
266

267
        /**
268
         * Returns the meta for an indexable.
269
         *
270
         * @param Indexable   $indexable The indexable.
271
         * @param string|null $page_type Optional. The page type if already known.
272
         *
273
         * @return Meta|false The meta values. False if none could be found.
274
         */
275
        public function for_indexable( $indexable, $page_type = null ) {
×
276

277
                if ( ! \is_a( $indexable, Indexable::class ) ) {
×
278
                        return false;
279
                }
280
                if ( \is_null( $page_type ) ) {
×
281
                        $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
282
                }
283

284
                return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) );
285
        }
286

287
        /**
288
         * Returns the meta for an indexable.
289
         *
290
         * @param Indexable[] $indexables The indexables.
291
         * @param string|null $page_type  Optional. The page type if already known.
292
         *
293
         * @return Meta|false The meta values. False if none could be found.
294
         */
295
        public function for_indexables( $indexables, $page_type = null ) {
×
296
                $closure = function( $indexable ) use ( $page_type ) {
297
                        $this_page_type = $page_type;
×
298
                        if ( \is_null( $this_page_type ) ) {
×
299
                                $this_page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
300
                        }
301

302
                        return $this->build_meta( $this->context_memoizer->get( $indexable, $this_page_type ) );
303
                };
304

305
                return \array_map( $closure, $indexables );
306
        }
307

308
        /**
309
         * Returns the meta tags context for a url.
310
         *
311
         * @param string $url The url of the page. Required to be relative to the site url.
312
         *
313
         * @return Meta|false The meta values. False if none could be found.
314
         */
315
        public function for_url( $url ) {
24✔
316
                $url_parts  = \wp_parse_url( $url );
24✔
317
                $site_parts = \wp_parse_url( \site_url() );
318

319
                if ( ( ! \is_array( $url_parts ) || ! \is_array( $site_parts ) )
24✔
320
                        || ! isset( $url_parts['host'], $url_parts['path'], $site_parts['host'], $site_parts['scheme'] )
321
                ) {
2✔
322
                        return false;
323
                }
324

325
                if ( $url_parts['host'] !== $site_parts['host'] ) {
×
326
                        return false;
327
                }
328
                // Ensure the scheme is consistent with values in the DB.
329
                $url = $site_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];
330

331
                if ( $this->is_date_archive_url( $url ) ) {
2✔
332
                        $indexable = $this->repository->find_for_date_archive();
333
                }
334
                else {
9✔
335
                        $indexable = $this->repository->find_by_permalink( $url );
336
                }
337

338
                // If we still don't have an indexable abort, the WP globals could be anything so we can't use the unknown indexable.
339
                if ( ! $indexable ) {
×
340
                        return false;
341
                }
10✔
342
                $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
343

344
                if ( $page_type === false ) {
×
345
                        return false;
346
                }
347

348
                return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) );
349
        }
350

351
        /**
352
         * Checks if a given URL is a date archive URL.
353
         *
354
         * @param string $url The url.
355
         *
356
         * @return bool
357
         */
358
        protected function is_date_archive_url( $url ) {
×
359
                $path = \wp_parse_url( $url, \PHP_URL_PATH );
×
360
                if ( $path === null ) {
×
361
                        return false;
362
                }
363

364
                $path         = \ltrim( $path, '/' );
×
365
                $wp_rewrite   = $this->wp_rewrite_wrapper->get();
×
366
                $date_rewrite = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), \EP_DATE );
×
367
                $date_rewrite = \apply_filters( 'date_rewrite_rules', $date_rewrite );
368

369
                foreach ( (array) $date_rewrite as $match => $query ) {
×
370
                        if ( \preg_match( "#^$match#", $path ) ) {
×
371
                                return true;
372
                        }
373
                }
374

375
                return false;
376
        }
377

378
        /**
379
         * Creates a new meta value object
380
         *
381
         * @param Meta_Tags_Context $context The meta tags context.
382
         *
383
         * @return Meta The meta value
384
         */
385
        protected function build_meta( Meta_Tags_Context $context ) {
386
                return new Meta( $context, $this->container );
387
        }
388
}
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

© 2026 Coveralls, Inc