File: /home/zwafgyp/locationdebateau/wp-content/plugins/wp-seopress/src/Actions/Admin/ModuleSettings.php
<?php // phpcs:ignore
namespace SEOPress\Actions\Admin;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use SEOPress\Core\Hooks\ExecuteHooks;
/**
* Module settings for React admin pages.
*/
class ModuleSettings implements ExecuteHooks {
/**
* Supported pages and their configurations.
*
* @var array
*/
private $supported_pages = array(
'seopress-titles' => array(
'type' => 'titles',
'option' => 'seopress_titles_option_name',
),
'seopress-xml-sitemap' => array(
'type' => 'sitemaps',
'option' => 'seopress_xml_sitemap_option_name',
),
'seopress-social' => array(
'type' => 'social',
'option' => 'seopress_social_option_name',
),
'seopress-google-analytics' => array(
'type' => 'analytics',
'option' => 'seopress_google_analytics_option_name',
),
'seopress-instant-indexing' => array(
'type' => 'instant-indexing',
'option' => 'seopress_instant_indexing_option_name',
),
'seopress-advanced' => array(
'type' => 'advanced',
'option' => 'seopress_advanced_option_name',
),
'seopress-import-export' => array(
'type' => 'tools',
'option' => 'seopress_import_export_option_name',
),
);
/**
* Get supported pages, filtered for extensibility.
*
* @return array
*/
private function getSupportedPages() {
return apply_filters( 'seopress_settings_supported_pages', $this->supported_pages );
}
/**
* The ModuleSettings hooks.
*
* @since 5.0.0
*
* @return void
*/
public function hooks() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
}
/**
* Check if current page is a supported settings page.
*
* @return string|false Page key if supported, false otherwise.
*/
private function getCurrentPageKey() {
if ( ! isset( $_GET['page'] ) ) { // phpcs:ignore
return false;
}
$page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore
$supported = $this->getSupportedPages();
if ( isset( $supported[ $page ] ) ) {
return $page;
}
return false;
}
/**
* Get the navigation map of all SEOPress settings pages.
*
* @return array
*/
private function getAllPages() {
$pages = array(
array(
'slug' => 'seopress-titles',
'type' => 'titles',
'feature' => 'titles',
'label' => __( 'Titles & Metas', 'wp-seopress' ),
'url' => admin_url( 'admin.php?page=seopress-titles' ),
),
array(
'slug' => 'seopress-xml-sitemap',
'type' => 'sitemaps',
'feature' => 'xml-sitemap',
'label' => __( 'XML - HTML Sitemap', 'wp-seopress' ),
'url' => admin_url( 'admin.php?page=seopress-xml-sitemap' ),
),
array(
'slug' => 'seopress-social',
'type' => 'social',
'feature' => 'social',
'label' => __( 'Social Networks', 'wp-seopress' ),
'url' => admin_url( 'admin.php?page=seopress-social' ),
),
array(
'slug' => 'seopress-google-analytics',
'type' => 'analytics',
'feature' => 'google-analytics',
'label' => __( 'Analytics', 'wp-seopress' ),
'url' => admin_url( 'admin.php?page=seopress-google-analytics' ),
),
array(
'slug' => 'seopress-instant-indexing',
'type' => 'instant-indexing',
'feature' => 'instant-indexing',
'label' => __( 'Instant Indexing', 'wp-seopress' ),
'url' => admin_url( 'admin.php?page=seopress-instant-indexing' ),
),
array(
'slug' => 'seopress-advanced',
'type' => 'advanced',
'feature' => 'advanced',
'label' => __( 'Advanced', 'wp-seopress' ),
'url' => admin_url( 'admin.php?page=seopress-advanced' ),
),
array(
'slug' => 'seopress-import-export',
'type' => 'tools',
'feature' => null,
'label' => __( 'Tools', 'wp-seopress' ),
'url' => admin_url( 'admin.php?page=seopress-import-export' ),
),
);
return apply_filters( 'seopress_settings_all_pages', $pages );
}
/**
* Get page types that have working React implementations.
*
* @return array
*/
private function getReactReadyPages() {
return apply_filters( 'seopress_settings_react_ready_pages', array( 'titles', 'sitemaps', 'social', 'analytics', 'instant-indexing', 'advanced', 'tools' ) );
}
/**
* Enqueue scripts and styles for settings pages.
*
* @param string $hook The current admin page hook.
*
* @since 5.0.0
*
* @return void
*/
public function enqueue( $hook ) {
// Check if this is a supported settings page.
$page_key = $this->getCurrentPageKey();
if ( ! $page_key ) {
return;
}
// Check user capabilities.
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$supported = $this->getSupportedPages();
$page_config = $supported[ $page_key ];
// Load asset manifest generated by @wordpress/dependency-extraction-webpack-plugin.
$asset_file = SEOPRESS_PLUGIN_DIR_PATH . 'public/admin/settings.asset.php';
$asset = file_exists( $asset_file ) ? require $asset_file : array(
'dependencies' => array( 'react', 'react-dom', 'wp-components', 'wp-api-fetch', 'wp-i18n', 'wp-data', 'wp-notices', 'wp-element' ),
'version' => SEOPRESS_VERSION,
);
// Enqueue wp-components styles.
wp_enqueue_style( 'wp-components' );
// Enqueue settings CSS (extracted by webpack build).
$css_file = SEOPRESS_PLUGIN_DIR_PATH . 'public/admin/settings.css';
if ( file_exists( $css_file ) ) {
wp_enqueue_style(
'seopress-admin-settings',
SEOPRESS_URL_PUBLIC . '/admin/settings.css',
array( 'wp-components' ),
SEOPRESS_VERSION
);
}
// Enqueue media uploader for image fields.
wp_enqueue_media();
// Enqueue our React app.
wp_enqueue_script(
'seopress-admin-settings',
SEOPRESS_URL_PUBLIC . '/admin/settings.js',
$asset['dependencies'],
$asset['version'],
true
);
// Load translations for the React settings bundle.
// Point to wp-content/languages/plugins/ where GlotPress language packs are stored.
wp_set_script_translations( 'seopress-admin-settings', 'wp-seopress', WP_LANG_DIR . '/plugins' );
// Merge translations from lazy-loaded webpack chunks into the main script.
// GlotPress generates a separate JSON per chunk, but wp_set_script_translations
// only loads the one matching the main bundle. This filter merges all of them.
add_filter(
'pre_load_script_translations',
function ( $translations, $file, $handle, $domain ) {
if ( 'seopress-admin-settings' !== $handle || 'wp-seopress' !== $domain ) {
return $translations;
}
$locale = determine_locale();
$cache_key = 'seopress_i18n_merged_' . $locale;
$cached = wp_cache_get( $cache_key, 'seopress' );
if ( false !== $cached ) {
return $cached;
}
$lang_dir = WP_LANG_DIR . '/plugins';
$merged = array( 'locale_data' => array( 'messages' => array( '' => array() ) ) );
foreach ( glob( $lang_dir . '/wp-seopress-' . $locale . '-*.json' ) as $json_file ) {
$content = file_get_contents( $json_file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
if ( ! $content ) {
continue;
}
$data = json_decode( $content, true );
if ( ! isset( $data['locale_data']['messages'] ) ) {
continue;
}
foreach ( $data['locale_data']['messages'] as $key => $value ) {
if ( '' === $key ) {
if ( empty( $merged['locale_data']['messages'][''] ) ) {
$merged['locale_data']['messages'][''] = $value;
}
continue;
}
$merged['locale_data']['messages'][ $key ] = $value;
}
}
$result = wp_json_encode( $merged );
wp_cache_set( $cache_key, $result, 'seopress' );
return $result;
},
10,
4
);
// Get post types for the settings.
$post_types = $this->getPostTypes();
// Get taxonomies for the settings.
$taxonomies = $this->getTaxonomies();
// Get dynamic variables.
$dynamic_variables = function_exists( 'seopress_get_dyn_variables' )
? seopress_get_dyn_variables()
: array();
// Get docs links.
$docs_links = function_exists( 'seopress_get_docs_links' )
? seopress_get_docs_links()
: array();
// Detect NGINX.
$is_nginx = false;
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
$server_software = explode( '/', sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) );
$is_nginx = 'nginx' === strtolower( current( $server_software ) );
}
// Get sitemap post types (includes attachment).
$sitemap_post_types = $this->getSitemapPostTypes();
// Localize main data.
wp_localize_script(
'seopress-admin-settings',
'SEOPRESS_SETTINGS_DATA',
array(
'REST_URL' => rest_url(),
'NONCE' => wp_create_nonce( 'wp_rest' ),
'PAGE_TYPE' => $page_config['type'],
'OPTION_NAME' => $page_config['option'],
'DYNAMIC_VARIABLES' => $dynamic_variables,
'POST_TYPES' => $post_types,
'TAXONOMIES' => $taxonomies,
'SITEMAP_POST_TYPES' => $sitemap_post_types,
'FEATURE_ENABLED' => true,
'ADMIN_URL' => admin_url(),
'SITE_URL' => get_option( 'home' ),
'ALL_PAGES' => $this->getAllPages(),
'REACT_READY_PAGES' => $this->getReactReadyPages(),
'ASSETS_URL' => SEOPRESS_URL_PUBLIC,
'PLUGIN_URL' => SEOPRESS_PLUGIN_DIR_URL,
'DOCS_LINKS' => $docs_links,
'IS_NGINX' => $is_nginx,
'IMAGE_SIZES' => array_merge( get_intermediate_image_sizes(), array( 'full' ) ),
'USER_ROLES' => $this->getUserRoles(),
'INDEXING_LOG' => get_option( 'seopress_instant_indexing_log_option_name', array() ),
'INDEXING_NONCES' => array(
'submit' => wp_create_nonce( 'seopress_instant_indexing_post_nonce' ),
),
'AJAX_URL' => admin_url( 'admin-ajax.php' ),
'PANELS_STATE' => 'titles' === $page_config['type'] ? $this->getPanelsState() : new \stdClass(),
'FEATURE_TOGGLES' => $this->getFeatureToggles(),
'TOGGLE_NONCE' => wp_create_nonce( 'seopress_toggle_features_nonce' ),
'MIGRATION_NONCES' => $this->getMigrationNonces(),
'TOOLS_TABS' => $this->getToolsTabs(),
'TOOLS_EXTRA_RESET_ACTIONS' => apply_filters( 'seopress_react_tools_reset_actions', array() ),
'IS_PRO_ACTIVE' => is_plugin_active( 'wp-seopress-pro/seopress-pro.php' ),
'PROMOTIONS' => $this->getContextualPromotion( $page_config['type'] ),
'PROMO_NONCE' => wp_create_nonce( 'seopress_dismiss_promotion_nonce' ),
'EXTRA_API_ENDPOINTS' => apply_filters( 'seopress_settings_api_endpoints', array() ),
)
);
}
/**
* Get public post types for settings.
*
* @return array
*/
private function getPostTypes() {
$args = array( 'public' => true );
$args = apply_filters( 'seopress_get_post_types_args', $args );
$post_types = get_post_types( $args, 'objects' );
// Filter to only include viewable post types (matches WordPressData service).
$post_types = array_filter( $post_types, 'is_post_type_viewable' );
unset(
$post_types['attachment'],
$post_types['seopress_rankings'],
$post_types['seopress_backlinks'],
$post_types['seopress_404'],
$post_types['elementor_library'],
$post_types['customer_discount'],
$post_types['cuar_private_file'],
$post_types['cuar_private_page'],
$post_types['ct_template'],
$post_types['bricks_template']
);
$result = array();
foreach ( $post_types as $post_type ) {
$result[] = array(
'name' => $post_type->name,
'label' => $post_type->label,
'has_archive' => $post_type->has_archive,
);
}
return $result;
}
/**
* Get post types for sitemap settings (includes attachment).
*
* @return array
*/
private function getSitemapPostTypes() {
$post_types = get_post_types(
array(
'public' => true,
'show_ui' => true,
),
'objects'
);
$post_types = array_filter( $post_types, 'is_post_type_viewable' );
// Remove attachment if already present (we add it explicitly below).
$post_types = array_filter(
$post_types,
function ( $pt ) {
return 'attachment' !== $pt->name;
}
);
// Add attachment post type (matching PHP sitemap callback behavior).
$post_types[] = get_post_type_object( 'attachment' );
$result = array();
foreach ( $post_types as $post_type ) {
$result[] = array(
'name' => $post_type->name,
'label' => $post_type->label,
);
}
return $result;
}
/**
* Get user roles for settings.
*
* @return array
*/
private function getUserRoles() {
global $wp_roles;
if ( ! isset( $wp_roles ) ) {
$wp_roles = new \WP_Roles();
}
$roles = array();
foreach ( $wp_roles->get_names() as $key => $value ) {
$roles[] = array(
'key' => $key,
'name' => $value,
'label' => translate_user_role( $value, 'default' ),
);
}
return $roles;
}
/**
* Get migration nonces for AJAX migration handlers.
*
* @return array
*/
private function getMigrationNonces() {
return array(
'yoast' => wp_create_nonce( 'seopress_yoast_migrate_nonce' ),
'aio' => wp_create_nonce( 'seopress_aio_migrate_nonce' ),
'seo-framework' => wp_create_nonce( 'seopress_seo_framework_migrate_nonce' ),
'rk' => wp_create_nonce( 'seopress_rk_migrate_nonce' ),
'squirrly' => wp_create_nonce( 'seopress_squirrly_migrate_nonce' ),
'seo-ultimate' => wp_create_nonce( 'seopress_seo_ultimate_migrate_nonce' ),
'wp-meta-seo' => wp_create_nonce( 'seopress_meta_seo_migrate_nonce' ),
'premium-seo-pack' => wp_create_nonce( 'seopress_premium_seo_pack_migrate_nonce' ),
'smartcrawl' => wp_create_nonce( 'seopress_smart_crawl_migrate_nonce' ),
'slim-seo' => wp_create_nonce( 'seopress_slim_seo_migrate_nonce' ),
'siteseo' => wp_create_nonce( 'seopress_siteseo_migrate_nonce' ),
);
}
/**
* Get tools page tabs, filtered so PRO can add its own.
*
* @return array
*/
private function getToolsTabs() {
$tabs = array(
'tab_seopress_tool_settings' => __( 'Settings', 'wp-seopress' ),
'tab_seopress_tool_plugins' => __( 'Plugins', 'wp-seopress' ),
'tab_seopress_tool_reset' => __( 'Reset', 'wp-seopress' ),
);
return apply_filters( 'seopress_tools_tabs', $tabs );
}
/**
* Get contextual promotion for a page type.
*
* Reuses the same data source as the PHP-rendered promotions.
*
* @param string $page_type The page type (titles, sitemaps, analytics, advanced).
*
* @return array|null Promotion data or null.
*/
private function getContextualPromotion( $page_type ) {
if ( ! function_exists( 'seopress_get_contextual_promotion' ) ) {
return null;
}
return seopress_get_contextual_promotion( $page_type );
}
/**
* Get feature toggle states for all pages.
*
* @return array Keyed by feature slug, value is "1" (enabled) or "0".
*/
private function getFeatureToggles() {
$features = array( 'titles', 'xml-sitemap', 'social', 'google-analytics', 'instant-indexing', 'advanced' );
$features = apply_filters( 'seopress_settings_feature_toggle_keys', $features );
$toggles = array();
foreach ( $features as $feature ) {
$toggles[ $feature ] = ( '1' == seopress_get_toggle_option( $feature ) ) ? '1' : '0'; // phpcs:ignore
}
return $toggles;
}
/**
* Get public taxonomies for settings.
*
* @return array
*/
private function getTaxonomies() {
// Match the WordPressData service: public OR publicly_queryable.
$args = array(
'public' => true,
'publicly_queryable' => true,
);
$args = apply_filters( 'seopress_get_taxonomies_args', $args );
$taxonomies = get_taxonomies( $args, 'objects', 'or' );
$result = array();
foreach ( $taxonomies as $taxonomy ) {
$result[] = array(
'name' => $taxonomy->name,
'label' => $taxonomy->label,
);
}
return $result;
}
/**
* Get current user's panels expand/collapse state.
*
* @return array
*/
private function getPanelsState() {
$user_id = get_current_user_id();
$state = get_user_meta( $user_id, 'seopress_panels_state', true );
if ( ! is_array( $state ) ) {
$state = array();
}
return $state;
}
}