class-admin-init.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. <?php
  2. /**
  3. * WPSEO plugin file.
  4. *
  5. * @package WPSEO\Admin
  6. */
  7. /**
  8. * Performs the load on admin side.
  9. */
  10. class WPSEO_Admin_Init {
  11. /**
  12. * Holds the global `$pagenow` variable's value.
  13. *
  14. * @var string
  15. */
  16. private $pagenow;
  17. /**
  18. * Holds the asset manager.
  19. *
  20. * @var WPSEO_Admin_Asset_Manager
  21. */
  22. private $asset_manager;
  23. /**
  24. * Class constructor
  25. */
  26. public function __construct() {
  27. $GLOBALS['wpseo_admin'] = new WPSEO_Admin();
  28. $this->pagenow = $GLOBALS['pagenow'];
  29. $this->asset_manager = new WPSEO_Admin_Asset_Manager();
  30. add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_dismissible' ) );
  31. add_action( 'admin_init', array( $this, 'tagline_notice' ), 15 );
  32. add_action( 'admin_init', array( $this, 'blog_public_notice' ), 15 );
  33. add_action( 'admin_init', array( $this, 'permalink_notice' ), 15 );
  34. add_action( 'admin_init', array( $this, 'page_comments_notice' ), 15 );
  35. add_action( 'admin_init', array( $this, 'ga_compatibility_notice' ), 15 );
  36. add_action( 'admin_init', array( $this, 'yoast_plugin_compatibility_notification' ), 15 );
  37. add_action( 'admin_init', array( $this, 'yoast_plugin_suggestions_notification' ), 15 );
  38. add_action( 'admin_init', array( $this, 'recalculate_notice' ), 15 );
  39. add_action( 'admin_init', array( $this, 'unsupported_php_notice' ), 15 );
  40. add_action( 'admin_init', array( $this->asset_manager, 'register_assets' ) );
  41. add_action( 'admin_init', array( $this, 'show_hook_deprecation_warnings' ) );
  42. add_action( 'admin_init', array( 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ) );
  43. add_action( 'admin_init', array( $this, 'handle_notifications' ), 15 );
  44. $listeners = array();
  45. $listeners[] = new WPSEO_Post_Type_Archive_Notification_Handler();
  46. /** @var WPSEO_Listener $listener */
  47. foreach ( $listeners as $listener ) {
  48. $listener->listen();
  49. }
  50. $this->load_meta_boxes();
  51. $this->load_taxonomy_class();
  52. $this->load_admin_page_class();
  53. $this->load_admin_user_class();
  54. $this->load_xml_sitemaps_admin();
  55. $this->load_plugin_suggestions();
  56. }
  57. /**
  58. * Handles the notifiers for the dashboard page.
  59. *
  60. * @return void
  61. */
  62. public function handle_notifications() {
  63. /**
  64. * @var WPSEO_Notification_Handler[] $handlers
  65. */
  66. $handlers = array();
  67. $handlers[] = new WPSEO_Post_Type_Archive_Notification_Handler();
  68. $notification_center = Yoast_Notification_Center::get();
  69. foreach ( $handlers as $handler ) {
  70. $handler->handle( $notification_center );
  71. }
  72. }
  73. /**
  74. * Enqueue our styling for dismissible yoast notifications.
  75. */
  76. public function enqueue_dismissible() {
  77. $this->asset_manager->enqueue_style( 'dismissible' );
  78. }
  79. /**
  80. * Helper to verify if the current user has already seen the about page for the current version
  81. *
  82. * @return bool
  83. */
  84. private function seen_about() {
  85. $seen_about_version = substr( get_user_meta( get_current_user_id(), 'wpseo_seen_about_version', true ), 0, 3 );
  86. $last_minor_version = substr( WPSEO_VERSION, 0, 3 );
  87. return version_compare( $seen_about_version, $last_minor_version, '>=' );
  88. }
  89. /**
  90. * Notify about the default tagline if the user hasn't changed it
  91. */
  92. public function tagline_notice() {
  93. $current_url = ( is_ssl() ? 'https://' : 'http://' );
  94. $current_url .= sanitize_text_field( $_SERVER['SERVER_NAME'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
  95. $customize_url = add_query_arg( array(
  96. 'autofocus[control]' => 'blogdescription',
  97. 'url' => urlencode( $current_url ),
  98. ), wp_customize_url() );
  99. $info_message = sprintf(
  100. /* translators: 1: link open tag; 2: link close tag. */
  101. __( 'You still have the default WordPress tagline, even an empty one is probably better. %1$sYou can fix this in the customizer%2$s.', 'wordpress-seo' ),
  102. '<a href="' . esc_attr( $customize_url ) . '">',
  103. '</a>'
  104. );
  105. $notification_options = array(
  106. 'type' => Yoast_Notification::ERROR,
  107. 'id' => 'wpseo-dismiss-tagline-notice',
  108. 'capabilities' => 'wpseo_manage_options',
  109. );
  110. $tagline_notification = new Yoast_Notification( $info_message, $notification_options );
  111. $notification_center = Yoast_Notification_Center::get();
  112. if ( $this->has_default_tagline() ) {
  113. $notification_center->add_notification( $tagline_notification );
  114. }
  115. else {
  116. $notification_center->remove_notification( $tagline_notification );
  117. }
  118. }
  119. /**
  120. * Add an alert if the blog is not publicly visible
  121. */
  122. public function blog_public_notice() {
  123. $info_message = '<strong>' . __( 'Huge SEO Issue: You\'re blocking access to robots.', 'wordpress-seo' ) . '</strong> ';
  124. $info_message .= sprintf(
  125. /* translators: %1$s resolves to the opening tag of the link to the reading settings, %1$s resolves to the closing tag for the link */
  126. __( 'You must %1$sgo to your Reading Settings%2$s and uncheck the box for Search Engine Visibility.', 'wordpress-seo' ),
  127. '<a href="' . esc_url( admin_url( 'options-reading.php' ) ) . '">',
  128. '</a>'
  129. );
  130. $notification_options = array(
  131. 'type' => Yoast_Notification::ERROR,
  132. 'id' => 'wpseo-dismiss-blog-public-notice',
  133. 'priority' => 1.0,
  134. 'capabilities' => 'wpseo_manage_options',
  135. );
  136. $notification = new Yoast_Notification( $info_message, $notification_options );
  137. $notification_center = Yoast_Notification_Center::get();
  138. if ( ! $this->is_blog_public() ) {
  139. $notification_center->add_notification( $notification );
  140. }
  141. else {
  142. $notification_center->remove_notification( $notification );
  143. }
  144. }
  145. /**
  146. * Display notice to disable comment pagination
  147. */
  148. public function page_comments_notice() {
  149. $info_message = __( 'Paging comments is enabled, this is not needed in 999 out of 1000 cases, we recommend to disable it.', 'wordpress-seo' );
  150. $info_message .= '<br/>';
  151. $info_message .= sprintf(
  152. /* translators: %1$s resolves to the opening tag of the link to the comment setting page, %2$s resolves to the closing tag of the link */
  153. __( 'To fix this uncheck the box in front of the "Break comments into pages..." on the %1$sComment settings page%2$s.', 'wordpress-seo' ),
  154. '<a href="' . esc_url( admin_url( 'options-discussion.php' ) ) . '">',
  155. '</a>'
  156. );
  157. $notification_options = array(
  158. 'type' => Yoast_Notification::WARNING,
  159. 'id' => 'wpseo-dismiss-page_comments-notice',
  160. 'capabilities' => 'wpseo_manage_options',
  161. );
  162. $tagline_notification = new Yoast_Notification( $info_message, $notification_options );
  163. $notification_center = Yoast_Notification_Center::get();
  164. if ( $this->has_page_comments() ) {
  165. $notification_center->add_notification( $tagline_notification );
  166. }
  167. else {
  168. $notification_center->remove_notification( $tagline_notification );
  169. }
  170. }
  171. /**
  172. * Returns whether or not the site has the default tagline
  173. *
  174. * @return bool
  175. */
  176. public function has_default_tagline() {
  177. $blog_description = get_bloginfo( 'description' );
  178. $default_blog_description = 'Just another WordPress site';
  179. // We are checking against the WordPress internal translation.
  180. // @codingStandardsIgnoreLine
  181. $translated_blog_description = __( 'Just another WordPress site' );
  182. return $translated_blog_description === $blog_description || $default_blog_description === $blog_description;
  183. }
  184. /**
  185. * Show alert when the permalink doesn't contain %postname%
  186. */
  187. public function permalink_notice() {
  188. $info_message = __( 'You do not have your postname in the URL of your posts and pages, it is highly recommended that you do. Consider setting your permalink structure to <strong>/%postname%/</strong>.', 'wordpress-seo' );
  189. $info_message .= '<br/>';
  190. $info_message .= sprintf(
  191. /* translators: %1$s resolves to the starting tag of the link to the permalink settings page, %2$s resolves to the closing tag of the link */
  192. __( 'You can fix this on the %1$sPermalink settings page%2$s.', 'wordpress-seo' ),
  193. '<a href="' . admin_url( 'options-permalink.php' ) . '">',
  194. '</a>'
  195. );
  196. $notification_options = array(
  197. 'type' => Yoast_Notification::WARNING,
  198. 'id' => 'wpseo-dismiss-permalink-notice',
  199. 'capabilities' => 'wpseo_manage_options',
  200. 'priority' => 0.8,
  201. );
  202. $notification = new Yoast_Notification( $info_message, $notification_options );
  203. $notification_center = Yoast_Notification_Center::get();
  204. if ( ! $this->has_postname_in_permalink() ) {
  205. $notification_center->add_notification( $notification );
  206. }
  207. else {
  208. $notification_center->remove_notification( $notification );
  209. }
  210. }
  211. /**
  212. * Are page comments enabled
  213. *
  214. * @return bool
  215. */
  216. public function has_page_comments() {
  217. return '1' === get_option( 'page_comments' );
  218. }
  219. /**
  220. * Shows a notice to the user if they have Google Analytics for WordPress 5.4.3 installed because it causes an error
  221. * on the google search console page.
  222. */
  223. public function ga_compatibility_notice() {
  224. $notification = $this->get_compatibility_notification();
  225. $notification_center = Yoast_Notification_Center::get();
  226. if ( defined( 'GAWP_VERSION' ) && '5.4.3' === GAWP_VERSION ) {
  227. $notification_center->add_notification( $notification );
  228. }
  229. else {
  230. $notification_center->remove_notification( $notification );
  231. }
  232. }
  233. /**
  234. * Build compatibility problem notification
  235. *
  236. * @return Yoast_Notification
  237. */
  238. private function get_compatibility_notification() {
  239. $info_message = sprintf(
  240. /* translators: %1$s expands to Yoast SEO, %2$s expands to 5.4.3, %3$s expands to Google Analytics by Yoast */
  241. __( '%1$s detected you are using version %2$s of %3$s, please update to the latest version to prevent compatibility issues.', 'wordpress-seo' ),
  242. 'Yoast SEO',
  243. '5.4.3',
  244. 'Google Analytics by Yoast'
  245. );
  246. return new Yoast_Notification(
  247. $info_message,
  248. array(
  249. 'id' => 'gawp-compatibility-notice',
  250. 'type' => Yoast_Notification::ERROR,
  251. )
  252. );
  253. }
  254. /**
  255. * Determines whether a suggested plugins notification needs to be displayed.
  256. *
  257. * @return void
  258. */
  259. public function yoast_plugin_suggestions_notification() {
  260. $checker = new WPSEO_Plugin_Availability();
  261. $notification_center = Yoast_Notification_Center::get();
  262. // Get all Yoast plugins that have dependencies.
  263. $plugins = $checker->get_plugins_with_dependencies();
  264. foreach ( $plugins as $plugin_name => $plugin ) {
  265. $dependency_names = $checker->get_dependency_names( $plugin );
  266. $notification = $this->get_yoast_seo_suggested_plugins_notification( $plugin_name, $plugin, $dependency_names[0] );
  267. if ( $checker->dependencies_are_satisfied( $plugin ) && ! $checker->is_installed( $plugin ) ) {
  268. $notification_center->add_notification( $notification );
  269. continue;
  270. }
  271. $notification_center->remove_notification( $notification );
  272. }
  273. }
  274. /**
  275. * Build Yoast SEO suggested plugins notification.
  276. *
  277. * @param string $name The plugin name to use for the unique ID.
  278. * @param array $plugin The plugin to retrieve the data from.
  279. * @param string $dependency_name The name of the dependency.
  280. *
  281. * @return Yoast_Notification The notification containing the suggested plugin.
  282. */
  283. private function get_yoast_seo_suggested_plugins_notification( $name, $plugin, $dependency_name ) {
  284. $info_message = sprintf(
  285. /* translators: %1$s expands to Yoast SEO, %2$s expands to the plugin version, %3$s expands to the plugin name */
  286. __( '%1$s and %2$s can work together a lot better by adding a helper plugin. Please install %3$s to make your life better.', 'wordpress-seo' ),
  287. 'Yoast SEO',
  288. $dependency_name,
  289. sprintf( '<a href="%s">%s</a>', $plugin['url'], $plugin['title'] )
  290. );
  291. return new Yoast_Notification(
  292. $info_message,
  293. array(
  294. 'id' => 'wpseo-suggested-plugin-' . $name,
  295. 'type' => Yoast_Notification::WARNING,
  296. )
  297. );
  298. }
  299. /**
  300. * Add an alert if outdated versions of Yoast SEO plugins are running.
  301. */
  302. public function yoast_plugin_compatibility_notification() {
  303. $compatibility_checker = new WPSEO_Plugin_Compatibility( WPSEO_VERSION );
  304. $plugins = $compatibility_checker->get_installed_plugins_compatibility();
  305. $notification_center = Yoast_Notification_Center::get();
  306. foreach ( $plugins as $name => $plugin ) {
  307. $type = ( $plugin['active'] ) ? Yoast_Notification::ERROR : Yoast_Notification::WARNING;
  308. $notification = $this->get_yoast_seo_compatibility_notification( $name, $plugin, $type );
  309. if ( $plugin['compatible'] === false ) {
  310. $notification_center->add_notification( $notification );
  311. continue;
  312. }
  313. $notification_center->remove_notification( $notification );
  314. }
  315. }
  316. /**
  317. * Build Yoast SEO compatibility problem notification
  318. *
  319. * @param string $name The plugin name to use for the unique ID.
  320. * @param array $plugin The plugin to retrieve the data from.
  321. * @param string $level The severity level to use for the notification.
  322. *
  323. * @return Yoast_Notification
  324. */
  325. private function get_yoast_seo_compatibility_notification( $name, $plugin, $level = Yoast_Notification::WARNING ) {
  326. $info_message = sprintf(
  327. /* translators: %1$s expands to Yoast SEO, %2$s expands to the plugin version, %3$s expands to the plugin name */
  328. __( '%1$s detected you are using version %2$s of %3$s, please update to the latest version to prevent compatibility issues.', 'wordpress-seo' ),
  329. 'Yoast SEO',
  330. $plugin['version'],
  331. $plugin['title']
  332. );
  333. return new Yoast_Notification(
  334. $info_message,
  335. array(
  336. 'id' => 'wpseo-outdated-yoast-seo-plugin-' . $name,
  337. 'type' => $level,
  338. )
  339. );
  340. }
  341. /**
  342. * Shows the notice for recalculating the post. the Notice will only be shown if the user hasn't dismissed it before.
  343. */
  344. public function recalculate_notice() {
  345. // Just a return, because we want to temporary disable this notice (#3998 and #4532).
  346. return;
  347. if ( filter_input( INPUT_GET, 'recalculate' ) === '1' ) {
  348. update_option( 'wpseo_dismiss_recalculate', '1' );
  349. return;
  350. }
  351. if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
  352. return;
  353. }
  354. if ( $this->is_site_notice_dismissed( 'wpseo_dismiss_recalculate' ) ) {
  355. return;
  356. }
  357. Yoast_Notification_Center::get()->add_notification(
  358. new Yoast_Notification(
  359. sprintf(
  360. /* translators: 1: is a link to 'admin_url / admin.php?page=wpseo_tools&recalculate=1' 2: closing link tag */
  361. __( 'We\'ve updated our SEO score algorithm. %1$sRecalculate the SEO scores%2$s for all posts and pages.', 'wordpress-seo' ),
  362. '<a href="' . admin_url( 'admin.php?page=wpseo_tools&recalculate=1' ) . '">',
  363. '</a>'
  364. ),
  365. array(
  366. 'type' => 'updated yoast-dismissible',
  367. 'id' => 'wpseo-dismiss-recalculate',
  368. 'nonce' => wp_create_nonce( 'wpseo-dismiss-recalculate' ),
  369. )
  370. )
  371. );
  372. }
  373. /**
  374. * Creates an unsupported PHP version notification in the notification center.
  375. *
  376. * @return void
  377. */
  378. public function unsupported_php_notice() {
  379. $notification_center = Yoast_Notification_Center::get();
  380. $notification_center->remove_notification_by_id( 'wpseo-dismiss-unsupported-php' );
  381. }
  382. /**
  383. * Check if the user has dismissed the given notice (by $notice_name)
  384. *
  385. * @param string $notice_name The name of the notice that might be dismissed.
  386. *
  387. * @return bool
  388. */
  389. private function is_site_notice_dismissed( $notice_name ) {
  390. return '1' === get_option( $notice_name, true );
  391. }
  392. /**
  393. * Helper to verify if the user is currently visiting one of our admin pages.
  394. *
  395. * @return bool
  396. */
  397. private function on_wpseo_admin_page() {
  398. return 'admin.php' === $this->pagenow && strpos( filter_input( INPUT_GET, 'page' ), 'wpseo' ) === 0;
  399. }
  400. /**
  401. * Determine whether we should load the meta box class and if so, load it.
  402. */
  403. private function load_meta_boxes() {
  404. $is_editor = WPSEO_Metabox::is_post_overview( $this->pagenow ) || WPSEO_Metabox::is_post_edit( $this->pagenow );
  405. $is_inline_save = filter_input( INPUT_POST, 'action' ) === 'inline-save';
  406. /**
  407. * Filter: 'wpseo_always_register_metaboxes_on_admin' - Allow developers to change whether
  408. * the WPSEO metaboxes are only registered on the typical pages (lean loading) or always
  409. * registered when in admin.
  410. *
  411. * @api bool Whether to always register the metaboxes or not. Defaults to false.
  412. */
  413. if ( $is_editor || $is_inline_save || apply_filters( 'wpseo_always_register_metaboxes_on_admin', false )
  414. ) {
  415. $GLOBALS['wpseo_metabox'] = new WPSEO_Metabox();
  416. $GLOBALS['wpseo_meta_columns'] = new WPSEO_Meta_Columns();
  417. }
  418. }
  419. /**
  420. * Determine if we should load our taxonomy edit class and if so, load it.
  421. */
  422. private function load_taxonomy_class() {
  423. if (
  424. WPSEO_Taxonomy::is_term_edit( $this->pagenow )
  425. || WPSEO_Taxonomy::is_term_overview( $this->pagenow )
  426. ) {
  427. new WPSEO_Taxonomy();
  428. }
  429. }
  430. /**
  431. * Determine if we should load our admin pages class and if so, load it.
  432. *
  433. * Loads admin page class for all admin pages starting with `wpseo_`.
  434. */
  435. private function load_admin_user_class() {
  436. if ( in_array( $this->pagenow, array( 'user-edit.php', 'profile.php' ), true )
  437. && current_user_can( 'edit_users' )
  438. ) {
  439. new WPSEO_Admin_User_Profile();
  440. }
  441. }
  442. /**
  443. * Determine if we should load our admin pages class and if so, load it.
  444. *
  445. * Loads admin page class for all admin pages starting with `wpseo_`.
  446. */
  447. private function load_admin_page_class() {
  448. if ( $this->on_wpseo_admin_page() ) {
  449. // For backwards compatabilty, this still needs a global, for now...
  450. $GLOBALS['wpseo_admin_pages'] = new WPSEO_Admin_Pages();
  451. // Only register the yoast i18n when the page is a Yoast SEO page.
  452. if ( WPSEO_Utils::is_yoast_seo_free_page( filter_input( INPUT_GET, 'page' ) ) ) {
  453. $this->register_i18n_promo_class();
  454. $this->register_premium_upsell_admin_block();
  455. }
  456. }
  457. }
  458. /**
  459. * Loads the plugin suggestions.
  460. */
  461. private function load_plugin_suggestions() {
  462. $suggestions = new WPSEO_Suggested_Plugins( new WPSEO_Plugin_Availability(), Yoast_Notification_Center::get() );
  463. $suggestions->register_hooks();
  464. }
  465. /**
  466. * Registers the Premium Upsell Admin Block.
  467. *
  468. * @return void
  469. */
  470. private function register_premium_upsell_admin_block() {
  471. if ( ! WPSEO_Utils::is_yoast_seo_premium() ) {
  472. $upsell_block = new WPSEO_Premium_Upsell_Admin_Block( 'wpseo_admin_promo_footer' );
  473. $upsell_block->register_hooks();
  474. }
  475. }
  476. /**
  477. * Registers the promotion class for our GlotPress instance, then creates a notification with the i18n promo.
  478. *
  479. * @link https://github.com/Yoast/i18n-module
  480. */
  481. private function register_i18n_promo_class() {
  482. // BC, because an older version of the i18n-module didn't have this class.
  483. $i18n_module = new Yoast_I18n_WordPressOrg_v3(
  484. array(
  485. 'textdomain' => 'wordpress-seo',
  486. 'plugin_name' => 'Yoast SEO',
  487. 'hook' => 'wpseo_admin_promo_footer',
  488. ), false
  489. );
  490. $message = $i18n_module->get_promo_message();
  491. if ( $message !== '' ) {
  492. $message .= $i18n_module->get_dismiss_i18n_message_button();
  493. }
  494. $notification_center = Yoast_Notification_Center::get();
  495. $notification = new Yoast_Notification(
  496. $message,
  497. array(
  498. 'type' => Yoast_Notification::WARNING,
  499. 'id' => 'i18nModuleTranslationAssistance',
  500. )
  501. );
  502. if ( $message ) {
  503. $notification_center->add_notification( $notification );
  504. return;
  505. }
  506. $notification_center->remove_notification( $notification );
  507. }
  508. /**
  509. * See if we should start our XML Sitemaps Admin class
  510. */
  511. private function load_xml_sitemaps_admin() {
  512. if ( WPSEO_Options::get( 'enable_xml_sitemap', false ) ) {
  513. new WPSEO_Sitemaps_Admin();
  514. }
  515. }
  516. /**
  517. * Check if the site is set to be publicly visible
  518. *
  519. * @return bool
  520. */
  521. private function is_blog_public() {
  522. return '1' === (string) get_option( 'blog_public' );
  523. }
  524. /**
  525. * Shows deprecation warnings to the user if a plugin has registered a filter we have deprecated.
  526. */
  527. public function show_hook_deprecation_warnings() {
  528. global $wp_filter;
  529. if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
  530. return false;
  531. }
  532. // WordPress hooks that have been deprecated since a Yoast SEO version.
  533. $deprecated_filters = array(
  534. 'wpseo_metadesc_length' => array(
  535. 'version' => '3.0',
  536. 'alternative' => 'javascript',
  537. ),
  538. 'wpseo_metadesc_length_reason' => array(
  539. 'version' => '3.0',
  540. 'alternative' => 'javascript',
  541. ),
  542. 'wpseo_body_length_score' => array(
  543. 'version' => '3.0',
  544. 'alternative' => 'javascript',
  545. ),
  546. 'wpseo_linkdex_results' => array(
  547. 'version' => '3.0',
  548. 'alternative' => 'javascript',
  549. ),
  550. 'wpseo_snippet' => array(
  551. 'version' => '3.0',
  552. 'alternative' => 'javascript',
  553. ),
  554. 'wp_seo_get_bc_title' => array(
  555. 'version' => '5.8',
  556. 'alternative' => 'wpseo_breadcrumb_single_link_info',
  557. ),
  558. 'wpseo_metakey' => array(
  559. 'version' => '6.3',
  560. 'alternative' => null,
  561. ),
  562. 'wpseo_metakeywords' => array(
  563. 'version' => '6.3',
  564. 'alternative' => null,
  565. ),
  566. 'wpseo_stopwords' => array(
  567. 'version' => '7.0',
  568. 'alternative' => null,
  569. ),
  570. 'wpseo_redirect_orphan_attachment' => array(
  571. 'version' => '7.0',
  572. 'alternative' => null,
  573. ),
  574. );
  575. // Determine which filters have been registered.
  576. $deprecated_notices = array_intersect(
  577. array_keys( $deprecated_filters ),
  578. array_keys( $wp_filter )
  579. );
  580. // Show notice for each deprecated filter or action that has been registered.
  581. foreach ( $deprecated_notices as $deprecated_filter ) {
  582. $deprecation_info = $deprecated_filters[ $deprecated_filter ];
  583. _deprecated_hook(
  584. $deprecated_filter,
  585. 'WPSEO ' . $deprecation_info['version'],
  586. $deprecation_info['alternative']
  587. );
  588. }
  589. }
  590. /**
  591. * Check if there is a dismiss notice action.
  592. *
  593. * @param string $notice_name The name of the notice to dismiss.
  594. *
  595. * @return bool
  596. */
  597. private function dismiss_notice( $notice_name ) {
  598. return filter_input( INPUT_GET, $notice_name ) === '1' && wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ), $notice_name );
  599. }
  600. /**
  601. * Check if the permalink uses %postname%
  602. *
  603. * @return bool
  604. */
  605. private function has_postname_in_permalink() {
  606. return ( false !== strpos( get_option( 'permalink_structure' ), '%postname%' ) );
  607. }
  608. }