PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
← All changes | admin/class-admin-init.php +86 -205 18.028.5 View file →
@@ -35,8 +35,9 @@
35 35 $this->asset_manager = new WPSEO_Admin_Asset_Manager();
36 36
37 37 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_dismissible' ] );
38 38 add_action( 'admin_init', [ $this, 'unsupported_php_notice' ], 15 );
39 + add_action( 'admin_init', [ $this, 'remove_translations_notification' ], 15 );
39 40 add_action( 'admin_init', [ $this->asset_manager, 'register_assets' ] );
40 41 add_action( 'admin_init', [ $this, 'show_hook_deprecation_warnings' ] );
41 42 add_action( 'admin_init', [ 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ] );
42 43 add_action( 'admin_notices', [ $this, 'permalink_settings_notice' ] );
@@ -41,28 +42,8 @@
41 42 add_action( 'admin_init', [ 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ] );
42 43 add_action( 'admin_notices', [ $this, 'permalink_settings_notice' ] );
43 44 add_action( 'post_submitbox_misc_actions', [ $this, 'add_publish_box_section' ] );
44 45
45 - /*
46 - * The `admin_notices` hook fires on single site admin pages vs.
47 - * `network_admin_notices` which fires on multisite admin pages and
48 - * `user_admin_notices` which fires on multisite user admin pagss.
49 - */
50 - add_action( 'admin_notices', [ $this, 'search_engines_discouraged_notice' ] );
51 -
52 - $health_checks = [
53 - new WPSEO_Health_Check_Page_Comments(),
54 - new WPSEO_Health_Check_Ryte(),
55 - new WPSEO_Health_Check_Default_Tagline(),
56 - new WPSEO_Health_Check_Postname_Permalink(),
57 - new WPSEO_Health_Check_Curl_Version(),
58 - new WPSEO_Health_Check_Link_Table_Not_Accessible(),
59 - ];
60 -
61 - foreach ( $health_checks as $health_check ) {
62 - $health_check->register_test();
63 - }
64 -
65 46 $this->load_meta_boxes();
66 47 $this->load_taxonomy_class();
67 48 $this->load_admin_page_class();
68 49 $this->load_admin_user_class();
@@ -71,8 +52,10 @@
71 52 }
72 53
73 54 /**
74 55 * Enqueue our styling for dismissible yoast notifications.
56 + *
57 + * @return void
75 58 */
76 59 public function enqueue_dismissible() {
77 60 $this->asset_manager->enqueue_style( 'dismissible' );
78 61 }
@@ -77,8 +60,18 @@
77 60 $this->asset_manager->enqueue_style( 'dismissible' );
78 61 }
79 62
80 63 /**
64 + * Removes any notification for incomplete translations.
65 + *
66 + * @return void
67 + */
68 + public function remove_translations_notification() {
69 + $notification_center = Yoast_Notification_Center::get();
70 + $notification_center->remove_notification_by_id( 'i18nModuleTranslationAssistance' );
71 + }
72 +
73 + /**
81 74 * Creates an unsupported PHP version notification in the notification center.
82 75 *
83 76 * @return void
84 77 */
@@ -115,28 +108,59 @@
115 108 *
116 109 * @return bool
117 110 */
118 111 private function on_wpseo_admin_page() {
119 - return $this->pagenow === 'admin.php' && strpos( filter_input( INPUT_GET, 'page' ), 'wpseo' ) === 0;
112 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
113 + if ( ! isset( $_GET['page'] ) || ! is_string( $_GET['page'] ) ) {
114 + return false;
115 + }
116 +
117 + if ( $this->pagenow !== 'admin.php' ) {
118 + return false;
119 + }
120 +
121 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
122 + $current_page = sanitize_text_field( wp_unslash( $_GET['page'] ) );
123 + return strpos( $current_page, 'wpseo' ) === 0;
120 124 }
121 125
122 126 /**
123 - * Determine whether we should load the meta box class and if so, load it.
127 + * Whether we should load the meta box classes.
128 + *
129 + * @return bool true if we should load the meta box classes, false otherwise.
124 130 */
125 - private function load_meta_boxes() {
126 -
127 - $is_editor = WPSEO_Metabox::is_post_overview( $this->pagenow ) || WPSEO_Metabox::is_post_edit( $this->pagenow );
128 - $is_inline_save = filter_input( INPUT_POST, 'action' ) === 'inline-save';
129 -
131 + private function should_load_meta_boxes() {
130 132 /**
131 133 * Filter: 'wpseo_always_register_metaboxes_on_admin' - Allow developers to change whether
132 134 * the WPSEO metaboxes are only registered on the typical pages (lean loading) or always
133 135 * registered when in admin.
134 136 *
135 - * @api bool Whether to always register the metaboxes or not. Defaults to false.
137 + * @param bool $register_metaboxes Whether to always register the metaboxes or not. Defaults to false.
136 138 */
137 - if ( $is_editor || $is_inline_save || apply_filters( 'wpseo_always_register_metaboxes_on_admin', false )
138 - ) {
139 + if ( apply_filters( 'wpseo_always_register_metaboxes_on_admin', false ) ) {
140 + return true;
141 + }
142 +
143 + // If we are in a post editor.
144 + if ( WPSEO_Metabox::is_post_overview( $this->pagenow ) || WPSEO_Metabox::is_post_edit( $this->pagenow ) ) {
145 + return true;
146 + }
147 +
148 + // If we are doing an inline save.
149 + if ( check_ajax_referer( 'inlineeditnonce', '_inline_edit', false ) && isset( $_POST['action'] ) && sanitize_text_field( wp_unslash( $_POST['action'] ) ) === 'inline-save' ) {
150 + return true;
151 + }
152 +
153 + return false;
154 + }
155 +
156 + /**
157 + * Determine whether we should load the meta box class and if so, load it.
158 + *
159 + * @return void
160 + */
161 + private function load_meta_boxes() {
162 + if ( $this->should_load_meta_boxes() ) {
139 163 $GLOBALS['wpseo_metabox'] = new WPSEO_Metabox();
140 164 $GLOBALS['wpseo_meta_columns'] = new WPSEO_Meta_Columns();
141 165 }
142 166 }
@@ -142,8 +166,10 @@
142 166 }
143 167
144 168 /**
145 169 * Determine if we should load our taxonomy edit class and if so, load it.
170 + *
171 + * @return void
146 172 */
147 173 private function load_taxonomy_class() {
148 174 if (
149 175 WPSEO_Taxonomy::is_term_edit( $this->pagenow )
@@ -156,8 +182,10 @@
156 182 /**
157 183 * Determine if we should load our admin pages class and if so, load it.
158 184 *
159 185 * Loads admin page class for all admin pages starting with `wpseo_`.
186 + *
187 + * @return void
160 188 */
161 189 private function load_admin_user_class() {
162 190 if ( in_array( $this->pagenow, [ 'user-edit.php', 'profile.php' ], true )
163 191 && current_user_can( 'edit_users' )
@@ -169,8 +197,10 @@
169 197 /**
170 198 * Determine if we should load our admin pages class and if so, load it.
171 199 *
172 200 * Loads admin page class for all admin pages starting with `wpseo_`.
201 + *
202 + * @return void
173 203 */
174 204 private function load_admin_page_class() {
175 205
176 206 if ( $this->on_wpseo_admin_page() ) {
@@ -176,21 +206,27 @@
176 206 if ( $this->on_wpseo_admin_page() ) {
177 207 // For backwards compatabilty, this still needs a global, for now...
178 208 $GLOBALS['wpseo_admin_pages'] = new WPSEO_Admin_Pages();
179 209
180 - $page = filter_input( INPUT_GET, 'page' );
181 - // Only register the yoast i18n when the page is a Yoast SEO page.
182 - if ( WPSEO_Utils::is_yoast_seo_free_page( $page ) ) {
183 - $this->register_i18n_promo_class();
184 - if ( $page !== 'wpseo_titles' ) {
185 - $this->register_premium_upsell_admin_block();
186 - }
210 + $page = null;
211 +
212 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
213 + if ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) ) {
214 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
215 + $page = sanitize_text_field( wp_unslash( $_GET['page'] ) );
187 216 }
217 +
218 + // Only renders Yoast SEO Premium upsells when the page is a Yoast SEO page.
219 + if ( $page !== null && WPSEO_Utils::is_yoast_seo_free_page( $page ) ) {
220 + $this->register_premium_upsell_admin_block();
221 + }
188 222 }
189 223 }
190 224
191 225 /**
192 226 * Loads the plugin suggestions.
227 + *
228 + * @return void
193 229 */
194 230 private function load_plugin_suggestions() {
195 231 $suggestions = new WPSEO_Suggested_Plugins( new WPSEO_Plugin_Availability(), Yoast_Notification_Center::get() );
196 232 $suggestions->register_hooks();
@@ -208,69 +244,23 @@
208 244 }
209 245 }
210 246
211 247 /**
212 - * Registers the promotion class for our GlotPress instance, then creates a notification with the i18n promo.
248 + * See if we should start our XML Sitemaps Admin class.
213 249 *
214 - * @link https://github.com/Yoast/i18n-module
250 + * @return void
215 251 */
216 - private function register_i18n_promo_class() {
217 - // BC, because an older version of the i18n-module didn't have this class.
218 - $i18n_module = new Yoast_I18n_WordPressOrg_v3(
219 - [
220 - 'textdomain' => 'wordpress-seo',
221 - 'plugin_name' => 'Yoast SEO',
222 - 'hook' => 'wpseo_admin_promo_footer',
223 - ],
224 - false
225 - );
226 -
227 - $message = $i18n_module->get_promo_message();
228 -
229 - if ( $message !== '' ) {
230 - $message .= $i18n_module->get_dismiss_i18n_message_button();
231 - }
232 -
233 - $notification_center = Yoast_Notification_Center::get();
234 -
235 - $notification = new Yoast_Notification(
236 - $message,
237 - [
238 - 'type' => Yoast_Notification::WARNING,
239 - 'id' => 'i18nModuleTranslationAssistance',
240 - ]
241 - );
242 -
243 - if ( $message ) {
244 - $notification_center->add_notification( $notification );
245 -
246 - return;
247 - }
248 -
249 - $notification_center->remove_notification( $notification );
250 - }
251 -
252 - /**
253 - * See if we should start our XML Sitemaps Admin class.
254 - */
255 252 private function load_xml_sitemaps_admin() {
256 - if ( WPSEO_Options::get( 'enable_xml_sitemap', false ) ) {
253 + if ( WPSEO_Options::get( 'enable_xml_sitemap', false, [ 'wpseo' ] ) ) {
257 254 new WPSEO_Sitemaps_Admin();
258 255 }
259 256 }
260 257
261 258 /**
262 - * Checks whether search engines are discouraged from indexing the site.
259 + * Shows deprecation warnings to the user if a plugin has registered a filter we have deprecated.
263 260 *
264 - * @return bool Whether search engines are discouraged from indexing the site.
261 + * @return void
265 262 */
266 - private function are_search_engines_discouraged() {
267 - return (string) get_option( 'blog_public' ) === '0';
268 - }
269 -
270 - /**
271 - * Shows deprecation warnings to the user if a plugin has registered a filter we have deprecated.
272 - */
273 263 public function show_hook_deprecation_warnings() {
274 264 global $wp_filter;
275 265
276 266 if ( wp_doing_ajax() ) {
@@ -315,9 +305,9 @@
315 305
316 306 // Determine which filters have been registered.
317 307 $deprecated_notices = array_intersect(
318 308 array_keys( $deprecated_filters ),
319 - array_keys( $wp_filter )
309 + array_keys( $wp_filter ),
320 310 );
321 311
322 312 // Show notice for each deprecated filter or action that has been registered.
323 313 foreach ( $deprecated_notices as $deprecated_filter ) {
@@ -325,9 +315,9 @@
325 315 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- Only uses the hardcoded values from above.
326 316 _deprecated_hook(
327 317 $deprecated_filter,
328 318 'WPSEO ' . $deprecation_info['version'],
329 - $deprecation_info['alternative']
319 + $deprecation_info['alternative'],
330 320 );
331 321 // phpcs:enable
332 322 }
333 323 }
@@ -342,8 +332,10 @@
342 332 }
343 333
344 334 /**
345 335 * Shows a notice on the permalink settings page.
336 + *
337 + * @return void
346 338 */
347 339 public function permalink_settings_notice() {
348 340 global $pagenow;
349 341
@@ -354,68 +346,21 @@
354 346 sprintf(
355 347 /* translators: %1$s and %2$s expand to <em> items to emphasize the word in the middle. */
356 348 esc_html__( 'Changing your permalinks settings can seriously impact your search engine visibility. It should almost %1$s never %2$s be done on a live website.', 'wordpress-seo' ),
357 349 '<em>',
358 - '</em>'
350 + '</em>',
359 351 ),
360 352 esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/why-permalinks/' ) ),
361 353 // The link's content.
362 - esc_html__( 'Learn about why permalinks are important for SEO.', 'wordpress-seo' )
354 + esc_html__( 'Learn about why permalinks are important for SEO.', 'wordpress-seo' ),
363 355 );
364 356 }
365 357 }
366 358
367 359 /**
368 - * Determines whether and where the "search engines discouraged" admin notice should be displayed.
369 - *
370 - * @return bool Whether the "search engines discouraged" admin notice should be displayed.
371 - */
372 - private function should_display_search_engines_discouraged_notice() {
373 - $discouraged_pages = [
374 - 'index.php',
375 - 'plugins.php',
376 - 'update-core.php',
377 - ];
378 -
379 - return (
380 - $this->are_search_engines_discouraged()
381 - && WPSEO_Capability_Utils::current_user_can( 'manage_options' )
382 - && WPSEO_Options::get( 'ignore_search_engines_discouraged_notice', false ) === false
383 - && (
384 - $this->on_wpseo_admin_page()
385 - || in_array( $this->pagenow, $discouraged_pages, true )
386 - )
387 - );
388 - }
389 -
390 - /**
391 - * Displays an admin notice when WordPress is set to discourage search engines from indexing the site.
392 - *
393 - * @return void
394 - */
395 - public function search_engines_discouraged_notice() {
396 - if ( ! $this->should_display_search_engines_discouraged_notice() ) {
397 - return;
398 - }
399 -
400 - printf(
401 - '<div id="robotsmessage" class="notice notice-error"><p><strong>%1$s</strong> %2$s <button type="button" id="robotsmessage-dismiss-button" class="button-link hide-if-no-js" data-nonce="%3$s">%4$s</button></p></div>',
402 - esc_html__( 'Huge SEO Issue: You\'re blocking access to robots.', 'wordpress-seo' ),
403 - sprintf(
404 - /* translators: 1: Link start tag to the WordPress Reading Settings page, 2: Link closing tag. */
405 - esc_html__( 'If you want search engines to show this site in their results, you must %1$sgo to your Reading Settings%2$s and uncheck the box for Search Engine Visibility.', 'wordpress-seo' ),
406 - '<a href="' . esc_url( admin_url( 'options-reading.php' ) ) . '">',
407 - '</a>'
408 - ),
409 - esc_js( wp_create_nonce( 'wpseo-ignore' ) ),
410 - esc_html__( 'I don\'t want this site to show in the search results.', 'wordpress-seo' )
411 - );
412 - }
413 -
414 - /**
415 360 * Adds a custom Yoast section within the Classic Editor publish box.
416 361 *
417 - * @param \WP_Post $post The current post object.
362 + * @param WP_Post $post The current post object.
418 363 *
419 364 * @return void
420 365 */
421 366 public function add_publish_box_section( $post ) {
@@ -425,74 +370,10 @@
425 370 <?php
426 371 /**
427 372 * Fires after the post time/date setting in the Publish meta box.
428 373 *
429 - * @api \WP_Post The current post object.
374 + * @param WP_Post $post The current post object.
430 375 */
431 376 do_action( 'wpseo_publishbox_misc_actions', $post );
432 377 }
433 - }
434 -
435 - /* ********************* DEPRECATED METHODS ********************* */
436 -
437 - /**
438 - * Notify about the default tagline if the user hasn't changed it.
439 - *
440 - * @deprecated 13.2
441 - * @codeCoverageIgnore
442 - */
443 - public function tagline_notice() {
444 - _deprecated_function( __METHOD__, 'WPSEO 13.2' );
445 - }
446 -
447 - /**
448 - * Returns whether or not the site has the default tagline.
449 - *
450 - * @deprecated 13.2
451 - * @codeCoverageIgnore
452 - *
453 - * @return bool
454 - */
455 - public function has_default_tagline() {
456 - _deprecated_function( __METHOD__, 'WPSEO 13.2' );
457 -
458 - $blog_description = get_bloginfo( 'description' );
459 - $default_blog_description = 'Just another WordPress site';
460 -
461 - // We are using the WordPress internal translation.
462 - $translated_blog_description = __( 'Just another WordPress site', 'default' );
463 -
464 - return $translated_blog_description === $blog_description || $default_blog_description === $blog_description;
465 - }
466 -
467 - /**
468 - * Shows an alert when the permalink doesn't contain %postname%.
469 - *
470 - * @deprecated 13.2
471 - * @codeCoverageIgnore
472 - */
473 - public function permalink_notice() {
474 - _deprecated_function( __METHOD__, 'WPSEO 13.2' );
475 - }
476 -
477 - /**
478 - * Add an alert if the blog is not publicly visible.
479 - *
480 - * @deprecated 14.1
481 - * @codeCoverageIgnore
482 - */
483 - public function blog_public_notice() {
484 - _deprecated_function( __METHOD__, 'WPSEO 14.1' );
485 - }
486 -
487 - /**
488 - * Handles the notifiers for the dashboard page.
489 - *
490 - * @deprecated 14.1
491 - * @codeCoverageIgnore
492 - *
493 - * @return void
494 - */
495 - public function handle_notifications() {
496 - _deprecated_function( __METHOD__, 'WPSEO 14.1' );
497 378 }
498 379 }