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

Yoast / wordpress-seo / 0fdb51d5ef87fb55b55da5a950cf7350c155980d

11 Mar 2025 10:16AM UTC coverage: 53.422% (-1.3%) from 54.687%
0fdb51d5ef87fb55b55da5a950cf7350c155980d

push

github

web-flow
Merge pull request #22086 from Yoast/add-pregnant-women-to-potentially-non-inclusive-phrases

Inclusive language: Add 'pregnant women' to potentially non-inclusive phrases

7918 of 13987 branches covered (56.61%)

Branch coverage included in aggregate %.

30526 of 57976 relevant lines covered (52.65%)

41097.18 hits per line

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

8.86
/inc/class-wpseo-admin-bar-menu.php
1
<?php
2
/**
3
 * WPSEO plugin file.
4
 *
5
 * @package WPSEO
6
 */
7

8
use Yoast\WP\SEO\Helpers\Product_Helper;
9
use Yoast\WP\SEO\Helpers\Score_Icon_Helper;
10
use Yoast\WP\SEO\Integrations\Support_Integration;
11
use Yoast\WP\SEO\Models\Indexable;
12
use Yoast\WP\SEO\Presenters\Admin\Premium_Badge_Presenter;
13
use Yoast\WP\SEO\Promotions\Application\Promotion_Manager;
14
use Yoast\WP\SEO\Repositories\Indexable_Repository;
15

16
/**
17
 * Class for the Yoast SEO admin bar menu.
18
 */
19
class WPSEO_Admin_Bar_Menu implements WPSEO_WordPress_Integration {
20

21
        /**
22
         * The identifier used for the menu.
23
         *
24
         * @var string
25
         */
26
        public const MENU_IDENTIFIER = 'wpseo-menu';
27

28
        /**
29
         * The identifier used for the Keyword Research submenu.
30
         *
31
         * @var string
32
         */
33
        public const KEYWORD_RESEARCH_SUBMENU_IDENTIFIER = 'wpseo-kwresearch';
34

35
        /**
36
         * The identifier used for the Analysis submenu.
37
         *
38
         * @var string
39
         */
40
        public const ANALYSIS_SUBMENU_IDENTIFIER = 'wpseo-analysis';
41

42
        /**
43
         * The identifier used for the Settings submenu.
44
         *
45
         * @var string
46
         */
47
        public const SETTINGS_SUBMENU_IDENTIFIER = 'wpseo-settings';
48

49
        /**
50
         * The identifier used for the Network Settings submenu.
51
         *
52
         * @var string
53
         */
54
        public const NETWORK_SETTINGS_SUBMENU_IDENTIFIER = 'wpseo-network-settings';
55

56
        /**
57
         * Asset manager instance.
58
         *
59
         * @var WPSEO_Admin_Asset_Manager
60
         */
61
        protected $asset_manager;
62

63
        /**
64
         * Holds the Score_Icon_Helper instance.
65
         *
66
         * @var Score_Icon_Helper
67
         */
68
        protected $indexable_repository;
69

70
        /**
71
         * Holds the Score_Icon_Helper instance.
72
         *
73
         * @var Score_Icon_Helper
74
         */
75
        protected $score_icon_helper;
76

77
        /**
78
         * Holds the Product_Helper instance.
79
         *
80
         * @var Product_Helper
81
         */
82
        protected $product_helper;
83

84
        /**
85
         * Holds the shortlinker instance.
86
         *
87
         * @var WPSEO_Shortlinker
88
         */
89
        protected $shortlinker;
90

91
        /**
92
         * Whether SEO Score is enabled.
93
         *
94
         * @var bool
95
         */
96
        protected $is_seo_enabled = null;
97

98
        /**
99
         * Whether readability is enabled.
100
         *
101
         * @var bool
102
         */
103
        protected $is_readability_enabled = null;
104

105
        /**
106
         * The indexable for the current WordPress page, if found.
107
         *
108
         * @var bool|Indexable
109
         */
110
        protected $current_indexable = null;
111

112
        /**
113
         * Constructs the WPSEO_Admin_Bar_Menu.
114
         *
115
         * @param WPSEO_Admin_Asset_Manager|null $asset_manager        Optional. Asset manager to use.
116
         * @param Indexable_Repository|null      $indexable_repository Optional. The Indexable_Repository.
117
         * @param Score_Icon_Helper|null         $score_icon_helper    Optional. The Score_Icon_Helper.
118
         * @param Product_Helper|null            $product_helper       Optional. The product helper.
119
         * @param WPSEO_Shortlinker|null         $shortlinker          The shortlinker.
120
         */
121
        public function __construct(
×
122
                ?WPSEO_Admin_Asset_Manager $asset_manager = null,
123
                ?Indexable_Repository $indexable_repository = null,
124
                ?Score_Icon_Helper $score_icon_helper = null,
125
                ?Product_Helper $product_helper = null,
126
                ?WPSEO_Shortlinker $shortlinker = null
127
        ) {
128
                if ( ! $asset_manager ) {
×
129
                        $asset_manager = new WPSEO_Admin_Asset_Manager();
×
130
                }
131
                if ( ! $indexable_repository ) {
×
132
                        $indexable_repository = YoastSEO()->classes->get( Indexable_Repository::class );
×
133
                }
134
                if ( ! $score_icon_helper ) {
×
135
                        $score_icon_helper = YoastSEO()->helpers->score_icon;
×
136
                }
137
                if ( ! $product_helper ) {
×
138
                        $product_helper = YoastSEO()->helpers->product;
×
139
                }
140
                if ( ! $shortlinker ) {
×
141
                        $shortlinker = new WPSEO_Shortlinker();
×
142
                }
143

144
                $this->product_helper       = $product_helper;
×
145
                $this->asset_manager        = $asset_manager;
×
146
                $this->indexable_repository = $indexable_repository;
×
147
                $this->score_icon_helper    = $score_icon_helper;
×
148
                $this->shortlinker          = $shortlinker;
×
149
        }
150

151
        /**
152
         * Gets whether SEO score is enabled, with cache applied.
153
         *
154
         * @return bool True if SEO score is enabled, false otherwise.
155
         */
156
        protected function get_is_seo_enabled() {
×
157
                if ( is_null( $this->is_seo_enabled ) ) {
×
158
                        $this->is_seo_enabled = ( new WPSEO_Metabox_Analysis_SEO() )->is_enabled();
×
159
                }
160

161
                return $this->is_seo_enabled;
×
162
        }
163

164
        /**
165
         * Gets whether readability is enabled, with cache applied.
166
         *
167
         * @return bool True if readability is enabled, false otherwise.
168
         */
169
        protected function get_is_readability_enabled() {
×
170
                if ( is_null( $this->is_readability_enabled ) ) {
×
171
                        $this->is_readability_enabled = ( new WPSEO_Metabox_Analysis_Readability() )->is_enabled();
×
172
                }
173

174
                return $this->is_readability_enabled;
×
175
        }
176

177
        /**
178
         * Returns the indexable for the current WordPress page, with cache applied.
179
         *
180
         * @return bool|Indexable The indexable, false if none could be found.
181
         */
182
        protected function get_current_indexable() {
×
183
                if ( is_null( $this->current_indexable ) ) {
×
184
                        $this->current_indexable = $this->indexable_repository->for_current_page();
×
185
                }
186

187
                return $this->current_indexable;
×
188
        }
189

190
        /**
191
         * Adds the admin bar menu.
192
         *
193
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
194
         *
195
         * @return void
196
         */
197
        public function add_menu( WP_Admin_Bar $wp_admin_bar ) {
4✔
198
                // On block editor pages, the admin bar only shows on mobile, where having this menu icon is not very helpful.
199
                if ( is_admin() ) {
4✔
200
                        $screen = get_current_screen();
×
201
                        if ( isset( $screen ) && $screen->is_block_editor() ) {
×
202
                                return;
×
203
                        }
204
                }
205

206
                // If the current user can't write posts, this is all of no use, so let's not output an admin menu.
207
                if ( ! current_user_can( 'edit_posts' ) ) {
4✔
208
                        return;
2✔
209
                }
210

211
                $this->add_root_menu( $wp_admin_bar );
2✔
212

213
                /**
214
                 * Adds a submenu item in the top of the adminbar.
215
                 *
216
                 * @param WP_Admin_Bar $wp_admin_bar    Admin bar instance to add the menu to.
217
                 * @param string       $menu_identifier The menu identifier.
218
                 */
219
                do_action( 'wpseo_add_adminbar_submenu', $wp_admin_bar, self::MENU_IDENTIFIER );
2✔
220

221
                if ( ! is_admin() ) {
2✔
222

223
                        if ( is_singular() || is_tag() || is_tax() || is_category() ) {
2✔
224
                                $is_seo_enabled         = $this->get_is_seo_enabled();
×
225
                                $is_readability_enabled = $this->get_is_readability_enabled();
×
226

227
                                $indexable = $this->get_current_indexable();
×
228

229
                                if ( $is_seo_enabled ) {
×
230
                                        $focus_keyword = ( ! is_a( $indexable, 'Yoast\WP\SEO\Models\Indexable' ) || is_null( $indexable->primary_focus_keyword ) ) ? __( 'not set', 'wordpress-seo' ) : $indexable->primary_focus_keyword;
×
231

232
                                        $wp_admin_bar->add_menu(
×
233
                                                [
×
234
                                                        'parent' => self::MENU_IDENTIFIER,
×
235
                                                        'id'     => 'wpseo-seo-focus-keyword',
×
236
                                                        'title'  => __( 'Focus keyphrase: ', 'wordpress-seo' ) . '<span class="wpseo-focus-keyword">' . $focus_keyword . '</span>',
×
237
                                                        'meta'   => [ 'tabindex' => '0' ],
×
238
                                                ]
×
239
                                        );
×
240
                                        $wp_admin_bar->add_menu(
×
241
                                                [
×
242
                                                        'parent' => self::MENU_IDENTIFIER,
×
243
                                                        'id'     => 'wpseo-seo-score',
×
244
                                                        'title'  => __( 'SEO score', 'wordpress-seo' ) . ': ' . $this->score_icon_helper->for_seo( $indexable, 'adminbar-sub-menu-score' )
×
245
                                                                        ->present(),
×
246
                                                        'meta'   => [ 'tabindex' => '0' ],
×
247
                                                ]
×
248
                                        );
×
249
                                }
250

251
                                if ( $is_readability_enabled ) {
×
252
                                        $wp_admin_bar->add_menu(
×
253
                                                [
×
254
                                                        'parent' => self::MENU_IDENTIFIER,
×
255
                                                        'id'     => 'wpseo-readability-score',
×
256
                                                        'title'  => __( 'Readability', 'wordpress-seo' ) . ': ' . $this->score_icon_helper->for_readability( $indexable->readability_score, 'adminbar-sub-menu-score' )
×
257
                                                                        ->present(),
×
258
                                                        'meta'   => [ 'tabindex' => '0' ],
×
259
                                                ]
×
260
                                        );
×
261
                                }
262

263
                                if ( ! $this->product_helper->is_premium() ) {
×
264
                                        $wp_admin_bar->add_menu(
×
265
                                                [
×
266
                                                        'parent' => self::MENU_IDENTIFIER,
×
267
                                                        'id'     => 'wpseo-frontend-inspector',
×
268
                                                        'href'   => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-frontend-inspector' ),
×
269
                                                        'title'  => __( 'Front-end SEO inspector', 'wordpress-seo' ) . new Premium_Badge_Presenter( 'wpseo-frontend-inspector-badge' ),
×
270
                                                        'meta'   => [
×
271
                                                                'tabindex' => '0',
×
272
                                                                'target'   => '_blank',
×
273
                                                        ],
×
274
                                                ]
×
275
                                        );
×
276
                                }
277
                        }
278
                        $this->add_analysis_submenu( $wp_admin_bar );
2✔
279
                        $this->add_seo_tools_submenu( $wp_admin_bar );
2✔
280
                        $this->add_how_to_submenu( $wp_admin_bar );
2✔
281
                        $this->add_get_help_submenu( $wp_admin_bar );
2✔
282
                }
283

284
                if ( ! is_admin() || is_blog_admin() ) {
2✔
285
                        $this->add_settings_submenu( $wp_admin_bar );
2✔
286
                }
287
                elseif ( is_network_admin() ) {
×
288
                        $this->add_network_settings_submenu( $wp_admin_bar );
×
289
                }
290

291
                if ( ! $this->product_helper->is_premium() ) {
2✔
292
                        $this->add_premium_link( $wp_admin_bar );
2✔
293
                }
294
        }
295

296
        /**
297
         * Enqueues admin bar assets.
298
         *
299
         * @return void
300
         */
301
        public function enqueue_assets() {
4✔
302
                if ( ! is_admin_bar_showing() ) {
4✔
303
                        return;
2✔
304
                }
305

306
                // If the current user can't write posts, this is all of no use, so let's not output an admin menu.
307
                if ( ! current_user_can( 'edit_posts' ) ) {
2✔
308
                        return;
×
309
                }
310

311
                $this->asset_manager->register_assets();
2✔
312
                $this->asset_manager->enqueue_style( 'adminbar' );
2✔
313
        }
314

315
        /**
316
         * Registers the hooks.
317
         *
318
         * @return void
319
         */
320
        public function register_hooks() {
2✔
321
                if ( ! $this->meets_requirements() ) {
2✔
322
                        return;
×
323
                }
324

325
                add_action( 'admin_bar_menu', [ $this, 'add_menu' ], 95 );
2✔
326

327
                add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] );
2✔
328
                add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
2✔
329
        }
330

331
        /**
332
         * Checks whether the requirements to use this class are met.
333
         *
334
         * @return bool True if requirements are met, false otherwise.
335
         */
336
        public function meets_requirements() {
2✔
337
                if ( is_network_admin() ) {
2✔
338
                        return WPSEO_Utils::is_plugin_network_active();
×
339
                }
340

341
                if ( WPSEO_Options::get( 'enable_admin_bar_menu' ) !== true ) {
2✔
342
                        return false;
2✔
343
                }
344

345
                return ! is_admin() || is_blog_admin();
2✔
346
        }
347

348
        /**
349
         * Adds the admin bar root menu.
350
         *
351
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
352
         *
353
         * @return void
354
         */
355
        protected function add_root_menu( WP_Admin_Bar $wp_admin_bar ) {
×
356
                $title = $this->get_title();
×
357

358
                $score              = '';
×
359
                $settings_url       = '';
×
360
                $counter            = '';
×
361
                $notification_popup = '';
×
362
                $notification_count = 0;
×
363

364
                $post = $this->get_singular_post();
×
365
                if ( $post ) {
×
366
                        $score = $this->get_post_score( $post );
×
367
                }
368

369
                $term = $this->get_singular_term();
×
370
                if ( $term ) {
×
371
                        $score = $this->get_term_score( $term );
×
372
                }
373

374
                $can_manage_options = $this->can_manage_options();
×
375

376
                if ( $can_manage_options ) {
×
377
                        $settings_url = $this->get_settings_page_url();
×
378
                }
379

380
                if ( empty( $score ) && ! is_network_admin() && $can_manage_options ) {
×
381
                        $notification_center = Yoast_Notification_Center::get();
×
382
                        $notification_count  = $notification_center->get_notification_count();
×
383

384
                        $counter            = $this->get_notification_counter( $notification_count );
×
385
                        $notification_popup = $this->get_notification_popup();
×
386
                }
387

388
                $admin_bar_menu_args = [
×
389
                        'id'    => self::MENU_IDENTIFIER,
×
390
                        'title' => $title . $score . $counter . $notification_popup,
×
391
                        'href'  => $settings_url,
×
392
                        'meta'  => [ 'tabindex' => ! empty( $settings_url ) ? false : '0' ],
×
393
                ];
×
394
                $wp_admin_bar->add_menu( $admin_bar_menu_args );
×
395

396
                if ( $notification_count > 0 ) {
×
397
                        $admin_bar_menu_args = [
×
398
                                'parent' => self::MENU_IDENTIFIER,
×
399
                                'id'     => 'wpseo-notifications',
×
400
                                'title'  => __( 'Notifications', 'wordpress-seo' ) . $counter,
×
401
                                'href'   => empty( $settings_url ) ? '' : $settings_url . '#/alert-center',
×
402
                                'meta'   => [ 'tabindex' => ! empty( $settings_url ) ? false : '0' ],
×
403
                        ];
×
404
                        $wp_admin_bar->add_menu( $admin_bar_menu_args );
×
405
                }
406
        }
407

408
        /**
409
         * Adds the admin bar analysis submenu.
410
         *
411
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
412
         *
413
         * @return void
414
         */
415
        protected function add_analysis_submenu( WP_Admin_Bar $wp_admin_bar ) {
×
416
                try {
417
                        $url = YoastSEO()->meta->for_current_page()->canonical;
×
418
                } catch ( Exception $e ) {
×
419
                        // This is not the type of error we can handle here.
420
                        return;
×
421
                }
422

423
                if ( ! $url ) {
×
424
                        return;
×
425
                }
426

427
                $menu_args = [
×
428
                        'parent' => self::MENU_IDENTIFIER,
×
429
                        'id'     => self::ANALYSIS_SUBMENU_IDENTIFIER,
×
430
                        'title'  => __( 'Analyze this page', 'wordpress-seo' ),
×
431
                        'meta'   => [ 'tabindex' => '0' ],
×
432
                ];
×
433
                $wp_admin_bar->add_menu( $menu_args );
×
434

435
                $encoded_url   = rawurlencode( $url );
×
436
                $submenu_items = [
×
437
                        [
×
438
                                'id'    => 'wpseo-inlinks',
×
439
                                'title' => __( 'Check links to this URL', 'wordpress-seo' ),
×
440
                                'href'  => 'https://search.google.com/search-console/links/drilldown?resource_id=' . rawurlencode( get_option( 'siteurl' ) ) . '&type=EXTERNAL&target=' . $encoded_url . '&domain=',
×
441
                        ],
×
442
                        [
×
443
                                'id'    => 'wpseo-structureddata',
×
444
                                'title' => __( 'Google Rich Results Test', 'wordpress-seo' ),
×
445
                                'href'  => 'https://search.google.com/test/rich-results?url=' . $encoded_url,
×
446
                        ],
×
447
                        [
×
448
                                'id'    => 'wpseo-facebookdebug',
×
449
                                'title' => __( 'Facebook Debugger', 'wordpress-seo' ),
×
450
                                'href'  => '//developers.facebook.com/tools/debug/?q=' . $encoded_url,
×
451
                        ],
×
452
                        [
×
453
                                'id'    => 'wpseo-pagespeed',
×
454
                                'title' => __( 'Google Page Speed Test', 'wordpress-seo' ),
×
455
                                'href'  => '//developers.google.com/speed/pagespeed/insights/?url=' . $encoded_url,
×
456
                        ],
×
457
                ];
×
458

459
                $this->add_submenu_items( $submenu_items, $wp_admin_bar, self::ANALYSIS_SUBMENU_IDENTIFIER );
×
460
        }
461

462
        /**
463
         * Adds the admin bar tools submenu.
464
         *
465
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
466
         *
467
         * @return void
468
         */
469
        protected function add_seo_tools_submenu( WP_Admin_Bar $wp_admin_bar ) {
×
470
                $menu_args = [
×
471
                        'parent' => self::MENU_IDENTIFIER,
×
472
                        'id'     => 'wpseo-sub-tools',
×
473
                        'title'  => __( 'SEO Tools', 'wordpress-seo' ),
×
474
                        'meta'   => [ 'tabindex' => '0' ],
×
475
                ];
×
476
                $wp_admin_bar->add_menu( $menu_args );
×
477

478
                $submenu_items = [
×
479
                        [
×
480
                                'id'    => 'wpseo-semrush',
×
481
                                'title' => 'Semrush',
×
482
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-semrush' ),
×
483
                        ],
×
484
                        [
×
485
                                'id'    => 'wpseo-wincher',
×
486
                                'title' => 'Wincher',
×
487
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-wincher' ),
×
488
                        ],
×
489
                        [
×
490
                                'id'    => 'wpseo-google-trends',
×
491
                                'title' => 'Google trends',
×
492
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-gtrends' ),
×
493
                        ],
×
494
                ];
×
495

496
                $this->add_submenu_items( $submenu_items, $wp_admin_bar, 'wpseo-sub-tools' );
×
497
        }
498

499
        /**
500
         * Adds the admin bar How To submenu.
501
         *
502
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
503
         *
504
         * @return void
505
         */
506
        protected function add_how_to_submenu( WP_Admin_Bar $wp_admin_bar ) {
×
507
                $menu_args = [
×
508
                        'parent' => self::MENU_IDENTIFIER,
×
509
                        'id'     => 'wpseo-sub-howto',
×
510
                        'title'  => __( 'How to', 'wordpress-seo' ),
×
511
                        'meta'   => [ 'tabindex' => '0' ],
×
512
                ];
×
513
                $wp_admin_bar->add_menu( $menu_args );
×
514

515
                $submenu_items = [
×
516
                        [
×
517
                                'id'    => 'wpseo-learn-seo',
×
518
                                'title' => __( 'Learn more SEO', 'wordpress-seo' ),
×
519
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-learn-more-seo' ),
×
520
                        ],
×
521
                        [
×
522
                                'id'    => 'wpseo-improve-blogpost',
×
523
                                'title' => __( 'Improve your blog post', 'wordpress-seo' ),
×
524
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-improve-blog-post' ),
×
525
                        ],
×
526
                        [
×
527
                                'id'    => 'wpseo-write-better-content',
×
528
                                'title' => __( 'Write better content', 'wordpress-seo' ),
×
529
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-write-better' ),
×
530
                        ],
×
531
                ];
×
532

533
                $this->add_submenu_items( $submenu_items, $wp_admin_bar, 'wpseo-sub-howto' );
×
534
        }
535

536
        /**
537
         * Adds the admin bar How To submenu.
538
         *
539
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
540
         *
541
         * @return void
542
         */
543
        protected function add_get_help_submenu( WP_Admin_Bar $wp_admin_bar ) {
×
544
                $menu_args = [
×
545
                        'parent' => self::MENU_IDENTIFIER,
×
546
                        'id'     => 'wpseo-sub-get-help',
×
547
                        'title'  => __( 'Help', 'wordpress-seo' ),
×
548
                        'meta'   => [ 'tabindex' => '0' ],
×
549
                ];
×
550

551
                if ( current_user_can( Support_Integration::CAPABILITY ) ) {
×
552
                        $menu_args['href'] = admin_url( 'admin.php?page=' . Support_Integration::PAGE );
×
553
                        $wp_admin_bar->add_menu( $menu_args );
×
554

555
                        return;
×
556
                }
557
                $wp_admin_bar->add_menu( $menu_args );
×
558

559
                $submenu_items = [
×
560
                        [
×
561
                                'id'    => 'wpseo-yoast-help',
×
562
                                'title' => __( 'Yoast.com help section', 'wordpress-seo' ),
×
563
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-yoast-help' ),
×
564
                        ],
×
565
                        [
×
566
                                'id'    => 'wpseo-premium-support',
×
567
                                'title' => __( 'Yoast Premium support', 'wordpress-seo' ),
×
568
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-premium-support' ),
×
569
                        ],
×
570
                        [
×
571
                                'id'    => 'wpseo-wp-support-forums',
×
572
                                'title' => __( 'WordPress.org support forums', 'wordpress-seo' ),
×
573
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-wp-support-forums' ),
×
574
                        ],
×
575
                        [
×
576
                                'id'    => 'wpseo-learn-seo-2',
×
577
                                'title' => __( 'Learn more SEO', 'wordpress-seo' ),
×
578
                                'href'  => $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-learn-more-seo-help' ),
×
579
                        ],
×
580
                ];
×
581

582
                $this->add_submenu_items( $submenu_items, $wp_admin_bar, 'wpseo-sub-get-help' );
×
583
        }
584

585
        /**
586
         * Adds the admin bar How To submenu.
587
         *
588
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
589
         *
590
         * @return void
591
         */
592
        protected function add_premium_link( WP_Admin_Bar $wp_admin_bar ) {
×
593
                $sale_percentage = '';
×
594
                if ( YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-2024-promotion' ) ) {
×
595
                        $sale_percentage = sprintf(
×
596
                                '<span class="admin-bar-premium-promotion">%1$s</span>',
×
597
                                esc_html__( '30% OFF', 'wordpress-seo' )
×
598
                        );
×
599
                }
600
                $wp_admin_bar->add_menu(
×
601
                        [
×
602
                                'parent' => self::MENU_IDENTIFIER,
×
603
                                'id'     => 'wpseo-get-premium',
×
604
                                // Circumvent an issue in the WP admin bar API in order to pass `data` attributes. See https://core.trac.wordpress.org/ticket/38636.
605
                                'title'  => sprintf(
×
606
                                        '<a href="%1$s" target="_blank" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2" style="padding:0;">%2$s &raquo; %3$s</a>',
×
607
                                        esc_url( $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-get-premium' ) ),
×
608
                                        esc_html__( 'Get Yoast SEO Premium', 'wordpress-seo' ),
×
609
                                        $sale_percentage
×
610
                                ),
×
611
                                'meta'   => [
×
612
                                        'tabindex' => '0',
×
613
                                ],
×
614
                        ]
×
615
                );
×
616
        }
617

618
        /**
619
         * Adds the admin bar settings submenu.
620
         *
621
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
622
         *
623
         * @return void
624
         */
625
        protected function add_settings_submenu( WP_Admin_Bar $wp_admin_bar ) {
×
626
                if ( ! $this->can_manage_options() ) {
×
627
                        return;
×
628
                }
629

630
                $admin_menu    = new WPSEO_Admin_Menu( new WPSEO_Menu() );
×
631
                $submenu_pages = $admin_menu->get_submenu_pages();
×
632

633
                $menu_args = [
×
634
                        'parent' => self::MENU_IDENTIFIER,
×
635
                        'id'     => self::SETTINGS_SUBMENU_IDENTIFIER,
×
636
                        'title'  => __( 'SEO Settings', 'wordpress-seo' ),
×
637
                        'meta'   => [ 'tabindex' => '0' ],
×
638
                ];
×
639
                $wp_admin_bar->add_menu( $menu_args );
×
640

641
                foreach ( $submenu_pages as $submenu_page ) {
×
642
                        if ( ! current_user_can( $submenu_page[3] ) ) {
×
643
                                continue;
×
644
                        }
645

646
                        // Don't add the Google Search Console menu item.
647
                        if ( $submenu_page[4] === 'wpseo_search_console' ) {
×
648
                                continue;
×
649
                        }
650

651
                        $id = 'wpseo-' . str_replace( '_', '-', str_replace( 'wpseo_', '', $submenu_page[4] ) );
×
652
                        if ( $id === 'wpseo-dashboard' ) {
×
653
                                $id = 'wpseo-general';
×
654
                        }
655

656
                        $menu_args = [
×
657
                                'parent' => self::SETTINGS_SUBMENU_IDENTIFIER,
×
658
                                'id'     => $id,
×
659
                                'title'  => $submenu_page[2],
×
660
                                'href'   => admin_url( 'admin.php?page=' . rawurlencode( $submenu_page[4] ) ),
×
661
                        ];
×
662
                        $wp_admin_bar->add_menu( $menu_args );
×
663
                }
664
        }
665

666
        /**
667
         * Adds the admin bar network settings submenu.
668
         *
669
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
670
         *
671
         * @return void
672
         */
673
        protected function add_network_settings_submenu( WP_Admin_Bar $wp_admin_bar ) {
×
674
                if ( ! $this->can_manage_options() ) {
×
675
                        return;
×
676
                }
677

678
                $network_admin_menu = new WPSEO_Network_Admin_Menu( new WPSEO_Menu() );
×
679
                $submenu_pages      = $network_admin_menu->get_submenu_pages();
×
680

681
                $menu_args = [
×
682
                        'parent' => self::MENU_IDENTIFIER,
×
683
                        'id'     => self::NETWORK_SETTINGS_SUBMENU_IDENTIFIER,
×
684
                        'title'  => __( 'SEO Settings', 'wordpress-seo' ),
×
685
                        'meta'   => [ 'tabindex' => '0' ],
×
686
                ];
×
687
                $wp_admin_bar->add_menu( $menu_args );
×
688

689
                foreach ( $submenu_pages as $submenu_page ) {
×
690
                        if ( ! current_user_can( $submenu_page[3] ) ) {
×
691
                                continue;
×
692
                        }
693

694
                        $id = 'wpseo-' . str_replace( '_', '-', str_replace( 'wpseo_', '', $submenu_page[4] ) );
×
695
                        if ( $id === 'wpseo-dashboard' ) {
×
696
                                $id = 'wpseo-general';
×
697
                        }
698

699
                        $menu_args = [
×
700
                                'parent' => self::NETWORK_SETTINGS_SUBMENU_IDENTIFIER,
×
701
                                'id'     => $id,
×
702
                                'title'  => $submenu_page[2],
×
703
                                'href'   => network_admin_url( 'admin.php?page=' . rawurlencode( $submenu_page[4] ) ),
×
704
                        ];
×
705
                        $wp_admin_bar->add_menu( $menu_args );
×
706
                }
707
        }
708

709
        /**
710
         * Gets the menu title markup.
711
         *
712
         * @return string Admin bar title markup.
713
         */
714
        protected function get_title() {
×
715
                return '<div id="yoast-ab-icon" class="ab-item yoast-logo svg"><span class="screen-reader-text">' . __( 'SEO', 'wordpress-seo' ) . '</span></div>';
×
716
        }
717

718
        /**
719
         * Gets the current post if in a singular post context.
720
         *
721
         * @global string       $pagenow Current page identifier.
722
         * @global WP_Post|null $post    Current post object, or null if none available.
723
         *
724
         * @return WP_Post|null Post object, or null if not in singular context.
725
         */
726
        protected function get_singular_post() {
×
727
                global $pagenow, $post;
×
728

729
                if ( ! is_singular() && ( ! is_blog_admin() || ! WPSEO_Metabox::is_post_edit( $pagenow ) ) ) {
×
730
                        return null;
×
731
                }
732

733
                if ( ! isset( $post ) || ! is_object( $post ) || ! $post instanceof WP_Post ) {
×
734
                        return null;
×
735
                }
736

737
                return $post;
×
738
        }
739

740
        /**
741
         * Gets the focus keyword for a given post.
742
         *
743
         * @param WP_Post $post Post object to get its focus keyword.
744
         *
745
         * @return string Focus keyword, or empty string if none available.
746
         */
747
        protected function get_post_focus_keyword( $post ) {
8✔
748
                if ( ! is_object( $post ) || ! property_exists( $post, 'ID' ) ) {
8✔
749
                        return '';
4✔
750
                }
751

752
                /**
753
                 * Filter: 'wpseo_use_page_analysis' Determines if the analysis should be enabled.
754
                 *
755
                 * @param bool $enabled Determines if the analysis should be enabled.
756
                 */
757
                if ( apply_filters( 'wpseo_use_page_analysis', true ) !== true ) {
4✔
758
                        return '';
2✔
759
                }
760

761
                return WPSEO_Meta::get_value( 'focuskw', $post->ID );
2✔
762
        }
763

764
        /**
765
         * Gets the score for a given post.
766
         *
767
         * @param WP_Post $post Post object to get its score.
768
         *
769
         * @return string Score markup, or empty string if none available.
770
         */
771
        protected function get_post_score( $post ) {
×
772
                if ( ! is_object( $post ) || ! property_exists( $post, 'ID' ) ) {
×
773
                        return '';
×
774
                }
775

776
                if ( apply_filters( 'wpseo_use_page_analysis', true ) !== true ) {
×
777
                        return '';
×
778
                }
779

780
                return $this->get_score_icon();
×
781
        }
782

783
        /**
784
         * Gets the current term if in a singular term context.
785
         *
786
         * @global string       $pagenow  Current page identifier.
787
         * @global WP_Query     $wp_query Current query object.
788
         * @global WP_Term|null $tag      Current term object, or null if none available.
789
         *
790
         * @return WP_Term|null Term object, or null if not in singular context.
791
         */
792
        protected function get_singular_term() {
×
793
                global $pagenow, $wp_query, $tag;
×
794

795
                if ( is_category() || is_tag() || is_tax() ) {
×
796
                        return $wp_query->get_queried_object();
×
797
                }
798

799
                if ( WPSEO_Taxonomy::is_term_edit( $pagenow ) && ! WPSEO_Taxonomy::is_term_overview( $pagenow ) && isset( $tag ) && is_object( $tag ) && ! is_wp_error( $tag ) ) {
×
800
                        return get_term( $tag->term_id );
×
801
                }
802

803
                return null;
×
804
        }
805

806
        /**
807
         * Gets the score for a given term.
808
         *
809
         * @param WP_Term $term Term object to get its score.
810
         *
811
         * @return string Score markup, or empty string if none available.
812
         */
813
        protected function get_term_score( $term ) {
×
814
                if ( ! is_object( $term ) || ! property_exists( $term, 'term_id' ) || ! property_exists( $term, 'taxonomy' ) ) {
×
815
                        return '';
×
816
                }
817

818
                return $this->get_score_icon();
×
819
        }
820

821
        /**
822
         * Create the score icon.
823
         *
824
         * @return string The score icon, or empty string.
825
         */
826
        protected function get_score_icon() {
×
827
                $is_seo_enabled         = $this->get_is_seo_enabled();
×
828
                $is_readability_enabled = $this->get_is_readability_enabled();
×
829

830
                $indexable = $this->get_current_indexable();
×
831

832
                if ( $is_seo_enabled ) {
×
833
                        return $this->score_icon_helper->for_seo( $indexable, 'adminbar-seo-score' )->present();
×
834
                }
835

836
                if ( $is_readability_enabled ) {
×
837
                        return $this->score_icon_helper->for_readability( $indexable->readability_score, 'adminbar-seo-score' )
×
838
                                ->present();
×
839
                }
840

841
                return '';
×
842
        }
843

844
        /**
845
         * Gets the URL to the main admin settings page.
846
         *
847
         * @return string Admin settings page URL.
848
         */
849
        protected function get_settings_page_url() {
×
850
                return self_admin_url( 'admin.php?page=' . WPSEO_Admin::PAGE_IDENTIFIER );
×
851
        }
852

853
        /**
854
         * Gets the notification counter if in a valid context.
855
         *
856
         * @param int $notification_count Number of notifications.
857
         *
858
         * @return string Notification counter markup, or empty string if not available.
859
         */
860
        protected function get_notification_counter( $notification_count ) {
×
861
                /* translators: Hidden accessibility text; %s: number of notifications. */
862
                $counter_screen_reader_text = sprintf( _n( '%s notification', '%s notifications', $notification_count, 'wordpress-seo' ), number_format_i18n( $notification_count ) );
×
863

864
                return sprintf(
×
865
                        ' <div class="wp-core-ui wp-ui-notification yoast-issue-counter%s"><span class="yoast-issues-count" aria-hidden="true">%d</span><span class="screen-reader-text">%s</span></div>',
×
866
                        ( $notification_count ) ? '' : ' wpseo-no-adminbar-notifications',
×
867
                        $notification_count,
×
868
                        $counter_screen_reader_text
×
869
                );
×
870
        }
871

872
        /**
873
         * Gets the notification popup if in a valid context.
874
         *
875
         * @return string Notification popup markup, or empty string if not available.
876
         */
877
        protected function get_notification_popup() {
×
878
                $notification_center     = Yoast_Notification_Center::get();
×
879
                $new_notifications       = $notification_center->get_new_notifications();
×
880
                $new_notifications_count = count( $new_notifications );
×
881

882
                if ( ! $new_notifications_count ) {
×
883
                        return '';
×
884
                }
885

886
                $notification = sprintf(
×
887
                        _n(
×
888
                                'There is a new notification.',
×
889
                                'There are new notifications.',
×
890
                                $new_notifications_count,
×
891
                                'wordpress-seo'
×
892
                        ),
×
893
                        $new_notifications_count
×
894
                );
×
895

896
                return '<div class="yoast-issue-added">' . $notification . '</div>';
×
897
        }
898

899
        /**
900
         * Checks whether the current user can manage options in the current context.
901
         *
902
         * @return bool True if capabilities are sufficient, false otherwise.
903
         */
904
        protected function can_manage_options() {
×
905
                return ( is_network_admin() && current_user_can( 'wpseo_manage_network_options' ) )
×
906
                        || ( ! is_network_admin() && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) );
×
907
        }
908

909
        /**
910
         * Add submenu items to a menu item.
911
         *
912
         * @param array        $submenu_items Submenu items array.
913
         * @param WP_Admin_Bar $wp_admin_bar  Admin bar object.
914
         * @param string       $parent_id     Parent menu item ID.
915
         *
916
         * @return void
917
         */
918
        protected function add_submenu_items( array $submenu_items, WP_Admin_Bar $wp_admin_bar, $parent_id ) {
×
919
                foreach ( $submenu_items as $menu_item ) {
×
920
                        $menu_args = [
×
921
                                'parent' => $parent_id,
×
922
                                'id'     => $menu_item['id'],
×
923
                                'title'  => $menu_item['title'],
×
924
                                'href'   => $menu_item['href'],
×
925
                                'meta'   => [ 'target' => '_blank' ],
×
926
                        ];
×
927
                        $wp_admin_bar->add_menu( $menu_args );
×
928
                }
929
        }
930
}
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