get_bloginfo('name'),'company_type'=>'Organization','phone'=>'','address'=>'','city'=>'','postal'=>'','country'=>'FR','lat'=>'','lng'=>'','hours'=>'','gsc'=>'','bing'=>'','pinterest'=>'','clarity'=>'','indexnow'=>'','robots_extra'=>'','facebook'=>'','x'=>'','linkedin'=>'','tiktok'=>'','social_default_image'=>'','social_enabled'=>'1','social_open_graph'=>'1','social_twitter'=>'1','social_product'=>'1','social_page'=>'1','social_post'=>'1','social_term'=>'1','social_twitter_card'=>'summary_large_image','redirects_enabled'=>'1','log404_enabled'=>'1','pagespeed_key'=>'','gsc_client_id'=>'','gsc_client_secret'=>'','gsc_property'=>home_url('/'),'rss_before'=>'','rss_after'=>__('Source: %%POSTLINK%% — %%BLOGLINK%%', 'multipify-seo-boost'),'schema_graph_enabled'=>'1','schema_author'=>'1','schema_taxonomy'=>'1','schema_breadcrumb'=>'1','schema_content'=>'1','schema_webpage'=>'1','schema_search'=>'1','schema_website'=>'1','schema_organization'=>'1','title_suffix_enabled'=>'0','title_suffix_text'=>'','title_suffix_product'=>'1','title_suffix_page'=>'1','title_suffix_post'=>'1','title_suffix_term'=>'1','content_post_templates'=>'1','content_post_description'=>'1','content_post_noindex'=>'0','content_page_templates'=>'1','content_page_description'=>'1','content_page_noindex'=>'0','content_product_templates'=>'1','content_product_description'=>'1','content_product_noindex'=>'0','content_term_templates'=>'1','content_term_description'=>'1','content_term_noindex'=>'0','delete_data_on_uninstall'=>'0','home_title'=>'','home_description'=>'','llms_enabled'=>'1','cleanup_generator'=>'0','cleanup_rsd'=>'0','cleanup_shortlink'=>'0','cleanup_rest_link'=>'0','cleanup_oembed'=>'0','cleanup_emoji'=>'0','cleanup_comment_feeds'=>'0','cleanup_pingback'=>'0']+(class_exists('MPSEO_V52_Options')?MPSEO_V52_Options::defaults():[]);} static function init(){add_action('admin_menu',[__CLASS__,'menu']);add_action('admin_init',[__CLASS__,'settings']);add_action('admin_enqueue_scripts',[__CLASS__,'assets']);} static function menu(){ $manage=MPSEO_Access::CAP_MANAGE;$settings=MPSEO_Access::CAP_SETTINGS;$audit=MPSEO_Access::CAP_AUDIT;$redir=MPSEO_Access::CAP_REDIRECTS;$ai=MPSEO_Access::CAP_AI; add_menu_page('Multipify SEO Boost','Multipify SEO Boost',$manage,'mpseo-dashboard',[__CLASS__,'dashboard'],'dashicons-chart-line',58); $menus=[ ['mpseo-priorities',__('SEO priorities', 'multipify-seo-boost'),'priorities',$manage],['mpseo-health',__('SEO health', 'multipify-seo-boost'),'health',$manage],['mpseo-features',__('Modules', 'multipify-seo-boost'),'features',$manage],['mpseo-statistics',__('SEO statistics', 'multipify-seo-boost'),'statistics',$manage],['mpseo-performance',__('Performance & opportunities', 'multipify-seo-boost'),'performance',$manage],['mpseo-content-decay',__('Content to refresh', 'multipify-seo-boost'),'content_decay',$manage],['mpseo-revisions',__('SEO revisions', 'multipify-seo-boost'),'revisions',$manage],['mpseo-links',__('Internal links', 'multipify-seo-boost'),'links',$manage],['mpseo-bulk',__('Bulk editor', 'multipify-seo-boost'),'bulk',$manage], ['mpseo-audit',__('SEO audit', 'multipify-seo-boost'),'audit',$audit],['mpseo-pagespeed','PageSpeed','pagespeed',$audit],['mpseo-redirects',__('Redirects & 404', 'multipify-seo-boost'),'redirects',$redir],['mpseo-automations',__('SEO automations', 'multipify-seo-boost'),'automations',$redir], ['mpseo-setup',__('Configuration', 'multipify-seo-boost'),'setup',$settings],['mpseo-connections',__('Connections', 'multipify-seo-boost'),'connections',$settings],['mpseo-local',__('Local SEO', 'multipify-seo-boost'),'local',$settings],['mpseo-indexing',__('Indexing & robots', 'multipify-seo-boost'),'indexing',$settings],['mpseo-tools',__('SEO tools', 'multipify-seo-boost'),'tools',$settings],['mpseo-import',__('SEO import', 'multipify-seo-boost'),'import',$settings],['mpseo-templates',__('SEO templates', 'multipify-seo-boost'),'templates',$settings],['mpseo-access',__('Access & permissions', 'multipify-seo-boost'),'access',$settings],['mpseo-diagnostics',__('Diagnostics', 'multipify-seo-boost'),'diagnostics',$settings],['mpseo-security',__('Security', 'multipify-seo-boost'),'security',$settings],['mpseo-settings',__('Settings', 'multipify-seo-boost'),'settings_page',$settings] ]; foreach($menus as $m)add_submenu_page('mpseo-dashboard',$m[1],$m[1],$m[3],$m[0],[__CLASS__,$m[2]]); // Keep every page registered and accessible, but simplify the WP sidebar. add_action('admin_menu',[__CLASS__,'compact_menu'],9999); } static function compact_menu(){ if(class_exists('MPSEO_V800_Studio')){MPSEO_V800_Studio::wp_menu();return;} // Hide secondary links from the WP sidebar with a CSS class instead of unsetting them: // WordPress refuses access (403) to admin.php?page= routes that are missing from $submenu. $keep=['mpseo-dashboard','mpseo-bulk','mpseo-audit','mpseo-statistics','mpseo-redirects','mpseo-settings']; global $submenu; if(empty($submenu['mpseo-dashboard'])||!is_array($submenu['mpseo-dashboard']))return; foreach($submenu['mpseo-dashboard'] as $key=>$item){ $slug=isset($item[2])?(string)$item[2]:''; if(strpos($slug,'mpseo-')===0&&!in_array($slug,$keep,true))$submenu['mpseo-dashboard'][$key][4]=trim(($item[4]??'').' mpseo-menu-hidden'); } if(!has_action('admin_enqueue_scripts',[__CLASS__,'hidden_menu_css']))add_action('admin_enqueue_scripts',[__CLASS__,'hidden_menu_css']); } static function hidden_menu_css(){MPSEO_Inline_Assets::style('#adminmenu .mpseo-menu-hidden{display:none!important}');} static function priorities(){MPSEO_V771_Priorities::page();} static function settings(){register_setting('mpseo_group',MPSEO_Core::SETTINGS,['sanitize_callback'=>[__CLASS__,'sanitize']]);} static function sanitize($v){ $v=is_array($v)?wp_unslash($v):[]; // This callback is invoked by the WordPress Settings API (options.php), which validates the options nonce before sanitizing. // phpcs:disable WordPress.Security.NonceVerification.Missing $partial=isset($_POST['mpseo_settings_partial']) && is_scalar($_POST['mpseo_settings_partial']) && sanitize_text_field(wp_unslash($_POST['mpseo_settings_partial']))==='1'; // phpcs:enable WordPress.Security.NonceVerification.Missing $previous=(array)get_option(MPSEO_Core::SETTINGS,[]); $d=$partial?array_merge(self::defaults(),$previous):self::defaults(); $urls= [] ; foreach($d as $k=>$x){ if(!array_key_exists($k,$v)&&$partial)continue; $raw=$v[$k]??''; if(!is_scalar($raw))continue; $raw=(string)$raw; if(class_exists('MPSEO_V52_Options')&&MPSEO_V52_Options::has($k))$d[$k]=MPSEO_V52_Options::clean($k,$raw); elseif($k==='ai_daily_limit')$d[$k]=(string)max(1,min(10000,absint($raw))); elseif(in_array($k,['enable_meta_keywords','schema_graph_enabled','schema_organization','schema_website','schema_search','schema_webpage','schema_content','schema_breadcrumb','schema_taxonomy','schema_author','social_enabled','social_open_graph','social_twitter','social_product','social_page','social_post','social_term','redirects_enabled','log404_enabled','llms_enabled','cleanup_generator','cleanup_rsd','cleanup_shortlink','cleanup_rest_link','cleanup_oembed','cleanup_emoji','cleanup_comment_feeds','cleanup_pingback','title_suffix_enabled','title_suffix_product','title_suffix_page','title_suffix_post','title_suffix_term','content_post_templates','content_post_description','content_post_noindex','content_page_templates','content_page_description','content_page_noindex','content_product_templates','content_product_description','content_product_noindex','content_term_templates','content_term_description','content_term_noindex','delete_data_on_uninstall'],true))$d[$k]=empty($raw)?'0':'1'; elseif(in_array($k,$urls,true)){ $url=trim($raw); if($url!=='' && (!wp_http_validate_url($url)||strtolower((string)wp_parse_url($url,PHP_URL_SCHEME))!=='https')){ add_settings_error('mpseo_group','mpseo_invalid_url_'.sanitize_key($k),__('Invalid HTTPS address: the previous setting was kept.', 'multipify-seo-boost'),'error'); $d[$k]=$previous[$k]??''; }else $d[$k]=esc_url_raw($url); } elseif($k==='social_default_image'){ $url=trim($raw); if($url!=='' && (strtolower((string)wp_parse_url($url,PHP_URL_SCHEME))!=='https'||!filter_var($url,FILTER_VALIDATE_URL))){ add_settings_error('mpseo_group','mpseo_invalid_social_image',__('The social image must use a valid HTTPS URL.', 'multipify-seo-boost'),'error'); $d[$k]=$previous[$k]??''; }else $d[$k]=esc_url_raw($url,['https']); } elseif($k==='social_twitter_card')$d[$k]=in_array($raw,['summary','summary_large_image'],true)?$raw:'summary_large_image'; elseif($k==='title_suffix_text')$d[$k]=mb_substr(sanitize_text_field($raw),0,65); elseif(in_array($k,['openai_key','robots_extra'],true))$d[$k]=sanitize_textarea_field($raw); else $d[$k]=sanitize_text_field($raw); } // A visible warning also survives direct POST requests without JavaScript. foreach(['content_post_noindex'=>__('posts', 'multipify-seo-boost'),'content_page_noindex'=>__('pages', 'multipify-seo-boost'),'content_product_noindex'=>__('products', 'multipify-seo-boost'),'content_term_noindex'=>__('categories and taxonomies', 'multipify-seo-boost')] as $key=>$label){ if(($d[$key]??'0')==='1'&&($previous[$key]??'0')!=='1'){ add_settings_error('mpseo_group','mpseo_noindex_warning_'.$key,(__('Warning: noindex by default has just been enabled for', 'multipify-seo-boost') . ' ').$label.'. '.__('Check the individual exceptions and the sitemap.', 'multipify-seo-boost'),'warning'); } } return $d; } static function assets($h){ $screen=function_exists('get_current_screen')?get_current_screen():null; $is_editor=in_array($h,['post.php','post-new.php'],true)&&$screen&&post_type_supports($screen->post_type,'editor'); $is_taxonomy=in_array($h,['edit-tags.php','term.php'],true)&&$screen&&!empty($screen->taxonomy)&&taxonomy_exists($screen->taxonomy); if(strpos($h,'mpseo')===false&&!$is_editor&&!$is_taxonomy)return; wp_enqueue_style('mpseo',plugins_url('../assets/admin.css',__FILE__),[],MPSEO_VERSION);if(isset($_GET['page'])&&in_array(sanitize_key(wp_unslash($_GET['page'])),['mpseo-dashboard','mpseo-multipify-vps','mpseo-file-editor','mpseo-keywords','mpseo-indexing-inspector'],true))wp_enqueue_style('mpseo-dashboard-v46',plugins_url('../assets/dashboard-v46.css',__FILE__),['mpseo'],MPSEO_VERSION);wp_enqueue_style('mpseo-mobile-premium',plugins_url('../assets/mobile-premium.css',__FILE__),['mpseo'],MPSEO_VERSION);wp_enqueue_script('mpseo',plugins_url('../assets/admin.js',__FILE__),['jquery'],MPSEO_VERSION,true);wp_localize_script('mpseo','MPSEO',['ajax'=>admin_url('admin-ajax.php'),'nonce'=>wp_create_nonce('mpseo'),'scoreNonce'=>wp_create_nonce('mpseo_score_backfill')]);if($is_taxonomy)wp_enqueue_script('mpseo-taxonomy-live',plugins_url('../assets/taxonomy-live.js',__FILE__),[],MPSEO_VERSION,true);} // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- page slug read only to choose stylesheets. /** Diagnostic informatif des extensions SEO concurrentes (sans modification). */ static function seo_conflicts(){ $known=['wordpress-seo/wp-seo.php'=>'Yoast SEO','seo-by-rank-math/rank-math.php'=>'Rank Math SEO','all-in-one-seo-pack/all_in_one_seo_pack.php'=>'All in One SEO','wp-seopress/seopress.php'=>'SEOPress','autodescription/autodescription.php'=>'The SEO Framework']; $active=(array)get_option('active_plugins',[]); if(is_multisite())$active=array_merge($active,array_keys((array)get_site_option('active_sitewide_plugins',[]))); $found=[]; foreach($known as $slug=>$name){if(in_array($slug,$active,true))$found[]=$name;} return array_values(array_unique($found)); } static function seo_conflicts_notice(){ $found=self::seo_conflicts(); if(!$found)return; $url=admin_url('admin.php?page=mpseo-settings'); echo ('

' . esc_html__('SEO conflict check', 'multipify-seo-boost') . '

' . esc_html__('Another SEO plugin is active:', 'multipify-seo-boost') . ' ').esc_html(implode(', ',$found)).'. ' . esc_html__('Check titles, meta descriptions, social tags, structured data and sitemaps: two generators can create duplicates.', 'multipify-seo-boost') . '

' . esc_html__('This check does not deactivate any plugin and does not prove that a duplicate exists.', 'multipify-seo-boost') . '

' . esc_html__('Check the Multipify settings', 'multipify-seo-boost') . '
'; } // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- $url() returns esc_url() output and $details is esc_html() output. static function dashboard(){ if(!current_user_can('manage_options'))return; $health=MPSEO_Health::report();$score=(int)($health['score']??0); $pub=0;foreach(get_post_types(['public'=>true]) as $pt){if($pt!=='attachment')$pub+=(int)(wp_count_posts($pt)->publish??0);} $recent=get_posts(['post_type'=>array_values(array_diff(get_post_types(['public'=>true]),['attachment'])),'post_status'=>'publish','posts_per_page'=>5,'orderby'=>'modified','order'=>'DESC']); $url=function($slug){return esc_url(admin_url('admin.php?page='.$slug));}; $user=wp_get_current_user();$name=$user&&$user->display_name?$user->display_name:''; // V69: WordPress places its notices (and the host's banners) after .wp-header-end, i.e. above the hero, never over it. echo '

'; /* translators: %s: user display name. */ $hello=$name!==''?sprintf(__('Hello %s!','multipify-seo-boost'),$name):__('Hello!','multipify-seo-boost'); echo '
'.esc_html__('YOUR SEO SPACE','multipify-seo-boost').'

'.esc_html($hello).' 👋
'. esc_html__('Your site is ready to be optimized','multipify-seo-boost') .'

'. esc_html__('Multipify analyses your content and helps you improve your ranking on Google.','multipify-seo-boost') .'

'; self::seo_conflicts_notice(); echo '
'; $details=esc_html__('See details','multipify-seo-boost'); foreach([[__('SEO health score','multipify-seo-boost'),$score.'/100','dashicons-heart','violet','mpseo-audit'],[__('Published content','multipify-seo-boost'),$pub,'dashicons-media-document','blue','mpseo-bulk'],[__('Recently updated pages','multipify-seo-boost'),count($recent),'dashicons-update','green','mpseo-bulk'], [__('Redirects','multipify-seo-boost'),(function(){$c=MPSEO_Redirects::counts();return (int)($c['exact']??0)+(int)($c['regex']??0);})(),'dashicons-randomize','amber','mpseo-redirects'] ] as $m){echo ''.esc_html($m[0]).''.esc_html((string)$m[1]).''.$details.' →';} echo '
'; echo '

Multipify SEO Boost Pro

'.esc_html__('Go further with the Pro add-on','multipify-seo-boost').'

'.esc_html__('Speed optimisation, AI writing, image SEO scores, advanced block editor tools and meta keywords are available in the separate Multipify SEO Boost Pro plugin.','multipify-seo-boost').'

'.esc_html__('Discover Pro','multipify-seo-boost').' →
'; echo '

'.esc_html__('Quick optimization','multipify-seo-boost').'

SEO

'.esc_html__('What the optimization tools do on your content:','multipify-seo-boost').'

    '; foreach([__('Optimize titles and meta descriptions','multipify-seo-boost'),__('Check keywords and readability','multipify-seo-boost'),__('Improve existing content','multipify-seo-boost'),__('Review links and SEO errors','multipify-seo-boost')] as $t)echo '
  • '.esc_html($t).'
  • '; echo '
'.esc_html__('Open the optimization tools','multipify-seo-boost').' →
'; echo '

⚡ '.esc_html__('Quick actions','multipify-seo-boost').'

'; foreach([[__('Analyse my site','multipify-seo-boost'),'mpseo-audit','dashicons-search'],[__('Optimize content','multipify-seo-boost'),'mpseo-bulk','dashicons-edit-page'],[__('View my statistics','multipify-seo-boost'),'mpseo-statistics','dashicons-chart-bar'],[__('Manage redirects','multipify-seo-boost'),'mpseo-redirects','dashicons-randomize'],[__('Configure SEO','multipify-seo-boost'),'mpseo-settings','dashicons-admin-generic']] as $a){echo ''.esc_html($a[0]).' →';} echo '
'; } // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped static function features(){ $items=[ [__('Analysis & content', 'multipify-seo-boost'),'mpseo-bulk','dashicons-analytics',__('SEO editor, scores and optimizations', 'multipify-seo-boost')], [__('Technical audit', 'multipify-seo-boost'),'mpseo-audit','dashicons-search',__('Detect site errors', 'multipify-seo-boost')], [__('Internal links', 'multipify-seo-boost'),'mpseo-links','dashicons-admin-links',__('Improve internal linking', 'multipify-seo-boost')], [__('Indexing', 'multipify-seo-boost'),'mpseo-indexing','dashicons-visibility',__('Robots, sitemaps and indexing', 'multipify-seo-boost')], [__('Local SEO', 'multipify-seo-boost'),'mpseo-local','dashicons-location',__('Business and local data', 'multipify-seo-boost')], [__('Connections', 'multipify-seo-boost'),'mpseo-connections','dashicons-admin-network', __('Search Console, PageSpeed and IndexNow', 'multipify-seo-boost') ], [__('SEO templates', 'multipify-seo-boost'),'mpseo-templates','dashicons-editor-table',__('Reuse templates', 'multipify-seo-boost')], [__('Diagnostics', 'multipify-seo-boost'),'mpseo-diagnostics','dashicons-shield',__('Check the configuration', 'multipify-seo-boost')] ]; echo ('
' . esc_html__('WORKSPACE', 'multipify-seo-boost') . '

' . esc_html__('Explore the SEO tools', 'multipify-seo-boost') . '

' . esc_html__('Find each feature in the right place. Start by analyzing your content or open a technical tool directly.', 'multipify-seo-boost') . '

'; foreach($items as $item){echo ''.esc_html($item[0]).''.esc_html($item[3]).'' . esc_html__('Open →', 'multipify-seo-boost') . '';} echo '
'; } /** V69: small hero at the top of each settings section (icon, title, text, key facts). */ static function section_heading($slug,$label,$help,$count){ $icons=['general'=>'dashicons-admin-home','content'=>'dashicons-media-document','schema'=>'dashicons-editor-code','webmaster'=>'dashicons-admin-tools','social'=>'dashicons-share','crawl'=>'dashicons-superhero-alt','redirects'=>'dashicons-randomize','advanced'=>'dashicons-admin-generic','appearance'=>'dashicons-visibility','breadcrumbs'=>'dashicons-menu-alt3','onpage'=>'dashicons-search','analytics'=>'dashicons-chart-area','sitemaps_extra'=>'dashicons-networking','reports'=>'dashicons-email-alt','admin'=>'dashicons-edit-page','woocommerce'=>'dashicons-cart']; $warn=['advanced'=>__('Expert settings','multipify-seo-boost'),'content'=>__('Affects indexing','multipify-seo-boost')]; /* translators: %d: number of options in the section. */ $chips=[''.esc_html($count===1?__('1 option','multipify-seo-boost'):sprintf(__('%d options','multipify-seo-boost'),$count)),''.esc_html__('Saved separately','multipify-seo-boost')]; if(isset($warn[$slug]))$chips[]=''.esc_html($warn[$slug]); $html='
'.esc_html__('Settings ·', 'multipify-seo-boost').' '.esc_html($label).'

'.esc_html($help[0]).'

'.($help[1]!==''?'

'.esc_html($help[1]).'

':'').'
'; } static function fields($keys){ $hints_extra=class_exists('MPSEO_V802_Cleanup')?array_map(function($o){return $o[1];},MPSEO_V802_Cleanup::options()):[]; $hints=[ 'rss_after'=>sprintf(/* translators: %s: list of template variables. */ __('Added at the end of each post in the RSS feed; protects against automated scraping. Variables: %s.', 'multipify-seo-boost'), '%title%, %link%, %site%, %site_link%, %author%, %date%'), 'rss_before'=>sprintf(/* translators: %1$s, %2$s: lists of template variables. */ __('Variables: %1$s (post link), %2$s.', 'multipify-seo-boost'), '%title%, %link%', '%site%, %site_link%, %author%, %date%'), 'hours'=>__('One range per line, in Schema.org format: “Mo-Fr 09:00-18:00”, “Sa 10:00-17:00”. Published in the LocalBusiness structured data.', 'multipify-seo-boost'), 'company_name'=>__('Public name used in your business’s structured data.', 'multipify-seo-boost'), 'company_type'=>__('Type of organization to fill in according to your activity.', 'multipify-seo-boost'), 'social_enabled'=>__('Turns off all social tags output by Multipify without touching saved metadata.', 'multipify-seo-boost'), 'social_open_graph'=>__('Facebook, LinkedIn and other Open Graph-compatible network tags.', 'multipify-seo-boost'), 'social_twitter'=>__('X / Twitter card tags.', 'multipify-seo-boost'), 'social_product'=>__('WooCommerce product pages.', 'multipify-seo-boost'), 'social_page'=>__('WordPress pages.', 'multipify-seo-boost'), 'social_post'=>__('WordPress posts.', 'multipify-seo-boost'), 'social_term'=>__('Public categories and taxonomies.', 'multipify-seo-boost'), 'social_default_image'=>__('Used if no specific social image or featured image is available. Public HTTPS URL recommended (1200 × 630 px).', 'multipify-seo-boost'), 'social_twitter_card'=>__('summary_large_image for a large image, summary for a compact card. Each item can have its own choice.', 'multipify-seo-boost'), 'title_suffix_enabled'=>__('Automatically adds the suffix to the SEO titles of the selected types, without changing saved titles.', 'multipify-seo-boost'), 'title_suffix_text'=>__('Example: | shopify.com. The full title is limited to 70 characters. The suffix is added without changing the saved title.', 'multipify-seo-boost'), 'title_suffix_product'=>__('WooCommerce products.', 'multipify-seo-boost'), 'title_suffix_page'=>__('WordPress pages.', 'multipify-seo-boost'), 'title_suffix_post'=>__('WordPress posts.', 'multipify-seo-boost'), 'title_suffix_term'=>__('Categories and other public taxonomies.', 'multipify-seo-boost'), 'gsc'=>__('Verification code provided by Google Search Console.', 'multipify-seo-boost'), 'bing'=>__('Verification code provided by Bing Webmaster Tools.', 'multipify-seo-boost'), 'pinterest'=>__('Verification code for your Pinterest domain.', 'multipify-seo-boost'), 'clarity'=>__('Microsoft Clarity project ID.', 'multipify-seo-boost'), 'indexnow'=>__('Key used to notify compatible search engines.', 'multipify-seo-boost'), 'pagespeed_key'=>__('Google API key for PageSpeed analyses.', 'multipify-seo-boost'), 'gsc_client_id'=>__('OAuth client ID obtained in Google Cloud.', 'multipify-seo-boost'), 'gsc_client_secret'=>__('OAuth secret: never share it publicly.', 'multipify-seo-boost'), 'gsc_property'=>__('Search Console property matching your site.', 'multipify-seo-boost'), 'robots_extra'=>__('Only add robots.txt directives whose effect you understand.', 'multipify-seo-boost'), 'schema_organization'=>__('Publisher identity. Disable it if another plugin already outputs this entity.', 'multipify-seo-boost'), 'schema_website'=>__('WebSite entity, usually useful on the home page.', 'multipify-seo-boost'), 'schema_search'=>__('SearchAction inside WebSite; enable it only if your internal search works.', 'multipify-seo-boost'), 'schema_webpage'=>__('WebPage node on individual content.', 'multipify-seo-boost'), 'schema_content'=>__('Article, BlogPosting or another type set on the item. WooCommerce Product remains handled by WooCommerce.', 'multipify-seo-boost'), 'schema_breadcrumb'=>__('BreadcrumbList breadcrumbs and their references.', 'multipify-seo-boost'), 'schema_taxonomy'=>__('CollectionPage and other taxonomy archive types.', 'multipify-seo-boost'), 'schema_author'=>__('Person entity on author archives.', 'multipify-seo-boost'), 'schema_graph_enabled'=>__('Disables the central Multipify JSON-LD graph if another plugin already handles Schema.org. WooCommerce Schema data stays independent.', 'multipify-seo-boost'),'delete_data_on_uninstall'=>__('Warning: may delete the plugin’s data when it is uninstalled.', 'multipify-seo-boost'), 'home_title'=>sprintf(/* translators: %s: list of template variables. */ __('Used when the home page shows the latest posts (otherwise, set the SEO title of the home page itself). Variables: %s. Empty = “Site name – Tagline”.', 'multipify-seo-boost'), '%site%, %tagline%, %sep%, %year%'), 'home_description'=>sprintf(/* translators: %s: list of template variables. */ __('About 120 to 160 characters. Empty = site tagline. Variables: %s.', 'multipify-seo-boost'), '%site%, %tagline%, %year%'), 'llms_enabled'=>__('Text file served at /llms.txt, updated automatically. Ignored if an llms.txt file already exists at the root.', 'multipify-seo-boost'), ]; $hints=array_merge($hints_extra,$hints); $o=array_merge(self::defaults(),(array)get_option(MPSEO_Core::SETTINGS,[]));foreach($keys as $k=>$label){if(class_exists('MPSEO_V52_Options')&&MPSEO_V52_Options::has($k)){MPSEO_V52_Options::row($k,$label,$o);continue;}$type=in_array($k,['hours','robots_extra'])?'textarea':'input';echo ''.esc_html($label).'';if(in_array($k,['enable_meta_keywords','schema_graph_enabled','schema_organization','schema_website','schema_search','schema_webpage','schema_content','schema_breadcrumb','schema_taxonomy','schema_author','social_enabled','social_open_graph','social_twitter','social_product','social_page','social_post','social_term','redirects_enabled','log404_enabled','llms_enabled','cleanup_generator','cleanup_rsd','cleanup_shortlink','cleanup_rest_link','cleanup_oembed','cleanup_emoji','cleanup_comment_feeds','cleanup_pingback','delete_data_on_uninstall','title_suffix_enabled','title_suffix_product','title_suffix_page','title_suffix_post','title_suffix_term','content_post_templates','content_post_description','content_post_noindex','content_page_templates','content_page_description','content_page_noindex','content_product_templates','content_product_description','content_product_noindex','content_term_templates','content_term_description','content_term_noindex'],true)){echo ''; }elseif($type==='textarea')echo '';else echo '';echo isset($hints[$k])?'

'.esc_html($hints[$k]).'

':'';echo '';}} static function settings_page(){ $groups=[ 'general'=>[__('General', 'multipify-seo-boost'),'home_title'=>__('Home page SEO title', 'multipify-seo-boost'),'home_description'=>__('Home page meta description', 'multipify-seo-boost'),'schema_graph_enabled'=>__('Enable the Multipify Schema.org graph', 'multipify-seo-boost'),'company_name'=>__('Business', 'multipify-seo-boost'),'company_type'=>__('Schema type', 'multipify-seo-boost'),'title_suffix_enabled'=>__('Enable the automatic suffix', 'multipify-seo-boost'),'title_suffix_text'=>__('Second part of the SEO title', 'multipify-seo-boost'),'title_suffix_product'=>__('Apply to products', 'multipify-seo-boost'),'title_suffix_page'=>__('Apply to pages', 'multipify-seo-boost'),'title_suffix_post'=>__('Apply to posts', 'multipify-seo-boost'),'title_suffix_term'=>__('Apply to categories / taxonomies', 'multipify-seo-boost')], 'content'=>[__('SEO by content type', 'multipify-seo-boost'),'content_post_templates'=>__('Posts — Use automatic SEO templates', 'multipify-seo-boost'),'content_post_description'=>__('Posts — Output the Multipify meta description', 'multipify-seo-boost'),'content_post_noindex'=>__('Posts — Noindex by default (careful)', 'multipify-seo-boost'),'content_page_templates'=>__('Pages — Use automatic SEO templates', 'multipify-seo-boost'),'content_page_description'=>__('Pages — Output the Multipify meta description', 'multipify-seo-boost'),'content_page_noindex'=>__('Pages — Noindex by default (careful)', 'multipify-seo-boost'),'content_product_templates'=>__('WooCommerce products — Use automatic SEO templates', 'multipify-seo-boost'),'content_product_description'=>__('WooCommerce products — Output the Multipify meta description', 'multipify-seo-boost'),'content_product_noindex'=>__('WooCommerce products — Noindex by default (careful)', 'multipify-seo-boost'),'content_term_templates'=>__('Categories and taxonomies — Use automatic SEO templates', 'multipify-seo-boost'),'content_term_description'=>__('Categories and taxonomies — Output the Multipify meta description', 'multipify-seo-boost'),'content_term_noindex'=>__('Categories and taxonomies — Noindex by default (careful)', 'multipify-seo-boost')], 'schema'=>[__('Advanced Schema.org', 'multipify-seo-boost'),'schema_organization'=>__('Business / person identity', 'multipify-seo-boost'),'schema_website'=>__('Website identity', 'multipify-seo-boost'),'schema_search'=>__('Internal search action', 'multipify-seo-boost'),'schema_webpage'=>__('Individual pages', 'multipify-seo-boost'),'schema_content'=>__('Posts and other content', 'multipify-seo-boost'),'schema_breadcrumb'=>__('Breadcrumbs', 'multipify-seo-boost'),'schema_taxonomy'=>__('Category and taxonomy archives', 'multipify-seo-boost'),'schema_author'=>__('Author profiles', 'multipify-seo-boost')], 'webmaster'=>['Webmaster','gsc'=>__('Google verification', 'multipify-seo-boost'),'bing'=>__('Bing verification', 'multipify-seo-boost'),'pinterest'=>__('Pinterest verification', 'multipify-seo-boost'),'clarity'=>'Microsoft Clarity ID','indexnow'=>__('IndexNow key', 'multipify-seo-boost'),'pagespeed_key'=>__('PageSpeed API key', 'multipify-seo-boost'),'gsc_client_id'=>'Google OAuth Client ID','gsc_client_secret'=>'Google OAuth Client Secret','gsc_property'=>__('Search Console property', 'multipify-seo-boost')], 'social'=>[__('Social networks', 'multipify-seo-boost'),'social_enabled'=>__('Enable Multipify social tags', 'multipify-seo-boost'),'social_open_graph'=>__('Enable Open Graph', 'multipify-seo-boost'),'social_twitter'=>__('Enable X / Twitter cards', 'multipify-seo-boost'),'social_product'=>__('Apply to products', 'multipify-seo-boost'),'social_page'=>__('Apply to pages', 'multipify-seo-boost'),'social_post'=>__('Apply to posts', 'multipify-seo-boost'),'social_term'=>__('Apply to categories', 'multipify-seo-boost'),'facebook'=>'Facebook','x'=>'X / Twitter','linkedin'=>'LinkedIn','tiktok'=>'TikTok','social_default_image'=>__('Default sharing image (HTTPS URL)', 'multipify-seo-boost'),'social_twitter_card'=>__('Default X / Twitter card type', 'multipify-seo-boost')], 'redirects'=>[__('Redirects & 404', 'multipify-seo-boost'),'redirects_enabled'=>__('Enable Multipify redirects', 'multipify-seo-boost'),'log404_enabled'=>__('Log 404 errors', 'multipify-seo-boost')], 'crawl'=>array_merge([__('Crawling & AI', 'multipify-seo-boost'),'llms_enabled'=>__('Publish /llms.txt for AI engines', 'multipify-seo-boost')],array_map(function($o){return $o[0];},MPSEO_V802_Cleanup::options())), 'advanced'=>[__('Advanced', 'multipify-seo-boost'),'robots_extra'=>__('Additional robots.txt rules', 'multipify-seo-boost'),'rss_before'=>__('Text before RSS', 'multipify-seo-boost'),'rss_after'=>__('Text after RSS', 'multipify-seo-boost'),'delete_data_on_uninstall'=>__('Delete data on uninstall', 'multipify-seo-boost')] ]; $section_help=[ 'general'=>[__('Site identity and SEO titles', 'multipify-seo-boost'),__('Home page title and description, business identity and the automatic end of your SEO titles: the basics Google shows in its results.', 'multipify-seo-boost')], 'content'=>[__('Control by content type', 'multipify-seo-boost'),__('Choose the automatic templates, descriptions and noindex directives for each family. Custom titles and descriptions take precedence over templates. A type’s global noindex applies to all its content and can remove it from search engines.', 'multipify-seo-boost')], 'schema'=>[__('Structured data types', 'multipify-seo-boost'),__('Choose exactly which JSON-LD nodes are published. Schema data output by WooCommerce stays independent. Disable the main graph in General to turn everything off.', 'multipify-seo-boost')], 'webmaster'=>[__('Search engine tools', 'multipify-seo-boost'),__('Centralize ownership verifications and search engine connection keys.', 'multipify-seo-boost')], 'social'=>[__('Official profiles', 'multipify-seo-boost'),__('Enter the public addresses of your social profiles to strengthen the consistency of your identity.', 'multipify-seo-boost')], 'crawl'=>[__('Crawling, performance and AI engines', 'multipify-seo-boost'),__('llms.txt presents your indexable content to AI assistants (ChatGPT, Perplexity, Claude…). Cleanup removes useless code from each page: fewer bytes, fewer junk URLs to crawl. Every option is reversible.', 'multipify-seo-boost')], 'redirects'=>[__('Redirects and 404 tracking', 'multipify-seo-boost'),__('Enable redirects and the not-found URL log independently. Existing rules are kept when you disable a module.', 'multipify-seo-boost')], 'advanced'=>[__('Advanced technical settings', 'multipify-seo-boost'), __('robots.txt rules and RSS feed protection. These options change how search engines and feed readers see your site: only modify what you need.', 'multipify-seo-boost') ] ]; if(class_exists('MPSEO_V52_Options')){$groups=MPSEO_V52_Options::extend_groups($groups);$section_help=MPSEO_V52_Options::extend_help($section_help);} // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only admin view/filter parameters, sanitized and allowlisted; no state change. $active=isset($_GET['section'])&&is_string($_GET['section'])?sanitize_key(wp_unslash($_GET['section'])):'general';if(!isset($groups[$active]))$active='general'; settings_errors('mpseo_group'); // A compact, capability-aware settings hub. Links lead to existing screens; no duplicated forms. $quick_links=[ [__('Sitemaps & indexing', 'multipify-seo-boost'),__('Choose WordPress or Multipify, manage exclusions and robots.txt.', 'multipify-seo-boost'),'mpseo-indexing','dashicons-networking'], [__('Automations', 'multipify-seo-boost'),__('Manage automatic redirects, IndexNow and scheduled checks.', 'multipify-seo-boost'),'mpseo-automations','dashicons-controls-repeat'], [__('Social networks', 'multipify-seo-boost'),__('Choose Open Graph, X cards and content types.', 'multipify-seo-boost'),'mpseo-settings§ion=social','dashicons-share'], [__('Redirects & 404', 'multipify-seo-boost'),__('Enable redirects and the error log separately.', 'multipify-seo-boost'),'mpseo-settings§ion=redirects','dashicons-randomize'], ['Schema.org',__('Enable the graph and configure structured data.', 'multipify-seo-boost'),'mpseo-settings§ion=schema','dashicons-editor-code'], [__('Diagnostics', 'multipify-seo-boost'),__('Check the configuration and detect issues.', 'multipify-seo-boost'),'mpseo-diagnostics','dashicons-heart'] ]; echo ('
' . esc_html__('CONFIGURATION CENTER', 'multipify-seo-boost') . '

' . esc_html__('Multipify SEO Boost settings', 'multipify-seo-boost') . '

' . esc_html__('Customize your SEO, integrations and advanced options. Each tab is saved independently.', 'multipify-seo-boost') . '

' . esc_html__('QUICK ACCESS', 'multipify-seo-boost') . '

' . esc_html__('Configure features', 'multipify-seo-boost') . '

' . esc_html__('Find the essential options without browsing every menu.', 'multipify-seo-boost') . '

'); foreach($quick_links as $link){ $slug=explode('&',$link[2])[0]; $cap=class_exists('MPSEO_V64_Design')?MPSEO_V64_Design::capability_for($slug):MPSEO_Access::CAP_SETTINGS; if(!current_user_can($cap))continue; echo ''.esc_html($link[0]).''.esc_html($link[1]).''; } echo '
';settings_fields('mpseo_group'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- section_heading() escapes every value. echo ('
').self::section_heading($active,$groups[$active][0],$section_help[$active]??[$groups[$active][0],''],count($groups[$active])-1).''; if($active==='content'){ echo (''); echo (''); } if(isset($section_help[$active])){ echo '
'.esc_html($section_help[$active][0]).'

'.esc_html($section_help[$active][1]).'

'; } $fields=$groups[$active];unset($fields[0]);self::fields($fields);echo '
';do_action('mpseo_settings_section_after',$active);echo '
';submit_button(__('Save settings', 'multipify-seo-boost'));echo ('' . esc_html__('Other sections will not be changed.', 'multipify-seo-boost') . '
'); if($active==='content'){ MPSEO_Inline_Assets::script('(function(){"use strict";var form=document.querySelector(".mpseo-settings-main form");if(!form)return;var keys=["content_post_noindex","content_page_noindex","content_product_noindex","content_term_noindex"];var warning=document.getElementById("mpseo-noindex-live-warning");var changed=function(){var active=keys.some(function(key){var el=form.querySelector("input[type=checkbox][name=\"'.esc_js(MPSEO_Core::SETTINGS).'["+key+"]\"]");return el&&el.checked;});if(warning)warning.style.display=active?"block":"none";};keys.forEach(function(key){var el=form.querySelector("input[type=checkbox][name=\"'.esc_js(MPSEO_Core::SETTINGS).'["+key+"]\"]");if(el)el.addEventListener("change",changed);});changed();form.addEventListener("submit",function(e){var newlyEnabled=keys.filter(function(key){var el=form.querySelector("input[type=checkbox][name=\"'.esc_js(MPSEO_Core::SETTINGS).('["+key+"]\\"]");return el&&el.checked&&el.defaultChecked===false;});if(newlyEnabled.length&&!window.confirm("' . esc_js(__('Warning: you are enabling noindex for one or more content families. This can remove many URLs from search results. Continue?', 'multipify-seo-boost')) . '"))e.preventDefault();});})();'),[]); } } static function local(){ echo ('
' . esc_html__('LOCAL VISIBILITY', 'multipify-seo-boost') . '

' . esc_html__('Local SEO', 'multipify-seo-boost') . '

' . esc_html__('Centralize your business information for structured data and your local presence.', 'multipify-seo-boost') . '

' . esc_html__('Your business listing', 'multipify-seo-boost') . '

' . esc_html__('Only enter public, verifiable information. The contact details feed the local Schema.', 'multipify-seo-boost') . '

' . esc_html__('Check your local identity', 'multipify-seo-boost') . '

' . esc_html__('Use the same name, address and phone number as on your site and your business listing. Leave unknown details empty.', 'multipify-seo-boost') . '

'; settings_fields('mpseo_group');echo '';self::fields(['company_name'=>__('Business name', 'multipify-seo-boost'),'company_type'=>__('Business type', 'multipify-seo-boost'),'phone'=>__('Phone', 'multipify-seo-boost'),'address'=>__('Address', 'multipify-seo-boost'),'city'=>__('City', 'multipify-seo-boost'),'postal'=>__('Postal code', 'multipify-seo-boost'),'country'=>__('Country', 'multipify-seo-boost'),'lat'=>__('Latitude', 'multipify-seo-boost'),'lng'=>__('Longitude', 'multipify-seo-boost'),'hours'=>__('Opening hours', 'multipify-seo-boost')]);echo '
';submit_button(__('Save the local listing', 'multipify-seo-boost'));echo '
'; } static function diagnostics(){self::seo_conflicts_notice();MPSEO_Diagnostics::page();} static function security(){MPSEO_V52_Security::page();} static function setup(){MPSEO_Setup_Wizard::page();} static function health(){MPSEO_Health::page();} static function statistics(){MPSEO_Statistics::page();} static function content_decay(){MPSEO_V37_Content_Decay::page();} static function performance(){MPSEO_Performance_Insights::page();} static function audit(){MPSEO_Site_Audit::page();} static function revisions(){MPSEO_Revisions::page();} static function connections(){MPSEO_Connections::page();} static function redirects(){MPSEO_Redirects::page();} static function automations(){MPSEO_V39_Automations::page();} static function links(){MPSEO_Link_Assistant::page();} static function pagespeed(){MPSEO_PageSpeed::page();} static function bulk(){MPSEO_Bulk_Editor::page();} static function indexing(){MPSEO_Index_Controls::page();} static function tools(){MPSEO_SEO_Tools::page();} static function import(){MPSEO_Importers::page();} static function templates(){MPSEO_Templates::page();} static function access(){MPSEO_Access::page();} }