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

Yoast / wordpress-seo / 6638054992

25 Oct 2023 08:55AM UTC coverage: 49.106%. First build
6638054992

Pull #20653

github

vraja-pro
Merge remote-tracking branch 'origin/feature/upgrade-react-and-tests' into feature/upgrade-react-and-tests
Pull Request #20653: Feature/upgrade react and tests

64 of 157 new or added lines in 34 files covered. (40.76%)

13135 of 26748 relevant lines covered (49.11%)

3.96 hits per line

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

11.8
/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
        const MENU_IDENTIFIER = 'wpseo-menu';
27

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

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

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

49
        /**
50
         * The identifier used for the Network Settings submenu.
51
         *
52
         * @var string
53
         */
54
        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 ) {
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() ) {
8✔
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' ) ) {
8✔
208
                        return;
4✔
209
                }
210

211
                $this->add_root_menu( $wp_admin_bar );
4✔
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 );
4✔
220

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

223
                        if ( is_singular() || is_tag() || is_tax() || is_category() ) {
4✔
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',
×
NEW
244
                                                        'title'  => __( 'SEO score', 'wordpress-seo' ) . ': ' . $this->score_icon_helper->for_seo( $indexable, 'adminbar-sub-menu-score' )
×
NEW
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',
×
NEW
256
                                                        'title'  => __( 'Readability', 'wordpress-seo' ) . ': ' . $this->score_icon_helper->for_readability( $indexable->readability_score, 'adminbar-sub-menu-score' )
×
NEW
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 );
4✔
279
                        $this->add_seo_tools_submenu( $wp_admin_bar );
4✔
280
                        $this->add_how_to_submenu( $wp_admin_bar );
4✔
281
                        $this->add_get_help_submenu( $wp_admin_bar );
4✔
282
                }
283

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

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

296
        /**
297
         * Enqueues admin bar assets.
298
         *
299
         * @return void
300
         */
301
        public function enqueue_assets() {
302
                if ( ! is_admin_bar_showing() ) {
8✔
303
                        return;
4✔
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' ) ) {
4✔
308
                        return;
×
309
                }
310

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

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

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

327
                add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] );
4✔
328
                add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
4✔
329
        }
2✔
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() {
337
                if ( is_network_admin() ) {
4✔
338
                        return WPSEO_Utils::is_plugin_network_active();
×
339
                }
340

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

345
                return ! is_admin() || is_blog_admin();
4✔
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

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

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

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

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

379
                if ( empty( $score ) && ! is_network_admin() && $can_manage_options ) {
×
380
                        $counter            = $this->get_notification_counter();
×
381
                        $notification_popup = $this->get_notification_popup();
×
382
                }
383

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

392
                if ( ! empty( $counter ) ) {
×
393
                        $admin_bar_menu_args = [
394
                                'parent' => self::MENU_IDENTIFIER,
×
395
                                'id'     => 'wpseo-notifications',
×
396
                                'title'  => __( 'Notifications', 'wordpress-seo' ) . $counter,
×
397
                                'href'   => $settings_url,
×
398
                                'meta'   => [ 'tabindex' => ! empty( $settings_url ) ? false : '0' ],
×
399
                        ];
400
                        $wp_admin_bar->add_menu( $admin_bar_menu_args );
×
401
                }
402
        }
403

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

419
                if ( ! $url ) {
×
420
                        return;
×
421
                }
422

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

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

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

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

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

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

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

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

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

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

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

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

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

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

586
        /**
587
         * Adds the admin bar How To submenu.
588
         *
589
         * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to.
590
         *
591
         * @return void
592
         */
593
        protected function add_premium_link( WP_Admin_Bar $wp_admin_bar ) {
NEW
594
                $sale_percentage = '';
×
NEW
595
                if ( YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-2023-promotion' ) ) {
×
NEW
596
                        $sale_percentage = sprintf(
×
NEW
597
                                '<span class="admin-bar-premium-promotion">%1$s</span>',
×
NEW
598
                                __( '-30%', 'wordpress-seo' )
×
599
                        );
600
                }
601
                $wp_admin_bar->add_menu(
×
602
                        [
603
                                'parent' => self::MENU_IDENTIFIER,
×
604
                                'id'     => 'wpseo-get-premium',
×
605
                                // Circumvent an issue in the WP admin bar API in order to pass `data` attributes. See https://core.trac.wordpress.org/ticket/38636.
606
                                'title'  => sprintf(
×
NEW
607
                                        '<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>',
×
608
                                        $this->shortlinker->build_shortlink( 'https://yoa.st/admin-bar-get-premium' ),
×
NEW
609
                                        __( 'Get Yoast SEO Premium', 'wordpress-seo' ),
×
NEW
610
                                        $sale_percentage
×
611
                                ),
612
                                'meta'   => [
613
                                        'tabindex' => '0',
614
                                ],
615
                        ]
616
                );
617
        }
618

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

738
                return $post;
×
739
        }
740

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

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

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

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

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

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

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

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

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

804
                return null;
×
805
        }
806

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

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

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

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

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

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

842
                return '';
×
843
        }
844

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

854
        /**
855
         * Gets the notification counter if in a valid context.
856
         *
857
         * @return string Notification counter markup, or empty string if not available.
858
         */
859
        protected function get_notification_counter() {
860
                $notification_center = Yoast_Notification_Center::get();
×
861
                $notification_count  = $notification_center->get_notification_count();
×
862

863
                if ( ! $notification_count ) {
×
864
                        return '';
×
865
                }
866

867
                /* translators: Hidden accessibility text; %s: number of notifications. */
868
                $counter_screen_reader_text = sprintf( _n( '%s notification', '%s notifications', $notification_count, 'wordpress-seo' ), number_format_i18n( $notification_count ) );
×
869

870
                return sprintf( ' <div class="wp-core-ui wp-ui-notification yoast-issue-counter"><span class="yoast-issues-count" aria-hidden="true">%d</span><span class="screen-reader-text">%s</span></div>', $notification_count, $counter_screen_reader_text );
×
871
        }
872

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

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

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

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

900
        /**
901
         * Checks whether the current user can manage options in the current context.
902
         *
903
         * @return bool True if capabilities are sufficient, false otherwise.
904
         */
905
        protected function can_manage_options() {
906
                return is_network_admin() && current_user_can( 'wpseo_manage_network_options' ) || ! 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