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

Yoast / wordpress-seo / 5401906903

pending completion
5401906903

push

github

web-flow
Merge pull request #20461 from Yoast/831-major-in-case-page-status-was-changed-from-publish-to-another-this-page-should-be-excluded-from-site-policies-pages-and-schema

Add check if the post is published.

0 of 2 new or added lines in 1 file covered. (0.0%)

2 existing lines in 1 file now uncovered.

10191 of 24161 relevant lines covered (42.18%)

3.43 hits per line

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

18.52
/src/integrations/settings-integration.php
1
<?php
2

3
namespace Yoast\WP\SEO\Integrations;
4

5
use WP_Post_Type;
6
use WP_Taxonomy;
7
use WP_User;
8
use WPSEO_Admin_Asset_Manager;
9
use WPSEO_Admin_Editor_Specific_Replace_Vars;
10
use WPSEO_Admin_Recommended_Replace_Vars;
11
use WPSEO_Option_Titles;
12
use WPSEO_Options;
13
use WPSEO_Replace_Vars;
14
use WPSEO_Shortlinker;
15
use WPSEO_Sitemaps_Router;
16
use Yoast\WP\SEO\Conditionals\Settings_Conditional;
17
use Yoast\WP\SEO\Config\Schema_Types;
18
use Yoast\WP\SEO\Helpers\Current_Page_Helper;
19
use Yoast\WP\SEO\Helpers\Language_Helper;
20
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
21
use Yoast\WP\SEO\Helpers\Product_Helper;
22
use Yoast\WP\SEO\Helpers\Schema\Article_Helper;
23
use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
24
use Yoast\WP\SEO\Helpers\User_Helper;
25
use Yoast\WP\SEO\Helpers\Woocommerce_Helper;
26
use Yoast\WP\SEO\Helpers\Options_Helper;
27
use Yoast\WP\SEO\Content_Type_Visibility\Application\Content_Type_Visibility_Dismiss_Notifications;
28

29
/**
30
 * Class Settings_Integration.
31
 */
32
class Settings_Integration implements Integration_Interface {
33

34
        const PAGE = 'wpseo_page_settings';
35

36
        /**
37
         * Holds the included WordPress options.
38
         *
39
         * @var string[]
40
         */
41
        const WP_OPTIONS = [ 'blogdescription' ];
42

43
        /**
44
         * Holds the allowed option groups.
45
         *
46
         * @var array
47
         */
48
        const ALLOWED_OPTION_GROUPS = [ 'wpseo', 'wpseo_titles', 'wpseo_social' ];
49

50
        /**
51
         * Holds the disallowed settings, per option group.
52
         *
53
         * @var array
54
         */
55
        const DISALLOWED_SETTINGS = [
56
                'wpseo'        => [
57
                        'myyoast-oauth',
58
                        'semrush_tokens',
59
                        'custom_taxonomy_slugs',
60
                        'zapier_subscription',
61
                        'import_cursors',
62
                        'workouts_data',
63
                        'configuration_finished_steps',
64
                        'importing_completed',
65
                        'wincher_tokens',
66
                        'least_readability_ignore_list',
67
                        'least_seo_score_ignore_list',
68
                        'most_linked_ignore_list',
69
                        'least_linked_ignore_list',
70
                        'indexables_page_reading_list',
71
                        'show_new_content_type_notification',
72
                        'new_post_types',
73
                        'new_taxonomies',
74
                ],
75
                'wpseo_titles' => [
76
                        'company_logo_meta',
77
                        'person_logo_meta',
78
                ],
79
        ];
80

81
        /**
82
         * Holds the disabled on multisite settings, per option group.
83
         *
84
         * @var array
85
         */
86
        const DISABLED_ON_MULTISITE_SETTINGS = [
87
                'wpseo' => [
88
                        'deny_search_crawling',
89
                        'deny_wp_json_crawling',
90
                        'deny_adsbot_crawling',
91
                ],
92
        ];
93

94
        /**
95
         * Holds the WPSEO_Admin_Asset_Manager.
96
         *
97
         * @var WPSEO_Admin_Asset_Manager
98
         */
99
        protected $asset_manager;
100

101
        /**
102
         * Holds the WPSEO_Replace_Vars.
103
         *
104
         * @var WPSEO_Replace_Vars
105
         */
106
        protected $replace_vars;
107

108
        /**
109
         * Holds the Schema_Types.
110
         *
111
         * @var Schema_Types
112
         */
113
        protected $schema_types;
114

115
        /**
116
         * Holds the Current_Page_Helper.
117
         *
118
         * @var Current_Page_Helper
119
         */
120
        protected $current_page_helper;
121

122
        /**
123
         * Holds the Post_Type_Helper.
124
         *
125
         * @var Post_Type_Helper
126
         */
127
        protected $post_type_helper;
128

129
        /**
130
         * Holds the Language_Helper.
131
         *
132
         * @var Language_Helper
133
         */
134
        protected $language_helper;
135

136
        /**
137
         * Holds the Taxonomy_Helper.
138
         *
139
         * @var Taxonomy_Helper
140
         */
141
        protected $taxonomy_helper;
142

143
        /**
144
         * Holds the Product_Helper.
145
         *
146
         * @var Product_Helper
147
         */
148
        protected $product_helper;
149

150
        /**
151
         * Holds the Woocommerce_Helper.
152
         *
153
         * @var Woocommerce_Helper
154
         */
155
        protected $woocommerce_helper;
156

157
        /**
158
         * Holds the Article_Helper.
159
         *
160
         * @var Article_Helper
161
         */
162
        protected $article_helper;
163

164
        /**
165
         * Holds the User_Helper.
166
         *
167
         * @var User_Helper
168
         */
169
        protected $user_helper;
170

171
        /**
172
         * Holds the Options_Helper instance.
173
         *
174
         * @var Options_Helper
175
         */
176
        protected $options;
177

178
        /**
179
         * Holds the Content_Type_Visibility_Dismiss_Notifications instance.
180
         *
181
         * @var Content_Type_Visibility_Dismiss_Notifications
182
         */
183
        protected $content_type_visibility;
184

185
        /**
186
         * Constructs Settings_Integration.
187
         *
188
         * @param WPSEO_Admin_Asset_Manager                     $asset_manager       The WPSEO_Admin_Asset_Manager.
189
         * @param WPSEO_Replace_Vars                            $replace_vars        The WPSEO_Replace_Vars.
190
         * @param Schema_Types                                  $schema_types        The Schema_Types.
191
         * @param Current_Page_Helper                           $current_page_helper The Current_Page_Helper.
192
         * @param Post_Type_Helper                              $post_type_helper    The Post_Type_Helper.
193
         * @param Language_Helper                               $language_helper     The Language_Helper.
194
         * @param Taxonomy_Helper                               $taxonomy_helper     The Taxonomy_Helper.
195
         * @param Product_Helper                                $product_helper      The Product_Helper.
196
         * @param Woocommerce_Helper                            $woocommerce_helper  The Woocommerce_Helper.
197
         * @param Article_Helper                                $article_helper      The Article_Helper.
198
         * @param User_Helper                                   $user_helper         The User_Helper.
199
         * @param Options_Helper                                $options             The options helper.
200
         * @param Content_Type_Visibility_Dismiss_Notifications $content_type_visibility The Content_Type_Visibility_Dismiss_Notifications instance.
201
         */
202
        public function __construct(
203
                WPSEO_Admin_Asset_Manager $asset_manager,
204
                WPSEO_Replace_Vars $replace_vars,
205
                Schema_Types $schema_types,
206
                Current_Page_Helper $current_page_helper,
207
                Post_Type_Helper $post_type_helper,
208
                Language_Helper $language_helper,
209
                Taxonomy_Helper $taxonomy_helper,
210
                Product_Helper $product_helper,
211
                Woocommerce_Helper $woocommerce_helper,
212
                Article_Helper $article_helper,
213
                User_Helper $user_helper,
214
                Options_Helper $options,
215
                Content_Type_Visibility_Dismiss_Notifications $content_type_visibility
216
        ) {
1✔
217
                $this->asset_manager           = $asset_manager;
2✔
218
                $this->replace_vars            = $replace_vars;
2✔
219
                $this->schema_types            = $schema_types;
2✔
220
                $this->current_page_helper     = $current_page_helper;
2✔
221
                $this->taxonomy_helper         = $taxonomy_helper;
2✔
222
                $this->post_type_helper        = $post_type_helper;
2✔
223
                $this->language_helper         = $language_helper;
2✔
224
                $this->product_helper          = $product_helper;
2✔
225
                $this->woocommerce_helper      = $woocommerce_helper;
2✔
226
                $this->article_helper          = $article_helper;
2✔
227
                $this->user_helper             = $user_helper;
2✔
228
                $this->options                 = $options;
2✔
229
                $this->content_type_visibility = $content_type_visibility;
2✔
230
        }
1✔
231

232
        /**
233
         * Returns the conditionals based on which this loadable should be active.
234
         *
235
         * @return array
236
         */
237
        public static function get_conditionals() {
238
                return [ Settings_Conditional::class ];
2✔
239
        }
240

241
        /**
242
         * Initializes the integration.
243
         *
244
         * This is the place to register hooks and filters.
245
         *
246
         * @return void
247
         */
248
        public function register_hooks() {
249
                // Add page.
250
                \add_filter( 'wpseo_submenu_pages', [ $this, 'add_page' ] );
×
251
                \add_filter( 'admin_menu', [ $this, 'add_settings_saved_page' ] );
×
252

253
                // Are we saving the settings?
254
                if ( $this->current_page_helper->get_current_admin_page() === 'options.php' ) {
×
255
                        // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged -- This deprecation will be addressed later.
256
                        $post_action = \filter_input( \INPUT_POST, 'action', @\FILTER_SANITIZE_STRING );
×
257
                        $option_page = \filter_input( \INPUT_POST, 'option_page', @\FILTER_SANITIZE_STRING );
×
258
                        // phpcs:enable
259

260
                        if ( $post_action === 'update' && $option_page === self::PAGE ) {
×
261
                                \add_action( 'admin_init', [ $this, 'register_setting' ] );
×
262
                                \add_action( 'in_admin_header', [ $this, 'remove_notices' ], \PHP_INT_MAX );
×
263
                        }
264

265
                        return;
×
266
                }
267

268
                // Are we on the settings page?
269
                if ( $this->current_page_helper->get_current_yoast_seo_page() === self::PAGE ) {
×
270
                        \add_action( 'admin_init', [ $this, 'register_setting' ] );
×
271
                        \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
×
272
                        \add_action( 'in_admin_header', [ $this, 'remove_notices' ], \PHP_INT_MAX );
×
273

274
                }
275
        }
276

277
        /**
278
         * Registers the different options under the setting.
279
         *
280
         * @return void
281
         */
282
        public function register_setting() {
283
                foreach ( WPSEO_Options::$options as $name => $instance ) {
×
284
                        if ( \in_array( $name, self::ALLOWED_OPTION_GROUPS, true ) ) {
×
285
                                \register_setting( self::PAGE, $name );
×
286
                        }
287
                }
288
                // Only register WP options when the user is allowed to manage them.
289
                if ( \current_user_can( 'manage_options' ) ) {
×
290
                        foreach ( self::WP_OPTIONS as $name ) {
×
291
                                \register_setting( self::PAGE, $name );
×
292
                        }
293
                }
294
        }
295

296
        /**
297
         * Adds the page.
298
         *
299
         * @param array $pages The pages.
300
         *
301
         * @return array The pages.
302
         */
303
        public function add_page( $pages ) {
304
                \array_splice(
×
305
                        $pages,
×
306
                        1,
×
307
                        0,
×
308
                        [
309
                                [
310
                                        'wpseo_dashboard',
×
311
                                        '',
×
312
                                        \__( 'Settings', 'wordpress-seo' ),
×
313
                                        'wpseo_manage_options',
×
314
                                        self::PAGE,
×
315
                                        [ $this, 'display_page' ],
×
316
                                ],
317
                        ]
318
                );
319

320
                return $pages;
×
321
        }
322

323
        /**
324
         * Adds a dummy page.
325
         *
326
         * Because the options route NEEDS to redirect to something.
327
         *
328
         * @param array $pages The pages.
329
         *
330
         * @return array The pages.
331
         */
332
        public function add_settings_saved_page( $pages ) {
333
                \add_submenu_page(
2✔
334
                        '',
2✔
335
                        '',
2✔
336
                        '',
2✔
337
                        'wpseo_manage_options',
2✔
338
                        self::PAGE . '_saved',
2✔
339
                        static function () {
1✔
340
                                // Add success indication to HTML response.
341
                                $success = empty( \get_settings_errors() ) ? 'true' : 'false';
×
342
                                echo \esc_html( "{{ yoast-success: $success }}" );
×
343
                        }
2✔
344
                );
1✔
345

346
                return $pages;
2✔
347
        }
348

349
        /**
350
         * Displays the page.
351
         */
352
        public function display_page() {
353
                echo '<div id="yoast-seo-settings"></div>';
×
354
        }
355

356
        /**
357
         * Enqueues the assets.
358
         *
359
         * @return void
360
         */
361
        public function enqueue_assets() {
362
                // Remove the emoji script as it is incompatible with both React and any contenteditable fields.
363
                \remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
×
364
                \wp_enqueue_media();
×
365
                $this->asset_manager->enqueue_script( 'new-settings' );
×
366
                $this->asset_manager->enqueue_style( 'new-settings' );
×
367
                $this->asset_manager->localize_script( 'new-settings', 'wpseoScriptData', $this->get_script_data() );
×
368
        }
369

370
        /**
371
         * Removes all current WP notices.
372
         *
373
         * @return void
374
         */
375
        public function remove_notices() {
376
                \remove_all_actions( 'admin_notices' );
×
377
                \remove_all_actions( 'user_admin_notices' );
×
378
                \remove_all_actions( 'network_admin_notices' );
×
379
                \remove_all_actions( 'all_admin_notices' );
×
380
        }
381

382
        /**
383
         * Creates the script data.
384
         *
385
         * @return array The script data.
386
         */
387
        protected function get_script_data() {
388
                $default_setting_values = $this->get_default_setting_values();
×
389
                $settings               = $this->get_settings( $default_setting_values );
×
390
                $post_types             = $this->post_type_helper->get_indexable_post_type_objects();
×
391
                $taxonomies             = $this->taxonomy_helper->get_indexable_taxonomy_objects();
×
392

393
                // Check if attachments are included in indexation.
394
                if ( ! \array_key_exists( 'attachment', $post_types ) ) {
×
395
                        // Always include attachments in the settings, to let the user enable them again.
396
                        $attachment_object = \get_post_type_object( 'attachment' );
×
397
                        if ( ! empty( $attachment_object ) ) {
×
398
                                $post_types['attachment'] = $attachment_object;
×
399
                        }
400
                }
401
                // Check if post formats are included in indexation.
402
                if ( ! \array_key_exists( 'post_format', $taxonomies ) ) {
×
403
                        // Always include post_format in the settings, to let the user enable them again.
404
                        $post_format_object = \get_taxonomy( 'post_format' );
×
405
                        if ( ! empty( $post_format_object ) ) {
×
406
                                $taxonomies['post_format'] = $post_format_object;
×
407
                        }
408
                }
409

410
                $transformed_post_types = $this->transform_post_types( $post_types );
×
411
                $transformed_taxonomies = $this->transform_taxonomies( $taxonomies, \array_keys( $transformed_post_types ) );
×
412

413
                // Check if there is a new content type to show notification only once in the settings.
414
                $show_new_content_type_notification = $this->content_type_visibility->maybe_add_settings_notification();
×
415

416
                return [
417
                        'settings'                       => $this->transform_settings( $settings ),
×
418
                        'defaultSettingValues'           => $default_setting_values,
×
419
                        'disabledSettings'               => $this->get_disabled_settings( $settings ),
×
420
                        'endpoint'                       => \admin_url( 'options.php' ),
×
421
                        'nonce'                          => \wp_create_nonce( self::PAGE . '-options' ),
×
422
                        'separators'                     => WPSEO_Option_Titles::get_instance()->get_separator_options_for_display(),
×
423
                        'replacementVariables'           => $this->get_replacement_variables(),
×
424
                        'schema'                         => $this->get_schema( $transformed_post_types ),
×
425
                        'preferences'                    => $this->get_preferences( $settings ),
×
426
                        'linkParams'                     => WPSEO_Shortlinker::get_query_params(),
×
427
                        'postTypes'                      => $transformed_post_types,
×
428
                        'taxonomies'                     => $transformed_taxonomies,
×
429
                        'fallbacks'                      => $this->get_fallbacks(),
×
430
                        'showNewContentTypeNotification' => $show_new_content_type_notification,
×
431
                ];
432
        }
433

434
        /**
435
         * Retrieves the preferences.
436
         *
437
         * @param array $settings The settings.
438
         *
439
         * @return array The preferences.
440
         */
441
        protected function get_preferences( $settings ) {
442
                $shop_page_id             = $this->woocommerce_helper->get_shop_page_id();
×
443
                $homepage_is_latest_posts = \get_option( 'show_on_front' ) === 'posts';
×
444
                $page_on_front            = \get_option( 'page_on_front' );
×
445
                $page_for_posts           = \get_option( 'page_for_posts' );
×
446

447
                if ( empty( $page_on_front ) ) {
×
448
                        $page_on_front = $page_for_posts;
×
449
                }
450

451
                return [
452
                        'isPremium'                     => $this->product_helper->is_premium(),
×
453
                        'isRtl'                         => \is_rtl(),
×
454
                        'isNetworkAdmin'                => \is_network_admin(),
×
455
                        'isMainSite'                    => \is_main_site(),
×
456
                        'isWooCommerceActive'           => $this->woocommerce_helper->is_active(),
×
457
                        'isLocalSeoActive'              => \defined( 'WPSEO_LOCAL_FILE' ),
×
458
                        'isNewsSeoActive'               => \defined( 'WPSEO_NEWS_FILE' ),
×
459
                        'siteUrl'                       => \get_bloginfo( 'url' ),
×
460
                        'siteTitle'                     => \get_bloginfo( 'name' ),
×
461
                        'sitemapUrl'                    => WPSEO_Sitemaps_Router::get_base_url( 'sitemap_index.xml' ),
×
462
                        'hasWooCommerceShopPage'        => $shop_page_id !== -1,
463
                        'editWooCommerceShopPageUrl'    => \get_edit_post_link( $shop_page_id, 'js' ),
×
464
                        'wooCommerceShopPageSettingUrl' => \get_admin_url( null, 'admin.php?page=wc-settings&tab=products' ),
×
465
                        'homepageIsLatestPosts'         => $homepage_is_latest_posts,
×
466
                        'homepagePageEditUrl'           => \get_edit_post_link( $page_on_front, 'js' ),
×
467
                        'homepagePostsEditUrl'          => \get_edit_post_link( $page_for_posts, 'js' ),
×
468
                        'createUserUrl'                 => \admin_url( 'user-new.php' ),
×
469
                        'createPageUrl'                 => \admin_url( 'post-new.php?post_type=page' ),
×
470
                        'editUserUrl'                   => \admin_url( 'user-edit.php' ),
×
471
                        'editTaxonomyUrl'               => \admin_url( 'edit-tags.php' ),
×
472
                        'generalSettingsUrl'            => \admin_url( 'options-general.php' ),
×
473
                        'companyOrPersonMessage'        => \apply_filters( 'wpseo_knowledge_graph_setting_msg', '' ),
×
474
                        'currentUserId'                 => \get_current_user_id(),
×
475
                        'canCreateUsers'                => \current_user_can( 'create_users' ),
×
476
                        'canCreatePages'                => \current_user_can( 'edit_pages' ),
×
477
                        'canEditUsers'                  => \current_user_can( 'edit_users' ),
×
478
                        'canManageOptions'              => \current_user_can( 'manage_options' ),
×
479
                        'userLocale'                    => \str_replace( '_', '-', \get_user_locale() ),
×
480
                        'pluginUrl'                     => \plugins_url( '', \WPSEO_FILE ),
×
481
                        'showForceRewriteTitlesSetting' => ! \current_theme_supports( 'title-tag' ) && ! ( \function_exists( 'wp_is_block_theme' ) && \wp_is_block_theme() ),
×
482
                        'upsellSettings'                => $this->get_upsell_settings(),
×
483
                        'siteRepresentsPerson'          => $this->get_site_represents_person( $settings ),
×
484
                        'siteBasicsPolicies'            => $this->get_site_basics_policies( $settings ),
×
485
                ];
486
        }
487

488
        /**
489
         * Retrieves the currently represented person.
490
         *
491
         * @param array $settings The settings.
492
         *
493
         * @return array The currently represented person's ID and name.
494
         */
495
        protected function get_site_represents_person( $settings ) {
496
                $person = [
497
                        'id'   => false,
×
498
                        'name' => '',
499
                ];
500

501
                if ( isset( $settings['wpseo_titles']['company_or_person_user_id'] ) ) {
×
502
                        $person['id'] = $settings['wpseo_titles']['company_or_person_user_id'];
×
503
                        $user         = \get_userdata( $person['id'] );
×
504
                        if ( $user instanceof WP_User ) {
×
505
                                $person['name'] = $user->get( 'display_name' );
×
506
                        }
507
                }
508

509
                return $person;
×
510
        }
511

512
        /**
513
         * Get site policy data.
514
         *
515
         * @param array $settings The settings.
516
         *
517
         * @return array The policy data.
518
         */
519
        private function get_site_basics_policies( $settings ) {
520
                $policies = [];
×
521

522

523
                $policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['publishing_principles_id'], 'publishing_principles_id' );
×
524
                $policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['ownership_funding_info_id'], 'ownership_funding_info_id' );
×
525
                $policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['actionable_feedback_policy_id'], 'actionable_feedback_policy_id' );
×
526
                $policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['corrections_policy_id'], 'corrections_policy_id' );
×
527
                $policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['ethics_policy_id'], 'ethics_policy_id' );
×
528
                $policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['diversity_policy_id'], 'diversity_policy_id' );
×
529
                $policies = $this->maybe_add_policy( $policies, $settings['wpseo_titles']['diversity_staffing_report_id'], 'diversity_staffing_report_id' );
×
530

531
                return $policies;
×
532
        }
533

534
        /**
535
         * Adds policy data if it is present.
536
         *
537
         * @param array  $policies The existing policy data.
538
         * @param int    $policy   The policy id to check.
539
         * @param string $key      The option key name.
540
         *
541
         * @return array The policy data.
542
         */
543
        private function maybe_add_policy( $policies, $policy, $key ) {
544
                $policy_array = [
545
                        'id'   => false,
×
546
                        'name' => '',
547
                ];
548

549
                if ( isset( $policy ) && \is_int( $policy ) ) {
×
550
                        $policy_array['id'] = $policy;
×
551
                        $post               = \get_post( $policy );
×
552
                        if ( $post instanceof \WP_Post ) {
×
NEW
553
                                if ( $post->post_status !== 'publish' ) {
×
NEW
554
                                        return $policies;
×
555
                                }
UNCOV
556
                                $policy_array['name'] = $post->post_title;
×
557
                        }
558
                }
559

UNCOV
560
                $policies[ $key ] = $policy_array;
×
561

562
                return $policies;
×
563
        }
564

565
        /**
566
         * Returns settings for the Call to Buy (CTB) buttons.
567
         *
568
         * @return string[] The array of CTB settings.
569
         */
570
        public function get_upsell_settings() {
571
                return [
572
                        'actionId'     => 'load-nfd-ctb',
×
573
                        'premiumCtbId' => 'f6a84663-465f-4cb5-8ba5-f7a6d72224b2',
574
                ];
575
        }
576

577
        /**
578
         * Retrieves the default setting values.
579
         *
580
         * These default values are currently being used in the UI for dummy fields.
581
         * Dummy fields should not expose or reflect the actual data.
582
         *
583
         * @return array The default setting values.
584
         */
585
        protected function get_default_setting_values() {
586
                $defaults = [];
×
587

588
                // Add Yoast settings.
589
                foreach ( WPSEO_Options::$options as $option_name => $instance ) {
×
590
                        if ( \in_array( $option_name, self::ALLOWED_OPTION_GROUPS, true ) ) {
×
591
                                $option_instance          = WPSEO_Options::get_option_instance( $option_name );
×
592
                                $defaults[ $option_name ] = ( $option_instance ) ? $option_instance->get_defaults() : [];
×
593
                        }
594
                }
595
                // Add WP settings.
596
                foreach ( self::WP_OPTIONS as $option_name ) {
×
597
                        $defaults[ $option_name ] = '';
×
598
                }
599

600
                // Remove disallowed settings.
601
                foreach ( self::DISALLOWED_SETTINGS as $option_name => $disallowed_settings ) {
×
602
                        foreach ( $disallowed_settings as $disallowed_setting ) {
×
603
                                unset( $defaults[ $option_name ][ $disallowed_setting ] );
×
604
                        }
605
                }
606

607
                return $defaults;
×
608
        }
609

610
        /**
611
         * Retrieves the settings and their values.
612
         *
613
         * @param array $default_setting_values The default setting values.
614
         *
615
         * @return array The settings.
616
         */
617
        protected function get_settings( $default_setting_values ) {
618
                $settings = [];
×
619

620
                // Add Yoast settings.
621
                foreach ( WPSEO_Options::$options as $option_name => $instance ) {
×
622
                        if ( \in_array( $option_name, self::ALLOWED_OPTION_GROUPS, true ) ) {
×
623
                                $settings[ $option_name ] = \array_merge( $default_setting_values[ $option_name ], WPSEO_Options::get_option( $option_name ) );
×
624
                        }
625
                }
626
                // Add WP settings.
627
                foreach ( self::WP_OPTIONS as $option_name ) {
×
628
                        $settings[ $option_name ] = \get_option( $option_name );
×
629
                }
630

631
                // Remove disallowed settings.
632
                foreach ( self::DISALLOWED_SETTINGS as $option_name => $disallowed_settings ) {
×
633
                        foreach ( $disallowed_settings as $disallowed_setting ) {
×
634
                                unset( $settings[ $option_name ][ $disallowed_setting ] );
×
635
                        }
636
                }
637

638
                return $settings;
×
639
        }
640

641
        /**
642
         * Transforms setting values.
643
         *
644
         * @param array $settings The settings.
645
         *
646
         * @return array The settings.
647
         */
648
        protected function transform_settings( $settings ) {
649
                if ( isset( $settings['wpseo_titles']['breadcrumbs-sep'] ) ) {
×
650
                        /**
651
                         * The breadcrumbs separator default value is the HTML entity `&raquo;`.
652
                         * Which does not get decoded in our JS, while it did in our Yoast form. Decode it here as an exception.
653
                         */
654
                        $settings['wpseo_titles']['breadcrumbs-sep'] = \html_entity_decode(
×
655
                                $settings['wpseo_titles']['breadcrumbs-sep'],
×
656
                                ( \ENT_NOQUOTES | \ENT_HTML5 ),
×
657
                                'UTF-8'
×
658
                        );
659
                }
660

661
                /**
662
                 * Decode some WP options.
663
                 */
664
                $settings['blogdescription'] = \html_entity_decode(
×
665
                        $settings['blogdescription'],
×
666
                        ( \ENT_NOQUOTES | \ENT_HTML5 ),
×
667
                        'UTF-8'
×
668
                );
669

670
                return $settings;
×
671
        }
672

673
        /**
674
         * Retrieves the disabled settings.
675
         *
676
         * @param array $settings The settings.
677
         *
678
         * @return array The settings.
679
         */
680
        protected function get_disabled_settings( $settings ) {
681
                $disabled_settings = [];
×
682
                $site_language     = $this->language_helper->get_language();
×
683

684
                foreach ( WPSEO_Options::$options as $option_name => $instance ) {
×
685
                        if ( ! \in_array( $option_name, self::ALLOWED_OPTION_GROUPS, true ) ) {
×
686
                                continue;
×
687
                        }
688

689
                        $disabled_settings[ $option_name ] = [];
×
690
                        $option_instance                   = WPSEO_Options::get_option_instance( $option_name );
×
691
                        if ( $option_instance === false ) {
×
692
                                continue;
×
693
                        }
694
                        foreach ( $settings[ $option_name ] as $setting_name => $setting_value ) {
×
695
                                if ( $option_instance->is_disabled( $setting_name ) ) {
×
696
                                        $disabled_settings[ $option_name ][ $setting_name ] = 'network';
×
697
                                }
698
                        }
699
                }
700

701
                // Remove disabled on multisite settings.
702
                if ( \is_multisite() ) {
×
703
                        foreach ( self::DISABLED_ON_MULTISITE_SETTINGS as $option_name => $disabled_ms_settings ) {
×
704
                                if ( \array_key_exists( $option_name, $disabled_settings ) ) {
×
705
                                        foreach ( $disabled_ms_settings as $disabled_ms_setting ) {
×
706
                                                $disabled_settings[ $option_name ][ $disabled_ms_setting ] = 'multisite';
×
707
                                        }
708
                                }
709
                        }
710
                }
711

712
                if ( \array_key_exists( 'wpseo', $disabled_settings ) && ! $this->language_helper->has_inclusive_language_support( $site_language ) ) {
×
713
                        $disabled_settings['wpseo']['inclusive_language_analysis_active'] = 'language';
×
714
                }
715

716
                return $disabled_settings;
×
717
        }
718

719
        /**
720
         * Retrieves the replacement variables.
721
         *
722
         * @return array The replacement variables.
723
         */
724
        protected function get_replacement_variables() {
725
                $recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
×
726
                $specific_replace_vars    = new WPSEO_Admin_Editor_Specific_Replace_Vars();
×
727
                $replacement_variables    = $this->replace_vars->get_replacement_variables_with_labels();
×
728

729
                return [
730
                        'variables'   => $replacement_variables,
×
731
                        'recommended' => $recommended_replace_vars->get_recommended_replacevars(),
×
732
                        'specific'    => $specific_replace_vars->get(),
×
733
                        'shared'      => $specific_replace_vars->get_generic( $replacement_variables ),
×
734
                ];
735
        }
736

737
        /**
738
         * Retrieves the schema.
739
         *
740
         * @param array $post_types The post types.
741
         *
742
         * @return array The schema.
743
         */
744
        protected function get_schema( array $post_types ) {
745
                $schema = [];
×
746

747
                foreach ( $this->schema_types->get_article_type_options() as $article_type ) {
×
748
                        $schema['articleTypes'][ $article_type['value'] ] = [
×
749
                                'label' => $article_type['name'],
×
750
                                'value' => $article_type['value'],
×
751
                        ];
752
                }
753

754
                foreach ( $this->schema_types->get_page_type_options() as $page_type ) {
×
755
                        $schema['pageTypes'][ $page_type['value'] ] = [
×
756
                                'label' => $page_type['name'],
×
757
                                'value' => $page_type['value'],
×
758
                        ];
759
                }
760

761
                $schema['articleTypeDefaults'] = [];
×
762
                $schema['pageTypeDefaults']    = [];
×
763
                foreach ( $post_types as $name => $post_type ) {
×
764
                        $schema['articleTypeDefaults'][ $name ] = WPSEO_Options::get_default( 'wpseo_titles', "schema-article-type-$name" );
×
765
                        $schema['pageTypeDefaults'][ $name ]    = WPSEO_Options::get_default( 'wpseo_titles', "schema-page-type-$name" );
×
766
                }
767

768
                return $schema;
×
769
        }
770

771
        /**
772
         * Transforms the post types, to represent them.
773
         *
774
         * @param WP_Post_Type[] $post_types The WP_Post_Type array to transform.
775
         *
776
         * @return array The post types.
777
         */
778
        protected function transform_post_types( $post_types ) {
779
                $transformed    = [];
4✔
780
                $new_post_types = $this->options->get( 'new_post_types', [] );
4✔
781
                foreach ( $post_types as $post_type ) {
4✔
782
                        $transformed[ $post_type->name ] = [
4✔
783
                                'name'                 => $post_type->name,
4✔
784
                                'route'                => $this->get_route( $post_type->name, $post_type->rewrite, $post_type->rest_base ),
4✔
785
                                'label'                => $post_type->label,
4✔
786
                                'singularLabel'        => $post_type->labels->singular_name,
4✔
787
                                'hasArchive'           => $this->post_type_helper->has_archive( $post_type ),
4✔
788
                                'hasSchemaArticleType' => $this->article_helper->is_article_post_type( $post_type->name ),
4✔
789
                                'menuPosition'         => $post_type->menu_position,
4✔
790
                                'isNew'                => \in_array( $post_type->name, $new_post_types, true ),
4✔
791
                        ];
2✔
792
                }
793

794
                \uasort( $transformed, [ $this, 'compare_post_types' ] );
4✔
795

796
                return $transformed;
4✔
797
        }
798

799
        /**
800
         * Compares two post types.
801
         *
802
         * @param array $a The first post type.
803
         * @param array $b The second post type.
804
         *
805
         * @return int The order.
806
         */
807
        protected function compare_post_types( $a, $b ) {
808
                if ( $a['menuPosition'] === null && $b['menuPosition'] !== null ) {
×
809
                        return 1;
×
810
                }
811
                if ( $a['menuPosition'] !== null && $b['menuPosition'] === null ) {
×
812
                        return -1;
×
813
                }
814

815
                if ( $a['menuPosition'] === null && $b['menuPosition'] === null ) {
×
816
                        // No position specified, order alphabetically by label.
817
                        return \strnatcmp( $a['label'], $b['label'] );
×
818
                }
819

820
                return ( ( $a['menuPosition'] < $b['menuPosition'] ) ? -1 : 1 );
×
821
        }
822

823
        /**
824
         * Transforms the taxonomies, to represent them.
825
         *
826
         * @param WP_Taxonomy[] $taxonomies      The WP_Taxonomy array to transform.
827
         * @param string[]      $post_type_names The post type names.
828
         *
829
         * @return array The taxonomies.
830
         */
831
        protected function transform_taxonomies( $taxonomies, $post_type_names ) {
832
                $transformed    = [];
4✔
833
                $new_taxonomies = $this->options->get( 'new_taxonomies', [] );
4✔
834
                foreach ( $taxonomies as $taxonomy ) {
4✔
835
                        $transformed[ $taxonomy->name ] = [
4✔
836
                                'name'          => $taxonomy->name,
4✔
837
                                'route'         => $this->get_route( $taxonomy->name, $taxonomy->rewrite, $taxonomy->rest_base ),
4✔
838
                                'label'         => $taxonomy->label,
4✔
839
                                'showUi'        => $taxonomy->show_ui,
4✔
840
                                'singularLabel' => $taxonomy->labels->singular_name,
4✔
841
                                'postTypes'     => \array_filter(
4✔
842
                                        $taxonomy->object_type,
4✔
843
                                        static function ( $object_type ) use ( $post_type_names ) {
2✔
844
                                                return \in_array( $object_type, $post_type_names, true );
4✔
845
                                        }
2✔
846
                                ),
4✔
847
                                'isNew'         => \in_array( $taxonomy->name, $new_taxonomies, true ),
2✔
848
                        ];
2✔
849
                }
850

851
                \uasort(
4✔
852
                        $transformed,
2✔
853
                        static function ( $a, $b ) {
2✔
854
                                return \strnatcmp( $a['label'], $b['label'] );
855
                        }
2✔
856
                );
4✔
857

858
                return $transformed;
859
        }
860

861
        /**
862
         * Gets the route from a name, rewrite and rest_base.
863
         *
864
         * @param string $name      The name.
865
         * @param array  $rewrite   The rewrite data.
866
         * @param string $rest_base The rest base.
867
         *
868
         * @return string The route.
869
         */
870
        protected function get_route( $name, $rewrite, $rest_base ) {
871
                $route = $name;
×
872
                if ( isset( $rewrite['slug'] ) ) {
873
                        $route = $rewrite['slug'];
×
874
                }
875
                if ( ! empty( $rest_base ) ) {
876
                        $route = $rest_base;
877
                }
878
                // Always strip leading slashes.
879
                while ( \substr( $route, 0, 1 ) === '/' ) {
880
                        $route = \substr( $route, 1 );
881
                }
882

883
                return \rawurlencode( $route );
884
        }
885

886
        /**
887
         * Retrieves the fallbacks.
888
         *
889
         * @return array The fallbacks.
890
         */
891
        protected function get_fallbacks() {
892
                $site_logo_id = \get_option( 'site_logo' );
×
893
                if ( ! $site_logo_id ) {
894
                        $site_logo_id = \get_theme_mod( 'custom_logo' );
×
895
                }
896
                if ( ! $site_logo_id ) {
897
                        $site_logo_id = '0';
898
                }
899

900
                return [
901
                        'siteLogoId' => $site_logo_id,
902
                ];
903
        }
904
}
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