• File: settings-integration.php
  • Full Path: /home/matthif/www/wp-content/plugins/wordpress-seo/src/integrations/settings-integration.php
  • Date Modified: 02/24/2024 11:29 PM
  • File size: 31.86 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php

namespace Yoast\WP\SEO\Integrations;

use 
WP_Post;
use 
WP_Post_Type;
use 
WP_Taxonomy;
use 
WP_User;
use 
WPSEO_Admin_Asset_Manager;
use 
WPSEO_Admin_Editor_Specific_Replace_Vars;
use 
WPSEO_Admin_Recommended_Replace_Vars;
use 
WPSEO_Option_Titles;
use 
WPSEO_Options;
use 
WPSEO_Plugin_Availability;
use 
WPSEO_Replace_Vars;
use 
WPSEO_Shortlinker;
use 
WPSEO_Sitemaps_Router;
use 
Yoast\WP\SEO\Conditionals\Settings_Conditional;
use 
Yoast\WP\SEO\Config\Schema_Types;
use 
Yoast\WP\SEO\Content_Type_Visibility\Application\Content_Type_Visibility_Dismiss_Notifications;
use 
Yoast\WP\SEO\Helpers\Current_Page_Helper;
use 
Yoast\WP\SEO\Helpers\Language_Helper;
use 
Yoast\WP\SEO\Helpers\Options_Helper;
use 
Yoast\WP\SEO\Helpers\Post_Type_Helper;
use 
Yoast\WP\SEO\Helpers\Product_Helper;
use 
Yoast\WP\SEO\Helpers\Schema\Article_Helper;
use 
Yoast\WP\SEO\Helpers\Taxonomy_Helper;
use 
Yoast\WP\SEO\Helpers\User_Helper;
use 
Yoast\WP\SEO\Helpers\Woocommerce_Helper;
use 
Yoast\WP\SEO\Promotions\Application\Promotion_Manager;

/**
 * Class Settings_Integration.
 */
class Settings_Integration implements Integration_Interface {

    public const 
PAGE 'wpseo_page_settings';

    
/**
     * Holds the included WordPress options.
     *
     * @var string[]
     */
    
public const WP_OPTIONS = [ 'blogdescription' ];

    
/**
     * Holds the allowed option groups.
     *
     * @var array
     */
    
public const ALLOWED_OPTION_GROUPS = [ 'wpseo''wpseo_titles''wpseo_social' ];

    
/**
     * Holds the disallowed settings, per option group.
     *
     * @var array
     */
    
public const DISALLOWED_SETTINGS = [
        
'wpseo'        => [
            
'myyoast-oauth',
            
'semrush_tokens',
            
'custom_taxonomy_slugs',
            
'zapier_subscription',
            
'import_cursors',
            
'workouts_data',
            
'configuration_finished_steps',
            
'importing_completed',
            
'wincher_tokens',
            
'least_readability_ignore_list',
            
'least_seo_score_ignore_list',
            
'most_linked_ignore_list',
            
'least_linked_ignore_list',
            
'indexables_page_reading_list',
            
'show_new_content_type_notification',
            
'new_post_types',
            
'new_taxonomies',
        ],
        
'wpseo_titles' => [
            
'company_logo_meta',
            
'person_logo_meta',
        ],
    ];

    
/**
     * Holds the disabled on multisite settings, per option group.
     *
     * @var array
     */
    
public const DISABLED_ON_MULTISITE_SETTINGS = [
        
'wpseo' => [
            
'deny_search_crawling',
            
'deny_wp_json_crawling',
            
'deny_adsbot_crawling',
            
'deny_ccbot_crawling',
            
'deny_google_extended_crawling',
            
'deny_gptbot_crawling',
        ],
    ];

    
/**
     * Holds the WPSEO_Admin_Asset_Manager.
     *
     * @var WPSEO_Admin_Asset_Manager
     */
    
protected $asset_manager;

    
/**
     * Holds the WPSEO_Replace_Vars.
     *
     * @var WPSEO_Replace_Vars
     */
    
protected $replace_vars;

    
/**
     * Holds the Schema_Types.
     *
     * @var Schema_Types
     */
    
protected $schema_types;

    
/**
     * Holds the Current_Page_Helper.
     *
     * @var Current_Page_Helper
     */
    
protected $current_page_helper;

    
/**
     * Holds the Post_Type_Helper.
     *
     * @var Post_Type_Helper
     */
    
protected $post_type_helper;

    
/**
     * Holds the Language_Helper.
     *
     * @var Language_Helper
     */
    
protected $language_helper;

    
/**
     * Holds the Taxonomy_Helper.
     *
     * @var Taxonomy_Helper
     */
    
protected $taxonomy_helper;

    
/**
     * Holds the Product_Helper.
     *
     * @var Product_Helper
     */
    
protected $product_helper;

    
/**
     * Holds the Woocommerce_Helper.
     *
     * @var Woocommerce_Helper
     */
    
protected $woocommerce_helper;

    
/**
     * Holds the Article_Helper.
     *
     * @var Article_Helper
     */
    
protected $article_helper;

    
/**
     * Holds the User_Helper.
     *
     * @var User_Helper
     */
    
protected $user_helper;

    
/**
     * Holds the Options_Helper instance.
     *
     * @var Options_Helper
     */
    
protected $options;

    
/**
     * Holds the Content_Type_Visibility_Dismiss_Notifications instance.
     *
     * @var Content_Type_Visibility_Dismiss_Notifications
     */
    
protected $content_type_visibility;

    
/**
     * Constructs Settings_Integration.
     *
     * @param WPSEO_Admin_Asset_Manager                     $asset_manager           The WPSEO_Admin_Asset_Manager.
     * @param WPSEO_Replace_Vars                            $replace_vars            The WPSEO_Replace_Vars.
     * @param Schema_Types                                  $schema_types            The Schema_Types.
     * @param Current_Page_Helper                           $current_page_helper     The Current_Page_Helper.
     * @param Post_Type_Helper                              $post_type_helper        The Post_Type_Helper.
     * @param Language_Helper                               $language_helper         The Language_Helper.
     * @param Taxonomy_Helper                               $taxonomy_helper         The Taxonomy_Helper.
     * @param Product_Helper                                $product_helper          The Product_Helper.
     * @param Woocommerce_Helper                            $woocommerce_helper      The Woocommerce_Helper.
     * @param Article_Helper                                $article_helper          The Article_Helper.
     * @param User_Helper                                   $user_helper             The User_Helper.
     * @param Options_Helper                                $options                 The options helper.
     * @param Content_Type_Visibility_Dismiss_Notifications $content_type_visibility The Content_Type_Visibility_Dismiss_Notifications instance.
     */
    
public function __construct(
        
WPSEO_Admin_Asset_Manager $asset_manager,
        
WPSEO_Replace_Vars $replace_vars,
        
Schema_Types $schema_types,
        
Current_Page_Helper $current_page_helper,
        
Post_Type_Helper $post_type_helper,
        
Language_Helper $language_helper,
        
Taxonomy_Helper $taxonomy_helper,
        
Product_Helper $product_helper,
        
Woocommerce_Helper $woocommerce_helper,
        
Article_Helper $article_helper,
        
User_Helper $user_helper,
        
Options_Helper $options,
        
Content_Type_Visibility_Dismiss_Notifications $content_type_visibility
    
) {
        
$this->asset_manager           $asset_manager;
        
$this->replace_vars            $replace_vars;
        
$this->schema_types            $schema_types;
        
$this->current_page_helper     $current_page_helper;
        
$this->taxonomy_helper         $taxonomy_helper;
        
$this->post_type_helper        $post_type_helper;
        
$this->language_helper         $language_helper;
        
$this->product_helper          $product_helper;
        
$this->woocommerce_helper      $woocommerce_helper;
        
$this->article_helper          $article_helper;
        
$this->user_helper             $user_helper;
        
$this->options                 $options;
        
$this->content_type_visibility $content_type_visibility;
    }

    
/**
     * Returns the conditionals based on which this loadable should be active.
     *
     * @return array
     */
    
public static function get_conditionals() {
        return [ 
Settings_Conditional::class ];
    }

    
/**
     * Initializes the integration.
     *
     * This is the place to register hooks and filters.
     *
     * @return void
     */
    
public function register_hooks() {
        
// Add page.
        
\add_filter'wpseo_submenu_pages', [ $this'add_page' ] );
        
\add_filter'admin_menu', [ $this'add_settings_saved_page' ] );

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

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

            return;
        }

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

    
/**
     * Registers the different options under the setting.
     *
     * @return void
     */
    
public function register_setting() {
        foreach ( 
WPSEO_Options::$options as $name => $instance ) {
            if ( 
\in_array$nameself::ALLOWED_OPTION_GROUPStrue ) ) {
                
\register_settingself::PAGE$name );
            }
        }
        
// Only register WP options when the user is allowed to manage them.
        
if ( \current_user_can'manage_options' ) ) {
            foreach ( 
self::WP_OPTIONS as $name ) {
                
\register_settingself::PAGE$name );
            }
        }
    }

    
/**
     * Adds the page.
     *
     * @param array $pages The pages.
     *
     * @return array The pages.
     */
    
public function add_page$pages ) {
        
\array_splice(
            
$pages,
            
1,
            
0,
            [
                [
                    
'wpseo_dashboard',
                    
'',
                    
\__'Settings''wordpress-seo' ),
                    
'wpseo_manage_options',
                    
self::PAGE,
                    [ 
$this'display_page' ],
                ],
            ]
        );

        return 
$pages;
    }

    
/**
     * Adds a dummy page.
     *
     * Because the options route NEEDS to redirect to something.
     *
     * @param array $pages The pages.
     *
     * @return array The pages.
     */
    
public function add_settings_saved_page$pages ) {
        
\add_submenu_page(
            
'',
            
'',
            
'',
            
'wpseo_manage_options',
            
self::PAGE '_saved',
            static function () {
                
// Add success indication to HTML response.
                
$success = empty( \get_settings_errors() ) ? 'true' 'false';
                echo 
\esc_html"{{ yoast-success: $success }}" );
            }
        );

        return 
$pages;
    }

    
/**
     * Displays the page.
     *
     * @return void
     */
    
public function display_page() {
        echo 
'<div id="yoast-seo-settings"></div>';
    }

    
/**
     * Enqueues the assets.
     *
     * @return void
     */
    
public function enqueue_assets() {
        
// Remove the emoji script as it is incompatible with both React and any contenteditable fields.
        
\remove_action'admin_print_scripts''print_emoji_detection_script' );
        
\wp_enqueue_media();
        
$this->asset_manager->enqueue_script'new-settings' );
        
$this->asset_manager->enqueue_style'new-settings' );
        if ( 
\YoastSEO()->classes->getPromotion_Manager::class )->is'black-friday-2023-promotion' ) ) {
            
$this->asset_manager->enqueue_style'black-friday-banner' );
        }
        
$this->asset_manager->localize_script'new-settings''wpseoScriptData'$this->get_script_data() );
    }

    
/**
     * Removes all current WP notices.
     *
     * @return void
     */
    
public function remove_notices() {
        
\remove_all_actions'admin_notices' );
        
\remove_all_actions'user_admin_notices' );
        
\remove_all_actions'network_admin_notices' );
        
\remove_all_actions'all_admin_notices' );
    }

    
/**
     * Creates the script data.
     *
     * @return array The script data.
     */
    
protected function get_script_data() {
        
$default_setting_values $this->get_default_setting_values();
        
$settings               $this->get_settings$default_setting_values );
        
$post_types             $this->post_type_helper->get_indexable_post_type_objects();
        
$taxonomies             $this->taxonomy_helper->get_indexable_taxonomy_objects();

        
// Check if attachments are included in indexation.
        
if ( ! \array_key_exists'attachment'$post_types ) ) {
            
// Always include attachments in the settings, to let the user enable them again.
            
$attachment_object \get_post_type_object'attachment' );
            if ( ! empty( 
$attachment_object ) ) {
                
$post_types['attachment'] = $attachment_object;
            }
        }
        
// Check if post formats are included in indexation.
        
if ( ! \array_key_exists'post_format'$taxonomies ) ) {
            
// Always include post_format in the settings, to let the user enable them again.
            
$post_format_object \get_taxonomy'post_format' );
            if ( ! empty( 
$post_format_object ) ) {
                
$taxonomies['post_format'] = $post_format_object;
            }
        }

        
$transformed_post_types $this->transform_post_types$post_types );
        
$transformed_taxonomies $this->transform_taxonomies$taxonomies\array_keys$transformed_post_types ) );

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

        return [
            
'settings'                       => $this->transform_settings$settings ),
            
'defaultSettingValues'           => $default_setting_values,
            
'disabledSettings'               => $this->get_disabled_settings$settings ),
            
'endpoint'                       => \admin_url'options.php' ),
            
'nonce'                          => \wp_create_nonceself::PAGE '-options' ),
            
'separators'                     => WPSEO_Option_Titles::get_instance()->get_separator_options_for_display(),
            
'replacementVariables'           => $this->get_replacement_variables(),
            
'schema'                         => $this->get_schema$transformed_post_types ),
            
'preferences'                    => $this->get_preferences$settings ),
            
'linkParams'                     => WPSEO_Shortlinker::get_query_params(),
            
'postTypes'                      => $transformed_post_types,
            
'taxonomies'                     => $transformed_taxonomies,
            
'fallbacks'                      => $this->get_fallbacks(),
            
'showNewContentTypeNotification' => $show_new_content_type_notification,
        ];
    }

    
/**
     * Retrieves the preferences.
     *
     * @param array $settings The settings.
     *
     * @return array The preferences.
     */
    
protected function get_preferences$settings ) {
        
$shop_page_id             $this->woocommerce_helper->get_shop_page_id();
        
$homepage_is_latest_posts \get_option'show_on_front' ) === 'posts';
        
$page_on_front            \get_option'page_on_front' );
        
$page_for_posts           \get_option'page_for_posts' );

        
$wpseo_plugin_availability_checker = new WPSEO_Plugin_Availability();
        
$woocommerce_seo_file              'wpseo-woocommerce/wpseo-woocommerce.php';
        
$woocommerce_seo_active            $wpseo_plugin_availability_checker->is_active$woocommerce_seo_file );

        if ( empty( 
$page_on_front ) ) {
            
$page_on_front $page_for_posts;
        }

        
$business_settings_url \get_admin_urlnull'admin.php?page=wpseo_local' );
        if ( 
\defined'WPSEO_LOCAL_FILE' ) ) {
            
$local_options      \get_option'wpseo_local' );
            
$multiple_locations $local_options['use_multiple_locations'];
            
$same_organization  $local_options['multiple_locations_same_organization'];
            if ( 
$multiple_locations === 'on' && $same_organization !== 'on' ) {
                
$business_settings_url \get_admin_urlnull'edit.php?post_type=wpseo_locations' );
            }
        }

        return [
            
'isPremium'                     => $this->product_helper->is_premium(),
            
'isRtl'                         => \is_rtl(),
            
'isNetworkAdmin'                => \is_network_admin(),
            
'isMainSite'                    => \is_main_site(),
            
'isMultisite'                   => \is_multisite(),
            
'isWooCommerceActive'           => $this->woocommerce_helper->is_active(),
            
'isLocalSeoActive'              => \defined'WPSEO_LOCAL_FILE' ),
            
'isNewsSeoActive'               => \defined'WPSEO_NEWS_FILE' ),
            
'isWooCommerceSEOActive'        => $woocommerce_seo_active,
            
'promotions'                    => \YoastSEO()->classes->getPromotion_Manager::class )->get_current_promotions(),
            
'siteUrl'                       => \get_bloginfo'url' ),
            
'siteTitle'                     => \get_bloginfo'name' ),
            
'sitemapUrl'                    => WPSEO_Sitemaps_Router::get_base_url'sitemap_index.xml' ),
            
'hasWooCommerceShopPage'        => $shop_page_id !== -1,
            
'editWooCommerceShopPageUrl'    => \get_edit_post_link$shop_page_id'js' ),
            
'wooCommerceShopPageSettingUrl' => \get_admin_urlnull'admin.php?page=wc-settings&tab=products' ),
            
'localSeoPageSettingUrl'        => $business_settings_url,
            
'homepageIsLatestPosts'         => $homepage_is_latest_posts,
            
'homepagePageEditUrl'           => \get_edit_post_link$page_on_front'js' ),
            
'homepagePostsEditUrl'          => \get_edit_post_link$page_for_posts'js' ),
            
'createUserUrl'                 => \admin_url'user-new.php' ),
            
'createPageUrl'                 => \admin_url'post-new.php?post_type=page' ),
            
'editUserUrl'                   => \admin_url'user-edit.php' ),
            
'editTaxonomyUrl'               => \admin_url'edit-tags.php' ),
            
'generalSettingsUrl'            => \admin_url'options-general.php' ),
            
'companyOrPersonMessage'        => \apply_filters'wpseo_knowledge_graph_setting_msg''' ),
            
'currentUserId'                 => \get_current_user_id(),
            
'canCreateUsers'                => \current_user_can'create_users' ),
            
'canCreatePages'                => \current_user_can'edit_pages' ),
            
'canEditUsers'                  => \current_user_can'edit_users' ),
            
'canManageOptions'              => \current_user_can'manage_options' ),
            
'userLocale'                    => \str_replace'_''-'\get_user_locale() ),
            
'pluginUrl'                     => \plugins_url''\WPSEO_FILE ),
            
'showForceRewriteTitlesSetting' => ! \current_theme_supports'title-tag' ) && ! ( \function_exists'wp_is_block_theme' ) && \wp_is_block_theme() ),
            
'upsellSettings'                => $this->get_upsell_settings(),
            
'siteRepresentsPerson'          => $this->get_site_represents_person$settings ),
            
'siteBasicsPolicies'            => $this->get_site_basics_policies$settings ),
        ];
    }

    
/**
     * Retrieves the currently represented person.
     *
     * @param array $settings The settings.
     *
     * @return array The currently represented person's ID and name.
     */
    
protected function get_site_represents_person$settings ) {
        
$person = [
            
'id'   => false,
            
'name' => '',
        ];

        if ( isset( 
$settings['wpseo_titles']['company_or_person_user_id'] ) ) {
            
$person['id'] = $settings['wpseo_titles']['company_or_person_user_id'];
            
$user         \get_userdata$person['id'] );
            if ( 
$user instanceof WP_User ) {
                
$person['name'] = $user->get'display_name' );
            }
        }

        return 
$person;
    }

    
/**
     * Get site policy data.
     *
     * @param array $settings The settings.
     *
     * @return array The policy data.
     */
    
private function get_site_basics_policies$settings ) {
        
$policies = [];

        
$policies $this->maybe_add_policy$policies$settings['wpseo_titles']['publishing_principles_id'], 'publishing_principles_id' );
        
$policies $this->maybe_add_policy$policies$settings['wpseo_titles']['ownership_funding_info_id'], 'ownership_funding_info_id' );
        
$policies $this->maybe_add_policy$policies$settings['wpseo_titles']['actionable_feedback_policy_id'], 'actionable_feedback_policy_id' );
        
$policies $this->maybe_add_policy$policies$settings['wpseo_titles']['corrections_policy_id'], 'corrections_policy_id' );
        
$policies $this->maybe_add_policy$policies$settings['wpseo_titles']['ethics_policy_id'], 'ethics_policy_id' );
        
$policies $this->maybe_add_policy$policies$settings['wpseo_titles']['diversity_policy_id'], 'diversity_policy_id' );
        
$policies $this->maybe_add_policy$policies$settings['wpseo_titles']['diversity_staffing_report_id'], 'diversity_staffing_report_id' );

        return 
$policies;
    }

    
/**
     * Adds policy data if it is present.
     *
     * @param array  $policies The existing policy data.
     * @param int    $policy   The policy id to check.
     * @param string $key      The option key name.
     *
     * @return array<int,string> The policy data.
     */
    
private function maybe_add_policy$policies$policy$key ) {
        
$policy_array = [
            
'id'   => 0,
            
'name' => \__'None''wordpress-seo' ),
        ];

        if ( isset( 
$policy ) && \is_int$policy ) ) {
            
$policy_array['id'] = $policy;
            
$post               \get_post$policy );
            if ( 
$post instanceof WP_Post ) {
                if ( 
$post->post_status !== 'publish' || $post->post_password !== '' ) {
                    return 
$policies;
                }
                
$policy_array['name'] = $post->post_title;
            }
        }

        
$policies$key ] = $policy_array;

        return 
$policies;
    }

    
/**
     * Returns settings for the Call to Buy (CTB) buttons.
     *
     * @return array<string> The array of CTB settings.
     */
    
public function get_upsell_settings() {
        return [
            
'actionId'     => 'load-nfd-ctb',
            
'premiumCtbId' => 'f6a84663-465f-4cb5-8ba5-f7a6d72224b2',
        ];
    }

    
/**
     * Retrieves the default setting values.
     *
     * These default values are currently being used in the UI for dummy fields.
     * Dummy fields should not expose or reflect the actual data.
     *
     * @return array The default setting values.
     */
    
protected function get_default_setting_values() {
        
$defaults = [];

        
// Add Yoast settings.
        
foreach ( WPSEO_Options::$options as $option_name => $instance ) {
            if ( 
\in_array$option_nameself::ALLOWED_OPTION_GROUPStrue ) ) {
                
$option_instance          WPSEO_Options::get_option_instance$option_name );
                
$defaults$option_name ] = ( $option_instance ) ? $option_instance->get_defaults() : [];
            }
        }
        
// Add WP settings.
        
foreach ( self::WP_OPTIONS as $option_name ) {
            
$defaults$option_name ] = '';
        }

        
// Remove disallowed settings.
        
foreach ( self::DISALLOWED_SETTINGS as $option_name => $disallowed_settings ) {
            foreach ( 
$disallowed_settings as $disallowed_setting ) {
                unset( 
$defaults$option_name ][ $disallowed_setting ] );
            }
        }

        if ( 
\defined'WPSEO_LOCAL_FILE' ) ) {
            
$defaults $this->get_defaults_from_local_seo$defaults );
        }

        return 
$defaults;
    }

    
/**
     * Retrieves the organization schema values from Local SEO for defaults in Site representation fields.
     * Specifically for the org-vat-id, org-tax-id, org-email and org-phone options.
     *
     * @param array<string|int|bool> $defaults The settings defaults.
     *
     * @return array<string|int|bool> The settings defaults with local seo overides.
     */
    
protected function get_defaults_from_local_seo$defaults ) {
        
$local_options      \get_option'wpseo_local' );
        
$multiple_locations $local_options['use_multiple_locations'];
        
$same_organization  $local_options['multiple_locations_same_organization'];
        
$shared_info        $local_options['multiple_locations_shared_business_info'];
        if ( 
$multiple_locations !== 'on' || ( $multiple_locations === 'on' && $same_organization === 'on' && $shared_info === 'on' ) ) {
            
$defaults['wpseo_titles']['org-vat-id'] = $local_options['location_vat_id'];
            
$defaults['wpseo_titles']['org-tax-id'] = $local_options['location_tax_id'];
            
$defaults['wpseo_titles']['org-email']  = $local_options['location_email'];
            
$defaults['wpseo_titles']['org-phone']  = $local_options['location_phone'];
        }

        if ( 
\wpseo_has_primary_location() ) {
            
$primary_location $local_options['multiple_locations_primary_location'];

            
$location_keys = [
                
'org-phone'  => [
                    
'is_overridden' => '_wpseo_is_overridden_business_phone',
                    
'value'         => '_wpseo_business_phone',
                ],
                
'org-email'  => [
                    
'is_overridden' => '_wpseo_is_overridden_business_email',
                    
'value'         => '_wpseo_business_email',
                ],
                
'org-tax-id' => [
                    
'is_overridden' => '_wpseo_is_overridden_business_tax_id',
                    
'value'         => '_wpseo_business_tax_id',
                ],
                
'org-vat-id' => [
                    
'is_overridden' => '_wpseo_is_overridden_business_vat_id',
                    
'value'         => '_wpseo_business_vat_id',
                ],
            ];

            foreach ( 
$location_keys as $key => $meta_keys ) {
                
$is_overridden = ( $shared_info === 'on' ) ? \get_post_meta$primary_location$meta_keys['is_overridden'], true ) : false;
                if ( 
$is_overridden === 'on' || $shared_info !== 'on' ) {
                    
$post_meta_value                  \get_post_meta$primary_location$meta_keys['value'], true );
                    
$defaults['wpseo_titles'][ $key ] = ( $post_meta_value ) ? $post_meta_value '';
                }
            }
        }

        return 
$defaults;
    }

    
/**
     * Retrieves the settings and their values.
     *
     * @param array $default_setting_values The default setting values.
     *
     * @return array The settings.
     */
    
protected function get_settings$default_setting_values ) {
        
$settings = [];

        
// Add Yoast settings.
        
foreach ( WPSEO_Options::$options as $option_name => $instance ) {
            if ( 
\in_array$option_nameself::ALLOWED_OPTION_GROUPStrue ) ) {
                
$settings$option_name ] = \array_merge$default_setting_values$option_name ], WPSEO_Options::get_option$option_name ) );
            }
        }
        
// Add WP settings.
        
foreach ( self::WP_OPTIONS as $option_name ) {
            
$settings$option_name ] = \get_option$option_name );
        }

        
// Remove disallowed settings.
        
foreach ( self::DISALLOWED_SETTINGS as $option_name => $disallowed_settings ) {
            foreach ( 
$disallowed_settings as $disallowed_setting ) {
                unset( 
$settings$option_name ][ $disallowed_setting ] );
            }
        }

        return 
$settings;
    }

    
/**
     * Transforms setting values.
     *
     * @param array $settings The settings.
     *
     * @return array The settings.
     */
    
protected function transform_settings$settings ) {
        if ( isset( 
$settings['wpseo_titles']['breadcrumbs-sep'] ) ) {
            
/**
             * The breadcrumbs separator default value is the HTML entity `&raquo;`.
             * Which does not get decoded in our JS, while it did in our Yoast form. Decode it here as an exception.
             */
            
$settings['wpseo_titles']['breadcrumbs-sep'] = \html_entity_decode(
                
$settings['wpseo_titles']['breadcrumbs-sep'],
                ( 
\ENT_NOQUOTES \ENT_HTML5 ),
                
'UTF-8'
            
);
        }

        
/**
         * Decode some WP options.
         */
        
$settings['blogdescription'] = \html_entity_decode(
            
$settings['blogdescription'],
            ( 
\ENT_NOQUOTES \ENT_HTML5 ),
            
'UTF-8'
        
);

        return 
$settings;
    }

    
/**
     * Retrieves the disabled settings.
     *
     * @param array $settings The settings.
     *
     * @return array The settings.
     */
    
protected function get_disabled_settings$settings ) {
        
$disabled_settings = [];
        
$site_language     $this->language_helper->get_language();

        foreach ( 
WPSEO_Options::$options as $option_name => $instance ) {
            if ( ! 
\in_array$option_nameself::ALLOWED_OPTION_GROUPStrue ) ) {
                continue;
            }

            
$disabled_settings$option_name ] = [];
            
$option_instance                   WPSEO_Options::get_option_instance$option_name );
            if ( 
$option_instance === false ) {
                continue;
            }
            foreach ( 
$settings$option_name ] as $setting_name => $setting_value ) {
                if ( 
$option_instance->is_disabled$setting_name ) ) {
                    
$disabled_settings$option_name ][ $setting_name ] = 'network';
                }
            }
        }

        
// Remove disabled on multisite settings.
        
if ( \is_multisite() ) {
            foreach ( 
self::DISABLED_ON_MULTISITE_SETTINGS as $option_name => $disabled_ms_settings ) {
                if ( 
\array_key_exists$option_name$disabled_settings ) ) {
                    foreach ( 
$disabled_ms_settings as $disabled_ms_setting ) {
                        
$disabled_settings$option_name ][ $disabled_ms_setting ] = 'multisite';
                    }
                }
            }
        }

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

        return 
$disabled_settings;
    }

    
/**
     * Retrieves the replacement variables.
     *
     * @return array The replacement variables.
     */
    
protected function get_replacement_variables() {
        
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
        
$specific_replace_vars    = new WPSEO_Admin_Editor_Specific_Replace_Vars();
        
$replacement_variables    $this->replace_vars->get_replacement_variables_with_labels();

        return [
            
'variables'   => $replacement_variables,
            
'recommended' => $recommended_replace_vars->get_recommended_replacevars(),
            
'specific'    => $specific_replace_vars->get(),
            
'shared'      => $specific_replace_vars->get_generic$replacement_variables ),
        ];
    }

    
/**
     * Retrieves the schema.
     *
     * @param array $post_types The post types.
     *
     * @return array The schema.
     */
    
protected function get_schema( array $post_types ) {
        
$schema = [];

        foreach ( 
$this->schema_types->get_article_type_options() as $article_type ) {
            
$schema['articleTypes'][ $article_type['value'] ] = [
                
'label' => $article_type['name'],
                
'value' => $article_type['value'],
            ];
        }

        foreach ( 
$this->schema_types->get_page_type_options() as $page_type ) {
            
$schema['pageTypes'][ $page_type['value'] ] = [
                
'label' => $page_type['name'],
                
'value' => $page_type['value'],
            ];
        }

        
$schema['articleTypeDefaults'] = [];
        
$schema['pageTypeDefaults']    = [];
        foreach ( 
$post_types as $name => $post_type ) {
            
$schema['articleTypeDefaults'][ $name ] = WPSEO_Options::get_default'wpseo_titles'"schema-article-type-$name);
            
$schema['pageTypeDefaults'][ $name ]    = WPSEO_Options::get_default'wpseo_titles'"schema-page-type-$name);
        }

        return 
$schema;
    }

    
/**
     * Transforms the post types, to represent them.
     *
     * @param WP_Post_Type[] $post_types The WP_Post_Type array to transform.
     *
     * @return array The post types.
     */
    
protected function transform_post_types$post_types ) {
        
$transformed    = [];
        
$new_post_types $this->options->get'new_post_types', [] );
        foreach ( 
$post_types as $post_type ) {
            
$transformed$post_type->name ] = [
                
'name'                 => $post_type->name,
                
'route'                => $this->get_route$post_type->name$post_type->rewrite$post_type->rest_base ),
                
'label'                => $post_type->label,
                
'singularLabel'        => $post_type->labels->singular_name,
                
'hasArchive'           => $this->post_type_helper->has_archive$post_type ),
                
'hasSchemaArticleType' => $this->article_helper->is_article_post_type$post_type->name ),
                
'menuPosition'         => $post_type->menu_position,
                
'isNew'                => \in_array$post_type->name$new_post_typestrue ),
            ];
        }

        
\uasort$transformed, [ $this'compare_post_types' ] );

        return 
$transformed;
    }

    
/**
     * Compares two post types.
     *
     * @param array $a The first post type.
     * @param array $b The second post type.
     *
     * @return int The order.
     */
    
protected function compare_post_types$a$b ) {
        if ( 
$a['menuPosition'] === null && $b['menuPosition'] !== null ) {
            return 
1;
        }
        if ( 
$a['menuPosition'] !== null && $b['menuPosition'] === null ) {
            return -
1;
        }

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

        return ( ( 
$a['menuPosition'] < $b['menuPosition'] ) ? -);
    }

    
/**
     * Transforms the taxonomies, to represent them.
     *
     * @param WP_Taxonomy[] $taxonomies      The WP_Taxonomy array to transform.
     * @param string[]      $post_type_names The post type names.
     *
     * @return array The taxonomies.
     */
    
protected function transform_taxonomies$taxonomies$post_type_names ) {
        
$transformed    = [];
        
$new_taxonomies $this->options->get'new_taxonomies', [] );
        foreach ( 
$taxonomies as $taxonomy ) {
            
$transformed$taxonomy->name ] = [
                
'name'          => $taxonomy->name,
                
'route'         => $this->get_route$taxonomy->name$taxonomy->rewrite$taxonomy->rest_base ),
                
'label'         => $taxonomy->label,
                
'showUi'        => $taxonomy->show_ui,
                
'singularLabel' => $taxonomy->labels->singular_name,
                
'postTypes'     => \array_filter(
                    
$taxonomy->object_type,
                    static function ( 
$object_type ) use ( $post_type_names ) {
                        return 
\in_array$object_type$post_type_namestrue );
                    }
                ),
                
'isNew'         => \in_array$taxonomy->name$new_taxonomiestrue ),
            ];
        }

        
\uasort(
            
$transformed,
            static function ( 
$a$b ) {
                return 
\strnatcmp$a['label'], $b['label'] );
            }
        );

        return 
$transformed;
    }

    
/**
     * Gets the route from a name, rewrite and rest_base.
     *
     * @param string $name      The name.
     * @param array  $rewrite   The rewrite data.
     * @param string $rest_base The rest base.
     *
     * @return string The route.
     */
    
protected function get_route$name$rewrite$rest_base ) {
        
$route $name;
        if ( isset( 
$rewrite['slug'] ) ) {
            
$route $rewrite['slug'];
        }
        if ( ! empty( 
$rest_base ) ) {
            
$route $rest_base;
        }
        
// Always strip leading slashes.
        
while ( \substr$route0) === '/' ) {
            
$route \substr$route);
        }

        return 
\rawurlencode$route );
    }

    
/**
     * Retrieves the fallbacks.
     *
     * @return array The fallbacks.
     */
    
protected function get_fallbacks() {
        
$site_logo_id \get_option'site_logo' );
        if ( ! 
$site_logo_id ) {
            
$site_logo_id \get_theme_mod'custom_logo' );
        }
        if ( ! 
$site_logo_id ) {
            
$site_logo_id '0';
        }

        return [
            
'siteLogoId' => $site_logo_id,
        ];
    }
}