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

Yoast / wordpress-seo / 52612d7369b0288e23ed59f15bc91909484d4b2c

23 May 2025 01:34PM UTC coverage: 38.951%. First build
52612d7369b0288e23ed59f15bc91909484d4b2c

Pull #22305

github

web-flow
Merge a08cc820a into adfa0279b
Pull Request #22305: Move ai generator integrations

2176 of 8301 branches covered (26.21%)

Branch coverage included in aggregate %.

0 of 120 new or added lines in 4 files covered. (0.0%)

20139 of 48989 relevant lines covered (41.11%)

4.46 hits per line

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

74.31
/src/helpers/current-page-helper.php
1
<?php
2

3
namespace Yoast\WP\SEO\Helpers;
4

5
use WP_Post;
6
use Yoast\WP\SEO\Wrappers\WP_Query_Wrapper;
7

8
/**
9
 * A helper object for WordPress posts.
10
 */
11
class Current_Page_Helper {
12

13
        /**
14
         * The WP Query wrapper.
15
         *
16
         * @var WP_Query_Wrapper
17
         */
18
        private $wp_query_wrapper;
19

20
        /**
21
         * Current_Page_Helper constructor.
22
         *
23
         * @codeCoverageIgnore It only sets dependencies.
24
         *
25
         * @param WP_Query_Wrapper $wp_query_wrapper The wrapper for WP_Query.
26
         */
27
        public function __construct( WP_Query_Wrapper $wp_query_wrapper ) {
28
                $this->wp_query_wrapper = $wp_query_wrapper;
29
        }
30

31
        /**
32
         * Returns the page type for the current request.
33
         *
34
         * @codeCoverageIgnore It just depends on other functions for its result.
35
         *
36
         * @return string Page type.
37
         */
38
        public function get_page_type() {
39
                switch ( true ) {
40
                        case $this->is_search_result():
41
                                return 'Search_Result_Page';
42
                        case $this->is_static_posts_page():
43
                                return 'Static_Posts_Page';
44
                        case $this->is_home_static_page():
45
                                return 'Static_Home_Page';
46
                        case $this->is_home_posts_page():
47
                                return 'Home_Page';
48
                        case $this->is_simple_page():
49
                                return 'Post_Type';
50
                        case $this->is_post_type_archive():
51
                                return 'Post_Type_Archive';
52
                        case $this->is_term_archive():
53
                                return 'Term_Archive';
54
                        case $this->is_author_archive():
55
                                return 'Author_Archive';
56
                        case $this->is_date_archive():
57
                                return 'Date_Archive';
58
                        case $this->is_404():
59
                                return 'Error_Page';
60
                }
61

62
                return 'Fallback';
63
        }
64

65
        /**
66
         * Checks if the currently opened page is a simple page.
67
         *
68
         * @return bool Whether the currently opened page is a simple page.
69
         */
70
        public function is_simple_page() {
2✔
71
                return $this->get_simple_page_id() > 0;
2✔
72
        }
73

74
        /**
75
         * Returns the id of the currently opened page.
76
         *
77
         * @return int The id of the currently opened page.
78
         */
79
        public function get_simple_page_id() {
6✔
80
                if ( \is_singular() ) {
6✔
81
                        return \get_the_ID();
2✔
82
                }
83

84
                if ( $this->is_posts_page() ) {
4✔
85
                        return \get_option( 'page_for_posts' );
2✔
86
                }
87

88
                /**
89
                 * Filter: Allow changing the default page id.
90
                 *
91
                 * @param int $page_id The default page id.
92
                 */
93
                return \apply_filters( 'wpseo_frontend_page_type_simple_page_id', 0 );
2✔
94
        }
95

96
        /**
97
         * Returns the id of the currently opened author archive.
98
         *
99
         * @codeCoverageIgnore It wraps WordPress functionality.
100
         *
101
         * @return int The id of the currently opened author archive.
102
         */
103
        public function get_author_id() {
104
                $wp_query = $this->wp_query_wrapper->get_main_query();
105

106
                return $wp_query->get( 'author' );
107
        }
108

109
        /**
110
         * Returns the id of the front page.
111
         *
112
         * @return int The id of the front page. 0 if the front page is not a static page.
113
         */
114
        public function get_front_page_id() {
4✔
115
                if ( \get_option( 'show_on_front' ) !== 'page' ) {
4✔
116
                        return 0;
2✔
117
                }
118

119
                return (int) \get_option( 'page_on_front' );
2✔
120
        }
121

122
        /**
123
         * Returns the id of the currently opened term archive.
124
         *
125
         * @return int The id of the currently opened term archive.
126
         */
127
        public function get_term_id() {
16✔
128
                $wp_query = $this->wp_query_wrapper->get_main_query();
16✔
129

130
                if ( $wp_query->is_tax() || $wp_query->is_tag() || $wp_query->is_category() ) {
16✔
131
                        $queried_object = $wp_query->get_queried_object();
16✔
132
                        if ( $queried_object && ! \is_wp_error( $queried_object ) ) {
16✔
133
                                return $queried_object->term_id;
14✔
134
                        }
135
                }
136

137
                return 0;
2✔
138
        }
139

140
        /**
141
         * Returns the post type of the main query.
142
         *
143
         * @return string The post type of the main query.
144
         */
145
        public function get_queried_post_type() {
4✔
146
                $wp_query  = $this->wp_query_wrapper->get_main_query();
4✔
147
                $post_type = $wp_query->get( 'post_type' );
4✔
148
                if ( \is_array( $post_type ) ) {
4✔
149
                        $post_type = \reset( $post_type );
2✔
150
                }
151

152
                return $post_type;
4✔
153
        }
154

155
        /**
156
         * Returns the permalink of the currently opened date archive.
157
         * If the permalink was cached, it returns this permalink.
158
         * If not, we call another function to get the permalink through wp_query.
159
         *
160
         * @return string The permalink of the currently opened date archive.
161
         */
162
        public function get_date_archive_permalink() {
4✔
163
                static $date_archive_permalink;
4✔
164

165
                if ( isset( $date_archive_permalink ) ) {
4✔
166
                        return $date_archive_permalink;
2✔
167
                }
168

169
                $date_archive_permalink = $this->get_non_cached_date_archive_permalink();
2✔
170

171
                return $date_archive_permalink;
2✔
172
        }
173

174
        /**
175
         * Determine whether this is the homepage and shows posts.
176
         *
177
         * @return bool Whether or not the current page is the homepage that displays posts.
178
         */
179
        public function is_home_posts_page() {
6✔
180
                $wp_query = $this->wp_query_wrapper->get_main_query();
6✔
181

182
                if ( ! $wp_query->is_home() ) {
6✔
183
                        return false;
2✔
184
                }
185

186
                /*
187
                 * Whether the static page's `Homepage` option is actually not set to a page.
188
                 * Otherwise WordPress proceeds to handle the homepage as a `Your latest posts` page.
189
                 */
190
                if ( (int) \get_option( 'page_on_front' ) === 0 ) {
4✔
191
                        return true;
2✔
192
                }
193

194
                return \get_option( 'show_on_front' ) === 'posts';
2✔
195
        }
196

197
        /**
198
         * Determine whether this is the static frontpage.
199
         *
200
         * @return bool Whether or not the current page is a static frontpage.
201
         */
202
        public function is_home_static_page() {
6✔
203
                $wp_query = $this->wp_query_wrapper->get_main_query();
6✔
204

205
                if ( ! $wp_query->is_front_page() ) {
6✔
206
                        return false;
2✔
207
                }
208

209
                if ( \get_option( 'show_on_front' ) !== 'page' ) {
4✔
210
                        return false;
2✔
211
                }
212

213
                return $wp_query->is_page( \get_option( 'page_on_front' ) );
2✔
214
        }
215

216
        /**
217
         * Determine whether this is the static posts page.
218
         *
219
         * @return bool Whether or not the current page is a static posts page.
220
         */
221
        public function is_static_posts_page() {
6✔
222
                $wp_query       = $this->wp_query_wrapper->get_main_query();
6✔
223
                $queried_object = $wp_query->get_queried_object();
6✔
224

225
                return (
6✔
226
                        $wp_query->is_posts_page
6✔
227
                        && \is_a( $queried_object, WP_Post::class )
6✔
228
                        && $queried_object->post_type === 'page'
6✔
229
                );
6✔
230
        }
231

232
        /**
233
         * Determine whether this is the statically set posts page, when it's not the frontpage.
234
         *
235
         * @return bool Whether or not it's a non-frontpage, statically set posts page.
236
         */
237
        public function is_posts_page() {
6✔
238
                $wp_query = $this->wp_query_wrapper->get_main_query();
6✔
239

240
                if ( ! $wp_query->is_home() ) {
6✔
241
                        return false;
2✔
242
                }
243

244
                return \get_option( 'show_on_front' ) === 'page';
4✔
245
        }
246

247
        /**
248
         * Determine whether this is a post type archive.
249
         *
250
         * @codeCoverageIgnore It wraps WordPress functionality.
251
         *
252
         * @return bool Whether nor not the current page is a post type archive.
253
         */
254
        public function is_post_type_archive() {
255
                $wp_query = $this->wp_query_wrapper->get_main_query();
256

257
                return $wp_query->is_post_type_archive();
258
        }
259

260
        /**
261
         * Determine whether this is a term archive.
262
         *
263
         * @codeCoverageIgnore It wraps WordPress functionality.
264
         *
265
         * @return bool Whether nor not the current page is a term archive.
266
         */
267
        public function is_term_archive() {
268
                $wp_query = $this->wp_query_wrapper->get_main_query();
269

270
                return $wp_query->is_tax || $wp_query->is_tag || $wp_query->is_category;
271
        }
272

273
        /**
274
         * Determine whether this is an attachment page.
275
         *
276
         * @codeCoverageIgnore It wraps WordPress functionality.
277
         *
278
         * @return bool Whether nor not the current page is an attachment page.
279
         */
280
        public function is_attachment() {
281
                $wp_query = $this->wp_query_wrapper->get_main_query();
282

283
                return $wp_query->is_attachment;
284
        }
285

286
        /**
287
         * Determine whether this is an author archive.
288
         *
289
         * @codeCoverageIgnore It wraps WordPress functionality.
290
         *
291
         * @return bool Whether nor not the current page is an author archive.
292
         */
293
        public function is_author_archive() {
294
                $wp_query = $this->wp_query_wrapper->get_main_query();
295

296
                return $wp_query->is_author();
297
        }
298

299
        /**
300
         * Determine whether this is an date archive.
301
         *
302
         * @codeCoverageIgnore It wraps WordPress functionality.
303
         *
304
         * @return bool Whether nor not the current page is an date archive.
305
         */
306
        public function is_date_archive() {
307
                $wp_query = $this->wp_query_wrapper->get_main_query();
308

309
                return $wp_query->is_date();
310
        }
311

312
        /**
313
         * Determine whether this is a search result.
314
         *
315
         * @codeCoverageIgnore It wraps WordPress functionality.
316
         *
317
         * @return bool Whether nor not the current page is a search result.
318
         */
319
        public function is_search_result() {
320
                $wp_query = $this->wp_query_wrapper->get_main_query();
321

322
                return $wp_query->is_search();
323
        }
324

325
        /**
326
         * Determine whether this is a 404 page.
327
         *
328
         * @codeCoverageIgnore It wraps WordPress functionality.
329
         *
330
         * @return bool Whether nor not the current page is a 404 page.
331
         */
332
        public function is_404() {
333
                $wp_query = $this->wp_query_wrapper->get_main_query();
334

335
                return $wp_query->is_404();
336
        }
337

338
        /**
339
         * Checks if the current page is the post format archive.
340
         *
341
         * @codeCoverageIgnore It wraps WordPress functionality.
342
         *
343
         * @return bool Whether or not the current page is the post format archive.
344
         */
345
        public function is_post_format_archive() {
346
                $wp_query = $this->wp_query_wrapper->get_main_query();
347

348
                return $wp_query->is_tax( 'post_format' );
349
        }
350

351
        /**
352
         * Determine whether this page is an taxonomy archive page for multiple terms (url: /term-1,term2/).
353
         *
354
         * @return bool Whether or not the current page is an archive page for multiple terms.
355
         */
356
        public function is_multiple_terms_page() {
6✔
357
                if ( ! $this->is_term_archive() ) {
6✔
358
                        return false;
2✔
359
                }
360

361
                return $this->count_queried_terms() > 1;
4✔
362
        }
363

364
        /**
365
         * Checks whether the current page is paged.
366
         *
367
         * @codeCoverageIgnore This method only calls a WordPress function.
368
         *
369
         * @return bool Whether the current page is paged.
370
         */
371
        public function is_paged() {
372
                return \is_paged();
373
        }
374

375
        /**
376
         * Checks if the current page is the front page.
377
         *
378
         * @codeCoverageIgnore It wraps WordPress functionality.
379
         *
380
         * @return bool Whether or not the current page is the front page.
381
         */
382
        public function is_front_page() {
383
                $wp_query = $this->wp_query_wrapper->get_main_query();
384

385
                return $wp_query->is_front_page();
386
        }
387

388
        /**
389
         * Retrieves the current admin page.
390
         *
391
         * @codeCoverageIgnore It only wraps a global WordPress variable.
392
         *
393
         * @return string The current page.
394
         */
395
        public function get_current_admin_page() {
396
                global $pagenow;
397

398
                return $pagenow;
399
        }
400

401
        /**
402
         * Check if the current opened page is a Yoast SEO page.
403
         *
404
         * @return bool True when current page is a yoast seo plugin page.
405
         */
406
        public function is_yoast_seo_page() {
8✔
407
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
408
                if ( isset( $_GET['page'] ) && \is_string( $_GET['page'] ) ) {
8✔
409
                        // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information, We are only using the variable in the strpos function.
410
                        $current_page = \wp_unslash( $_GET['page'] );
2✔
411
                        return \strpos( $current_page, 'wpseo_' ) === 0;
2✔
412
                }
413
                return false;
6✔
414
        }
415

416
        /**
417
         * Returns the current Yoast SEO page.
418
         * (E.g. the `page` query variable in the URL).
419
         *
420
         * @return string The current Yoast SEO page.
421
         */
422
        public function get_current_yoast_seo_page() {
8✔
423
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
424
                if ( isset( $_GET['page'] ) && \is_string( $_GET['page'] ) ) {
8✔
425
                        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
426
                        return \sanitize_text_field( \wp_unslash( $_GET['page'] ) );
2✔
427
                }
428

429
                return '';
6✔
430
        }
431

432
        /**
433
         * Checks if the current global post is the privacy policy page.
434
         *
435
         * @return bool current global post is set as privacy page
436
         */
437
        public function current_post_is_privacy_policy() {
×
438
                global $post;
×
439

440
                if ( ! isset( $post->ID ) ) {
×
441
                        return false;
×
442
                }
443

444
                return \intval( $post->ID ) === \intval( \get_option( 'wp_page_for_privacy_policy', false ) );
×
445
        }
446

447
        /**
448
         * Returns the permalink of the currently opened date archive.
449
         *
450
         * @return string The permalink of the currently opened date archive.
451
         */
452
        protected function get_non_cached_date_archive_permalink() {
8✔
453
                $date_archive_permalink = '';
8✔
454
                $wp_query               = $this->wp_query_wrapper->get_main_query();
8✔
455

456
                if ( $wp_query->is_day() ) {
8✔
457
                        $date_archive_permalink = \get_day_link( $wp_query->get( 'year' ), $wp_query->get( 'monthnum' ), $wp_query->get( 'day' ) );
2✔
458
                }
459
                if ( $wp_query->is_month() ) {
8✔
460
                        $date_archive_permalink = \get_month_link( $wp_query->get( 'year' ), $wp_query->get( 'monthnum' ) );
2✔
461
                }
462
                if ( $wp_query->is_year() ) {
8✔
463
                        $date_archive_permalink = \get_year_link( $wp_query->get( 'year' ) );
2✔
464
                }
465

466
                return $date_archive_permalink;
8✔
467
        }
468

469
        /**
470
         * Counts the total amount of queried terms.
471
         *
472
         * @codeCoverageIgnore This relies too much on WordPress dependencies.
473
         *
474
         * @return int The amoumt of queried terms.
475
         */
476
        protected function count_queried_terms() {
477
                $wp_query = $this->wp_query_wrapper->get_main_query();
478
                $term     = $wp_query->get_queried_object();
479

480
                $queried_terms = $wp_query->tax_query->queried_terms;
481
                if ( $term === null || empty( $queried_terms[ $term->taxonomy ]['terms'] ) ) {
482
                        return 0;
483
                }
484

485
                return \count( $queried_terms[ $term->taxonomy ]['terms'] );
486
        }
487

488
        /**
489
         * Retrieves the current post id.
490
         * Returns 0 if no post id is found.
491
         *
492
         * @return int The post id.
493
         */
NEW
494
        public function get_current_post_id(): int {
×
495
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information, We are casting to an integer.
NEW
496
                if ( isset( $_GET['post'] ) && \is_string( $_GET['post'] ) && (int) \wp_unslash( $_GET['post'] ) > 0 ) {
×
497
                        // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information, We are casting to an integer, also this is a helper function.
NEW
498
                        return (int) \wp_unslash( $_GET['post'] );
×
499
                }
NEW
500
                return 0;
×
501
        }
502

503
        /**
504
         * Retrieves the current post type.
505
         *
506
         * @return string The post type.
507
         */
NEW
508
        public function get_current_post_type(): string {
×
509
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
NEW
510
                if ( isset( $_GET['post_type'] ) && \is_string( $_GET['post_type'] ) ) {
×
511
                        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
NEW
512
                        return \sanitize_text_field( \wp_unslash( $_GET['post_type'] ) );
×
513
                }
514

515
                // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: should be done outside the helper function.
NEW
516
                if ( isset( $_POST['post_type'] ) && \is_string( $_POST['post_type'] ) ) {
×
517
                        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: should be done outside the helper function.
NEW
518
                        return \sanitize_text_field( \wp_unslash( $_POST['post_type'] ) );
×
519
                }
520

NEW
521
                $post_id = $this->get_current_post_id();
×
522

NEW
523
                if ( $post_id ) {
×
NEW
524
                        return \get_post_type( $post_id );
×
525
                }
526

NEW
527
                return 'post';
×
528
        }
529

530
        /**
531
         * Retrieves the current taxonomy.
532
         *
533
         * @return string The taxonomy.
534
         */
NEW
535
        public function get_current_taxonomy(): string {
×
NEW
536
                if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || ! \in_array( $_SERVER['REQUEST_METHOD'], [ 'GET', 'POST' ], true ) ) {
×
NEW
537
                        return '';
×
538
                }
539

540
                // phpcs:ignore WordPress.Security.NonceVerification -- Reason: We are not processing form information.
NEW
541
                if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
×
542
                        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: should be done outside the helper function.
NEW
543
                        if ( isset( $_POST['taxonomy'] ) && \is_string( $_POST['taxonomy'] ) ) {
×
544
                                // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: should be done outside the helper function.
NEW
545
                                return \sanitize_text_field( \wp_unslash( $_POST['taxonomy'] ) );
×
546
                        }
NEW
547
                        return '';
×
548
                }
549

550
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
NEW
551
                if ( isset( $_GET['taxonomy'] ) && \is_string( $_GET['taxonomy'] ) ) {
×
552
                        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
NEW
553
                        return \sanitize_text_field( \wp_unslash( $_GET['taxonomy'] ) );
×
554
                }
555

NEW
556
                return '';
×
557
        }
558
}
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