Yoast SEO - Version 7.3

Version Description

Download this release

Release Info

Developer jipmoors
Plugin Icon 128x128 Yoast SEO
Version 7.3
Comparing to
See all releases

Code changes from version 7.2 to 7.3

Files changed (100) hide show
  1. admin/class-admin-asset-manager.php +0 -12
  2. admin/class-admin-init.php +37 -0
  3. admin/class-admin-utils.php +14 -0
  4. admin/class-admin.php +37 -0
  5. admin/class-cornerstone-field.php +3 -3
  6. admin/class-cornerstone.php +6 -4
  7. admin/class-meta-columns.php +3 -3
  8. admin/class-meta-table-accessible.php +2 -1
  9. admin/class-unsupported-php-message.php +68 -0
  10. admin/class-yoast-form.php +3 -18
  11. admin/config-ui/fields/class-field-google-search-console-intro.php +8 -5
  12. admin/filters/class-cornerstone-filter.php +2 -2
  13. admin/formatter/class-metabox-formatter.php +1 -0
  14. admin/import/plugins/class-abstract-plugin-importer.php +59 -8
  15. admin/import/plugins/class-import-aioseo.php +16 -12
  16. admin/import/plugins/class-import-greg-high-performance-seo.php +42 -0
  17. admin/import/plugins/class-import-headspace.php +2 -2
  18. admin/import/plugins/class-import-jetpack.php +2 -2
  19. admin/import/plugins/class-import-platinum-seo-pack.php +138 -0
  20. admin/import/plugins/class-import-premium-seo-pack.php +39 -0
  21. admin/import/plugins/class-import-seo-framework.php +93 -0
  22. admin/import/plugins/class-import-seopressor.php +12 -17
  23. admin/import/plugins/class-import-smartcrawl.php +150 -0
  24. admin/import/plugins/class-import-squirrly.php +218 -0
  25. admin/import/plugins/class-import-ultimate-seo.php +2 -2
  26. admin/import/plugins/class-import-woothemes-seo.php +2 -2
  27. admin/import/plugins/class-import-wp-meta-seo.php +81 -0
  28. admin/import/plugins/class-import-wpseo.php +26 -2
  29. admin/import/plugins/class-importers.php +7 -0
  30. admin/links/class-link-columns.php +4 -1
  31. admin/links/class-link-notifier.php +1 -1
  32. admin/links/class-link-table-accessible.php +2 -1
  33. admin/metabox/class-metabox.php +7 -13
  34. admin/onpage/class-onpage.php +1 -1
  35. admin/taxonomy/class-taxonomy-fields-presenter.php +1 -6
  36. admin/taxonomy/class-taxonomy-settings-fields.php +1 -0
  37. admin/tracking/class-tracking-server-data.php +1 -1
  38. admin/views/licenses.php +0 -1
  39. admin/views/tabs/dashboard/features.php +15 -9
  40. admin/views/tabs/dashboard/webmaster-tools.php +14 -0
  41. admin/views/tabs/metas/breadcrumbs.php +8 -2
  42. admin/views/tabs/tool/import-seo.php +13 -9
  43. admin/views/tool-import-export.php +10 -7
  44. admin/views/user-profile.php +12 -8
  45. css/dist/{admin-global-720-rtl.min.css → admin-global-730-rtl.min.css} +0 -0
  46. css/dist/{admin-global-720.min.css → admin-global-730.min.css} +0 -0
  47. css/dist/{adminbar-720-rtl.min.css → adminbar-730-rtl.min.css} +0 -0
  48. css/dist/{adminbar-720.min.css → adminbar-730.min.css} +0 -0
  49. css/dist/{alerts-720-rtl.min.css → alerts-730-rtl.min.css} +0 -0
  50. css/dist/{alerts-720.min.css → alerts-730.min.css} +0 -0
  51. css/dist/{dashboard-720-rtl.min.css → dashboard-730-rtl.min.css} +0 -0
  52. css/dist/{dashboard-720.min.css → dashboard-730.min.css} +0 -0
  53. css/dist/{edit-page-720-rtl.min.css → edit-page-730-rtl.min.css} +0 -0
  54. css/dist/{edit-page-720.min.css → edit-page-730.min.css} +0 -0
  55. css/dist/{featured-image-720-rtl.min.css → featured-image-730-rtl.min.css} +0 -0
  56. css/dist/{featured-image-720.min.css → featured-image-730.min.css} +0 -0
  57. css/dist/filter-explanation-720-rtl.min.css +0 -1
  58. css/dist/filter-explanation-720.min.css +0 -1
  59. css/dist/filter-explanation-730-rtl.min.css +1 -0
  60. css/dist/filter-explanation-730.min.css +1 -0
  61. css/dist/{inside-editor-720-rtl.min.css → inside-editor-730-rtl.min.css} +0 -0
  62. css/dist/{inside-editor-720.min.css → inside-editor-730.min.css} +0 -0
  63. css/dist/{metabox-720-rtl.min.css → metabox-730-rtl.min.css} +1 -1
  64. css/dist/{metabox-720.min.css → metabox-730.min.css} +1 -1
  65. css/dist/{metabox-primary-category-720-rtl.min.css → metabox-primary-category-730-rtl.min.css} +0 -0
  66. css/dist/{metabox-primary-category-720.min.css → metabox-primary-category-730.min.css} +0 -0
  67. css/dist/{snippet-720-rtl.min.css → snippet-730-rtl.min.css} +0 -0
  68. css/dist/{snippet-720.min.css → snippet-730.min.css} +0 -0
  69. css/dist/{toggle-switch-720-rtl.min.css → toggle-switch-730-rtl.min.css} +0 -0
  70. css/dist/{toggle-switch-720.min.css → toggle-switch-730.min.css} +0 -0
  71. css/dist/{wpseo-dismissible-720-rtl.min.css → wpseo-dismissible-730-rtl.min.css} +0 -0
  72. css/dist/{wpseo-dismissible-720.min.css → wpseo-dismissible-730.min.css} +0 -0
  73. css/dist/{yoast-components-720-rtl.min.css → yoast-components-730-rtl.min.css} +0 -0
  74. css/dist/{yoast-components-720.min.css → yoast-components-730.min.css} +0 -0
  75. css/dist/{yoast-extensions-720-rtl.min.css → yoast-extensions-730-rtl.min.css} +1 -1
  76. css/dist/{yoast-extensions-720.min.css → yoast-extensions-730.min.css} +1 -1
  77. css/dist/{yst_plugin_tools-720-rtl.min.css → yst_plugin_tools-730-rtl.min.css} +1 -1
  78. css/dist/{yst_plugin_tools-720.min.css → yst_plugin_tools-730.min.css} +1 -1
  79. css/dist/{yst_seo_score-720-rtl.min.css → yst_seo_score-730-rtl.min.css} +0 -0
  80. css/dist/{yst_seo_score-720.min.css → yst_seo_score-730.min.css} +0 -0
  81. frontend/class-frontend.php +21 -10
  82. frontend/class-json-ld.php +1 -1
  83. images/Yoast_SEO_Icon.svg +1 -1
  84. images/Yoast_SEO_negative_icon.svg +1 -1
  85. images/link-in-icon.svg +1 -1
  86. images/link-out-icon.svg +1 -1
  87. images/readability-icon.svg +1 -1
  88. images/support-team.svg +1 -1
  89. images/yoast-configuration-icon.svg +1 -1
  90. inc/class-upgrade.php +21 -1
  91. inc/class-wpseo-meta.php +7 -1
  92. inc/class-wpseo-shortlinker.php +3 -15
  93. inc/class-wpseo-utils.php +1 -2
  94. inc/options/class-wpseo-option-titles.php +65 -67
  95. inc/options/class-wpseo-option-wpseo.php +3 -0
  96. inc/options/class-wpseo-option.php +5 -0
  97. inc/options/class-wpseo-options-backfill.php +21 -25
  98. inc/sitemaps/class-sitemaps.php +5 -5
  99. js/dist/{commons-720.min.js → commons-730.min.js} +6 -6
  100. js/dist/{configuration-wizard-720.min.js → configuration-wizard-730.min.js} +3 -3
admin/class-admin-asset-manager.php CHANGED
@@ -85,17 +85,6 @@ class WPSEO_Admin_Asset_Manager {
85
  * Calls the functions that register scripts and styles with the scripts and styles to be registered as arguments.
86
  */
87
  public function register_assets() {
88
-
89
- $user_locale = WPSEO_Utils::get_user_locale();
90
- $language = WPSEO_Utils::get_language( $user_locale );
91
-
92
- wp_register_script(
93
- self::PREFIX . 'intl-polyfill',
94
- sprintf( 'https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.%s', $language ),
95
- array(),
96
- WPSEO_VERSION
97
- );
98
-
99
  $this->register_scripts( $this->scripts_to_be_registered() );
100
  $this->register_styles( $this->styles_to_be_registered() );
101
  }
@@ -199,7 +188,6 @@ class WPSEO_Admin_Asset_Manager {
199
  // Load webpack-commons for bundle support.
200
  'src' => 'commons-' . $flat_version,
201
  'deps' => array(
202
- self::PREFIX . 'intl-polyfill',
203
  self::PREFIX . 'babel-polyfill',
204
  ),
205
  ),
85
  * Calls the functions that register scripts and styles with the scripts and styles to be registered as arguments.
86
  */
87
  public function register_assets() {
 
 
 
 
 
 
 
 
 
 
 
88
  $this->register_scripts( $this->scripts_to_be_registered() );
89
  $this->register_styles( $this->styles_to_be_registered() );
90
  }
188
  // Load webpack-commons for bundle support.
189
  'src' => 'commons-' . $flat_version,
190
  'deps' => array(
 
191
  self::PREFIX . 'babel-polyfill',
192
  ),
193
  ),
admin/class-admin-init.php CHANGED
@@ -43,6 +43,7 @@ class WPSEO_Admin_Init {
43
  add_action( 'admin_init', array( $this, 'yoast_plugin_compatibility_notification' ), 15 );
44
  add_action( 'admin_init', array( $this, 'yoast_plugin_suggestions_notification' ), 15 );
45
  add_action( 'admin_init', array( $this, 'recalculate_notice' ), 15 );
 
46
  add_action( 'admin_init', array( $this->asset_manager, 'register_assets' ) );
47
  add_action( 'admin_init', array( $this, 'show_hook_deprecation_warnings' ) );
48
  add_action( 'admin_init', array( 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ) );
@@ -410,6 +411,42 @@ class WPSEO_Admin_Init {
410
  );
411
  }
412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  /**
414
  * Check if the user has dismissed the given notice (by $notice_name)
415
  *
43
  add_action( 'admin_init', array( $this, 'yoast_plugin_compatibility_notification' ), 15 );
44
  add_action( 'admin_init', array( $this, 'yoast_plugin_suggestions_notification' ), 15 );
45
  add_action( 'admin_init', array( $this, 'recalculate_notice' ), 15 );
46
+ add_action( 'admin_init', array( $this, 'unsupported_php_notice' ), 15 );
47
  add_action( 'admin_init', array( $this->asset_manager, 'register_assets' ) );
48
  add_action( 'admin_init', array( $this, 'show_hook_deprecation_warnings' ) );
49
  add_action( 'admin_init', array( 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ) );
411
  );
412
  }
413
 
414
+ /**
415
+ * Creates an unsupported PHP version notification in the notification center.
416
+ *
417
+ * @return void
418
+ */
419
+ public function unsupported_php_notice() {
420
+ $info_message = sprintf(
421
+ /* translators: 1: The strong opening tag; 2: The strong closing tag; 3: the Yoast SEO version that is dropping support; 4: The release date of the version of Yoast SEO that is dropping support; 5: The PHP version no longer being supported; */
422
+ __( '%1$sAction is needed%2$s: As of version %3$s, due to be released on %4$s, Yoast SEO will no longer work with PHP %5$s. Unfortunately, your site is running on PHP %5$s right now, so action is needed. Thankfully, you can update your PHP yourself.', 'wordpress-seo' ),
423
+ '<strong>',
424
+ '</strong>',
425
+ '7.5',
426
+ date_i18n( get_option( 'date_format' ), strtotime( '15-05-2018' ) ),
427
+ '5.2'
428
+ );
429
+
430
+ $unsupported_php_notification = new Yoast_Notification(
431
+ $info_message,
432
+ array(
433
+ 'type' => Yoast_Notification::ERROR,
434
+ 'id' => 'wpseo-dismiss-unsupported-php',
435
+ 'capabilities' => 'wpseo_manage_options',
436
+ )
437
+ );
438
+
439
+ $notification_center = Yoast_Notification_Center::get();
440
+
441
+ if ( WPSEO_Admin_Utils::is_supported_php_version_installed() === false ) {
442
+ $notification_center->add_notification( $unsupported_php_notification );
443
+
444
+ return;
445
+ }
446
+
447
+ $notification_center->remove_notification( $unsupported_php_notification );
448
+ }
449
+
450
  /**
451
  * Check if the user has dismissed the given notice (by $notice_name)
452
  *
admin/class-admin-utils.php CHANGED
@@ -67,4 +67,18 @@ class WPSEO_Admin_Utils {
67
  );
68
 
69
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
67
  );
68
 
69
  }
70
+
71
+ /**
72
+ * Determines whether or not the user has an invalid version of PHP installed.
73
+ *
74
+ * @return bool Whether or not PHP 5.2 or lower is installed.
75
+ */
76
+ public static function is_supported_php_version_installed() {
77
+ $checker = new Whip_RequirementsChecker( array( 'php' => PHP_VERSION ) );
78
+
79
+ $checker->addRequirement( Whip_VersionRequirement::fromCompareString( 'php', '>=5.3' ) );
80
+ $checker->check();
81
+
82
+ return $checker->hasMessages() === false;
83
+ }
84
  }
admin/class-admin.php CHANGED
@@ -312,12 +312,34 @@ class WPSEO_Admin {
312
 
313
  /**
314
  * Initializes Whip to show a notice for outdated PHP versions.
 
 
 
 
315
  */
316
  protected function check_php_version() {
 
317
  if ( ! current_user_can( 'manage_options' ) ) {
318
  return;
319
  }
320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  if ( ! $this->on_dashboard_page() ) {
322
  return;
323
  }
@@ -327,6 +349,21 @@ class WPSEO_Admin {
327
  ) );
328
  }
329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  /**
331
  * Whether we are on the admin dashboard page.
332
  *
312
 
313
  /**
314
  * Initializes Whip to show a notice for outdated PHP versions.
315
+ *
316
+ * @todo Deprecate this method when WordPress 5.1 is our currently minimal supported version.
317
+ *
318
+ * @return void
319
  */
320
  protected function check_php_version() {
321
+ // If the user isn't an admin, don't display anything.
322
  if ( ! current_user_can( 'manage_options' ) ) {
323
  return;
324
  }
325
 
326
+ // Check if the user is running PHP 5.2.
327
+ if ( WPSEO_Admin_Utils::is_supported_php_version_installed() === false ) {
328
+ $this->show_unsupported_php_message();
329
+
330
+ return;
331
+ }
332
+
333
+ /*
334
+ * The Whip message shouldn't be shown from WordPress 4.9.5 and higher because
335
+ * that version introduces Serve Happy which is almost similar to Whip.
336
+ */
337
+ $minimal_wp_version = '4.9.5';
338
+
339
+ if ( version_compare( $GLOBALS['wp_version'], $minimal_wp_version, '>=' ) ) {
340
+ return;
341
+ }
342
+
343
  if ( ! $this->on_dashboard_page() ) {
344
  return;
345
  }
349
  ) );
350
  }
351
 
352
+ /**
353
+ * Creates a new message to display regarding the usage of PHP 5.2 (or lower).
354
+ *
355
+ * @return void
356
+ */
357
+ protected function show_unsupported_php_message() {
358
+ $presenter = new Whip_WPMessagePresenter(
359
+ new WPSEO_Unsupported_PHP_Message(),
360
+ new Whip_MessageDismisser( time(), ( WEEK_IN_SECONDS * 4 ), new Whip_WPDismissOption() ),
361
+ __( 'Remind me again in 4 weeks.', 'wordpress-seo' )
362
+ );
363
+
364
+ $presenter->register_hooks();
365
+ }
366
+
367
  /**
368
  * Whether we are on the admin dashboard page.
369
  *
admin/class-cornerstone-field.php CHANGED
@@ -27,11 +27,11 @@ class WPSEO_Cornerstone_Field {
27
  $return = '';
28
  $return .= sprintf(
29
  '<input id="%1$s" class="wpseo-cornerstone-checkbox" type="checkbox" value="1" name="%1$s" %2$s/>',
30
- WPSEO_Cornerstone::META_NAME,
31
  checked( $this->get_meta_value( $post->ID ), '1', false )
32
  );
33
 
34
- $return .= sprintf( '<label for="%1$s">', WPSEO_Cornerstone::META_NAME );
35
 
36
  $return .= sprintf(
37
  /* translators: 1: link open tag; 2: link close tag. */
@@ -52,6 +52,6 @@ class WPSEO_Cornerstone_Field {
52
  * @return null|string The meta value from the database.
53
  */
54
  protected function get_meta_value( $post_id ) {
55
- return get_post_meta( $post_id, WPSEO_Cornerstone::META_NAME, true );
56
  }
57
  }
27
  $return = '';
28
  $return .= sprintf(
29
  '<input id="%1$s" class="wpseo-cornerstone-checkbox" type="checkbox" value="1" name="%1$s" %2$s/>',
30
+ WPSEO_Cornerstone::FIELD_NAME,
31
  checked( $this->get_meta_value( $post->ID ), '1', false )
32
  );
33
 
34
+ $return .= sprintf( '<label for="%1$s">', WPSEO_Cornerstone::FIELD_NAME );
35
 
36
  $return .= sprintf(
37
  /* translators: 1: link open tag; 2: link close tag. */
52
  * @return null|string The meta value from the database.
53
  */
54
  protected function get_meta_value( $post_id ) {
55
+ return WPSEO_Meta::get_value( WPSEO_Cornerstone::META_NAME, $post_id );
56
  }
57
  }
admin/class-cornerstone.php CHANGED
@@ -10,7 +10,9 @@
10
  */
11
  class WPSEO_Cornerstone {
12
 
13
- const META_NAME = '_yst_is_cornerstone';
 
 
14
 
15
  /**
16
  * Registers the hooks.
@@ -53,7 +55,7 @@ class WPSEO_Cornerstone {
53
  * @return bool True when checkbox is checked.
54
  */
55
  protected function is_cornerstone_content() {
56
- return filter_input( INPUT_POST, self::META_NAME ) === '1';
57
  }
58
 
59
  /**
@@ -76,7 +78,7 @@ class WPSEO_Cornerstone {
76
  * @return void
77
  */
78
  protected function update_meta( $post_id, $is_cornerstone_content ) {
79
- update_post_meta( $post_id, self::META_NAME, $is_cornerstone_content );
80
  }
81
 
82
  /**
@@ -87,6 +89,6 @@ class WPSEO_Cornerstone {
87
  * @return void
88
  */
89
  protected function delete_meta( $post_id ) {
90
- delete_post_meta( $post_id, self::META_NAME );
91
  }
92
  }
10
  */
11
  class WPSEO_Cornerstone {
12
 
13
+ const META_NAME = 'is_cornerstone';
14
+
15
+ const FIELD_NAME = 'yoast_wpseo_is_cornerstone';
16
 
17
  /**
18
  * Registers the hooks.
55
  * @return bool True when checkbox is checked.
56
  */
57
  protected function is_cornerstone_content() {
58
+ return filter_input( INPUT_POST, self::FIELD_NAME ) === '1';
59
  }
60
 
61
  /**
78
  * @return void
79
  */
80
  protected function update_meta( $post_id, $is_cornerstone_content ) {
81
+ WPSEO_Meta::set_value( self::META_NAME, $is_cornerstone_content, $post_id );
82
  }
83
 
84
  /**
89
  * @return void
90
  */
91
  protected function delete_meta( $post_id ) {
92
+ WPSEO_Meta::delete( self::META_NAME, $post_id );
93
  }
94
  }
admin/class-meta-columns.php CHANGED
@@ -295,9 +295,9 @@ class WPSEO_Meta_Columns {
295
  */
296
  protected function get_keyword_filter( $keyword_filter ) {
297
  return array(
298
- 'post_type' => get_query_var( 'post_type', 'post' ),
299
- 'meta_key' => WPSEO_Meta::$meta_prefix . 'focuskw',
300
- 'meta_value' => sanitize_text_field( $keyword_filter ),
301
  );
302
  }
303
 
295
  */
296
  protected function get_keyword_filter( $keyword_filter ) {
297
  return array(
298
+ 'post_type' => get_query_var( 'post_type', 'post' ),
299
+ 'key' => WPSEO_Meta::$meta_prefix . 'focuskw',
300
+ 'value' => sanitize_text_field( $keyword_filter ),
301
  );
302
  }
303
 
admin/class-meta-table-accessible.php CHANGED
@@ -71,7 +71,8 @@ class WPSEO_Meta_Table_Accessible {
71
  global $wpdb;
72
 
73
  $storage = new WPSEO_Meta_Storage();
74
- if ( $wpdb->get_var( 'SHOW TABLES LIKE "' . $storage->get_table_name() . '"' ) !== $storage->get_table_name() ) {
 
75
  self::set_inaccessible();
76
  return false;
77
  }
71
  global $wpdb;
72
 
73
  $storage = new WPSEO_Meta_Storage();
74
+ $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $storage->get_table_name() );
75
+ if ( $wpdb->get_var( $query ) !== $storage->get_table_name() ) {
76
  self::set_inaccessible();
77
  return false;
78
  }
admin/class-unsupported-php-message.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WPSEO plugin file.
4
+ *
5
+ * @package WPSEO\Admin
6
+ */
7
+
8
+ /**
9
+ * Class that creates the PHP 5.2 support message.
10
+ */
11
+ class WPSEO_Unsupported_PHP_Message implements Whip_Message {
12
+
13
+ /**
14
+ * Composes the body of the message to display.
15
+ *
16
+ * @return string The message to display.
17
+ */
18
+ public function body() {
19
+ $message = array();
20
+
21
+ $message[] = Whip_MessageFormatter::strongParagraph( __( 'PHP update required.', 'wordpress-seo' ) ) . '<br />';
22
+ $message[] = Whip_MessageFormatter::paragraph(
23
+ sprintf(
24
+ /* translators: 1: The strong opening tag; 2: The strong closing tag; 3: the Yoast SEO version that is dropping support; 4: The release date of the version of Yoast SEO that is dropping support; 5: The PHP version no longer being supported; */
25
+ __( '%1$sAction is needed%2$s: As of version %3$s, due to be released on %4$s, Yoast SEO will no longer work with PHP %5$s. Unfortunately, your site is running on PHP %5$s right now, so action is needed. Thankfully, you can update your PHP yourself.', 'wordpress-seo' ),
26
+ '<strong>',
27
+ '</strong>',
28
+ '7.5',
29
+ date_i18n( get_option( 'date_format' ), strtotime( '15-05-2018' ) ),
30
+ '5.2'
31
+ )
32
+ ) . '<br />';
33
+
34
+ $message[] = Whip_MessageFormatter::strongParagraph( __( 'Why?', 'wordpress-seo' ) ) . '<br />';
35
+ $message[] = Whip_MessageFormatter::paragraph(
36
+ sprintf(
37
+ /* translators: 1: the PHP version that will no longer be supported; 2: The year the unsupported PHP version was released; 3: The minimal PHP version that will be supported; 4: The year the minimally supported version of PHP was released; */
38
+ __( 'PHP is the programming language WordPress is developed in and your site runs on. PHP %1$s was released in %2$s and was replaced by PHP %3$s in %4$s. Newer versions of PHP are both faster and more secure, so updating will have a positive effect on your site. Plus, it it enables our developers to use the latest technologies to make Yoast SEO even better.', 'wordpress-seo' ),
39
+ '5.2',
40
+ '2006',
41
+ '5.3',
42
+ '2009'
43
+ )
44
+ ) . '<br />';
45
+
46
+ $message[] = Whip_MessageFormatter::strongParagraph( __( 'How?', 'wordpress-seo' ) ) . '<br />';
47
+ $message[] = Whip_MessageFormatter::paragraph(
48
+ sprintf(
49
+ /* translators: 1: The link tag to the WordPress instructions page for upgrading to newer versions of PHP; 2: The link closing tag; 3: The recommended PHP version; 4: The Yoast article about testing plugin compatibility with newer PHP versions; */
50
+ __( 'For any questions you may have about updating your PHP version, WordPress %1$shas a great page with instructions here%2$s. We recommend going up to version %3$s. Not all plugins may be ready for PHP 7 though, so %4$swe wrote an article on how to test them before you update here%2$s.', 'wordpress-seo' ),
51
+ '<a href="https://wordpress.org/support/upgrade-php/" target="_blank" rel="noopener noreferrer">',
52
+ '</a>',
53
+ '7.2',
54
+ '<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/wg' ) . '" target="_blank">'
55
+ ) ) . '<br />';
56
+
57
+ $message[] = Whip_MessageFormatter::paragraph(
58
+ sprintf(
59
+ /* translators: 1: The link tag to email examples page; 2: The link closing tag; 3: The link tag for the list of recommended WordPress hosting partners; */
60
+ __( 'If you cannot update your PHP yourself, you can send an email to your host. We have %1$sexamples%2$s here. If they don\'t want to upgrade your PHP version, we recommend switching hosts. Take a look at our list of %3$srecommended WordPress hosting partners%2$s, they\'ve been vetted by the Yoast support team and offer all the features a modern host should have.', 'wordpress-seo' ),
61
+ '<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/wh' ) . '" target="_blank">',
62
+ '</a>',
63
+ sprintf( '<a href="%1$s" target="_blank">', esc_url( Whip_Host::hostingPageUrl() ) )
64
+ ) ) . '<br />';
65
+
66
+ return implode( $message, "\n" );
67
+ }
68
+ }
admin/class-yoast-form.php CHANGED
@@ -117,7 +117,7 @@ class Yoast_Form {
117
  *
118
  * @return array
119
  */
120
- private function get_option() {
121
  if ( is_network_admin() ) {
122
  return get_site_option( $this->option_name );
123
  }
@@ -144,7 +144,7 @@ class Yoast_Form {
144
  /**
145
  * Apply general admin_footer hooks
146
  */
147
- do_action( 'wpseo_admin_footer' );
148
 
149
  /**
150
  * Run possibly set actions to add for example an i18n box
@@ -160,22 +160,7 @@ class Yoast_Form {
160
 
161
  echo '</div><!-- end of div wpseo_content_wrapper -->';
162
 
163
-
164
- if ( ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) ) {
165
- $xdebug = ( extension_loaded( 'xdebug' ) ? true : false );
166
- echo '
167
- <div id="wpseo-debug-info" class="yoast-container">
168
-
169
- <h2>' . esc_html__( 'Debug Information', 'wordpress-seo' ) . '</h2>
170
- <div>
171
- <h3 class="wpseo-debug-heading">' . esc_html__( 'Current option:', 'wordpress-seo' ) . ' <span class="wpseo-debug">' . esc_html( $this->option_name ) . '</span></h3>
172
- ' . ( ( $xdebug ) ? '' : '<pre>' );
173
- var_dump( $this->get_option() );
174
- echo '
175
- ' . ( ( $xdebug ) ? '' : '</pre>' ) . '
176
- </div>
177
- </div>';
178
- }
179
 
180
  echo '
181
  </div><!-- end of wrap -->';
117
  *
118
  * @return array
119
  */
120
+ public function get_option() {
121
  if ( is_network_admin() ) {
122
  return get_site_option( $this->option_name );
123
  }
144
  /**
145
  * Apply general admin_footer hooks
146
  */
147
+ do_action( 'wpseo_admin_footer', $this );
148
 
149
  /**
150
  * Run possibly set actions to add for example an i18n box
160
 
161
  echo '</div><!-- end of div wpseo_content_wrapper -->';
162
 
163
+ do_action( 'wpseo_admin_below_content', $this );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
  echo '
166
  </div><!-- end of wrap -->';
admin/config-ui/fields/class-field-google-search-console-intro.php CHANGED
@@ -18,14 +18,17 @@ class WPSEO_Config_Field_Google_Search_Console_Intro extends WPSEO_Config_Field
18
 
19
  $html = sprintf(
20
  /* translators: %1$s is the plugin name, %2$s is a link start tag to a Yoast help page, %3$s is the link closing tag. */
21
- __( '%1$s integrates with Google Search Console, a must-have tool for site owners.
22
- It provides you with information about the health of your site.
 
23
  Don\'t have a Google account or is your site not activated yet?
24
  Find out %2$show to connect Google Search Console to your site.%3$s',
25
- 'wordpress-seo' ),
 
26
  'Yoast SEO',
27
- '<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/1ex' ) . '">',
28
- '</a>' );
 
29
 
30
  $disclaimer = __( 'Note: we don\'t store your data in any way and don\'t have full access to your account.
31
  Your privacy is safe with us.', 'wordpress-seo' );
18
 
19
  $html = sprintf(
20
  /* translators: %1$s is the plugin name, %2$s is a link start tag to a Yoast help page, %3$s is the link closing tag. */
21
+ esc_html__(
22
+ '%1$s integrates with Google Search Console, a must-have tool for site owners.
23
+ It provides you with information about the health of your site.
24
  Don\'t have a Google account or is your site not activated yet?
25
  Find out %2$show to connect Google Search Console to your site.%3$s',
26
+ 'wordpress-seo'
27
+ ),
28
  'Yoast SEO',
29
+ '<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1ex' ) ) . '">',
30
+ '</a>'
31
+ );
32
 
33
  $disclaimer = __( 'Note: we don\'t store your data in any way and don\'t have full access to your account.
34
  Your privacy is safe with us.', 'wordpress-seo' );
admin/filters/class-cornerstone-filter.php CHANGED
@@ -32,7 +32,7 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter {
32
 
33
  $where .= sprintf(
34
  ' AND ' . $wpdb->posts . '.ID IN( SELECT post_id FROM ' . $wpdb->postmeta . ' WHERE meta_key = "%s" AND meta_value = "1" ) ',
35
- WPSEO_Cornerstone::META_NAME
36
  );
37
  }
38
 
@@ -85,7 +85,7 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter {
85
  meta_value = "1" AND meta_key = %s
86
  ',
87
  $this->get_current_post_type(),
88
- WPSEO_Cornerstone::META_NAME
89
  )
90
  );
91
  }
32
 
33
  $where .= sprintf(
34
  ' AND ' . $wpdb->posts . '.ID IN( SELECT post_id FROM ' . $wpdb->postmeta . ' WHERE meta_key = "%s" AND meta_value = "1" ) ',
35
+ WPSEO_Meta::$meta_prefix . WPSEO_Cornerstone::META_NAME
36
  );
37
  }
38
 
85
  meta_value = "1" AND meta_key = %s
86
  ',
87
  $this->get_current_post_type(),
88
+ WPSEO_Meta::$meta_prefix . WPSEO_Cornerstone::META_NAME
89
  )
90
  );
91
  }
admin/formatter/class-metabox-formatter.php CHANGED
@@ -129,6 +129,7 @@ class WPSEO_Metabox_Formatter {
129
  ),
130
  ),
131
  'markdownEnabled' => $this->is_markdown_enabled(),
 
132
  );
133
  }
134
 
129
  ),
130
  ),
131
  'markdownEnabled' => $this->is_markdown_enabled(),
132
+ 'analysisHeadingTitle' => __( 'Analysis', 'wordpress-seo' ),
133
  );
134
  }
135
 
admin/import/plugins/class-abstract-plugin-importer.php CHANGED
@@ -26,12 +26,19 @@ abstract class WPSEO_Plugin_Importer {
26
  protected $plugin_name;
27
 
28
  /**
29
- * Meta key, used in SQL LIKE clause for detect query.
30
  *
31
  * @var string
32
  */
33
  protected $meta_key;
34
 
 
 
 
 
 
 
 
35
  /**
36
  * Class constructor.
37
  */
@@ -98,6 +105,9 @@ abstract class WPSEO_Plugin_Importer {
98
  */
99
  protected function cleanup() {
100
  global $wpdb;
 
 
 
101
  $wpdb->query(
102
  $wpdb->prepare(
103
  "DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s",
@@ -106,13 +116,22 @@ abstract class WPSEO_Plugin_Importer {
106
  );
107
  $result = $wpdb->__get( 'result' );
108
  if ( ! $result ) {
109
- /* translators: %s is replaced with the plugin's name. */
110
- $this->status->set_msg( sprintf( __( 'Cleanup of %s data failed.', 'wordpress-seo' ), $this->plugin_name ) );
111
  }
112
 
113
  return $result;
114
  }
115
 
 
 
 
 
 
 
 
 
 
 
116
  /**
117
  * Detects whether an import for this plugin is needed.
118
  *
@@ -135,10 +154,13 @@ abstract class WPSEO_Plugin_Importer {
135
  */
136
  protected function detect() {
137
  global $wpdb;
138
- $result = $wpdb->get_var(
 
 
 
139
  $wpdb->prepare(
140
- "SELECT COUNT(*) AS `count` FROM {$wpdb->postmeta} WHERE meta_key LIKE %s",
141
- $this->meta_key
142
  )
143
  );
144
  if ( $result === '0' ) {
@@ -171,6 +193,7 @@ abstract class WPSEO_Plugin_Importer {
171
  $this->set_missing_db_rights_status();
172
  return false;
173
  }
 
174
  // Delete all the values in our temp table for posts that already have data for $new_key.
175
  $wpdb->query(
176
  $wpdb->prepare(
@@ -227,6 +250,22 @@ abstract class WPSEO_Plugin_Importer {
227
  $this->status->set_msg( sprintf( __( 'The %s importer functionality uses temporary database tables. It seems your WordPress install does not have the capability to do this, please consult your hosting provider.', 'wordpress-seo' ), 'Yoast SEO' ) );
228
  }
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  /**
231
  * Saves a post meta value if it doesn't already exist.
232
  *
@@ -235,9 +274,21 @@ abstract class WPSEO_Plugin_Importer {
235
  * @param int $post_id The Post to save the meta for.
236
  */
237
  protected function maybe_save_post_meta( $new_key, $value, $post_id ) {
238
- $existing_value = get_post_meta( $post_id, WPSEO_Meta::$meta_prefix . $new_key, true );
 
 
 
 
 
 
 
 
239
  if ( empty( $existing_value ) ) {
240
- WPSEO_Meta::set_value( $new_key, $value, $post_id );
 
 
 
 
241
  }
242
  }
243
 
26
  protected $plugin_name;
27
 
28
  /**
29
+ * Meta key, used in SQL LIKE clause for delete query.
30
  *
31
  * @var string
32
  */
33
  protected $meta_key;
34
 
35
+ /**
36
+ * Array of meta keys to detect and import.
37
+ *
38
+ * @var array
39
+ */
40
+ protected $clone_keys;
41
+
42
  /**
43
  * Class constructor.
44
  */
105
  */
106
  protected function cleanup() {
107
  global $wpdb;
108
+ if ( empty( $this->meta_key ) ) {
109
+ return true;
110
+ }
111
  $wpdb->query(
112
  $wpdb->prepare(
113
  "DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s",
116
  );
117
  $result = $wpdb->__get( 'result' );
118
  if ( ! $result ) {
119
+ $this->cleanup_error_msg();
 
120
  }
121
 
122
  return $result;
123
  }
124
 
125
+ /**
126
+ * Sets the status message for when a cleanup has gone bad.
127
+ *
128
+ * @return void
129
+ */
130
+ protected function cleanup_error_msg() {
131
+ /* translators: %s is replaced with the plugin's name. */
132
+ $this->status->set_msg( sprintf( __( 'Cleanup of %s data failed.', 'wordpress-seo' ), $this->plugin_name ) );
133
+ }
134
+
135
  /**
136
  * Detects whether an import for this plugin is needed.
137
  *
154
  */
155
  protected function detect() {
156
  global $wpdb;
157
+
158
+ $meta_keys = wp_list_pluck( $this->clone_keys, 'old_key' );
159
+ $placeholders = implode( ', ', array_fill( 0, count( $meta_keys ), '%s' ) );
160
+ $result = $wpdb->get_var(
161
  $wpdb->prepare(
162
+ "SELECT COUNT(*) AS `count` FROM {$wpdb->postmeta} WHERE meta_key IN ( $placeholders )",
163
+ $meta_keys
164
  )
165
  );
166
  if ( $result === '0' ) {
193
  $this->set_missing_db_rights_status();
194
  return false;
195
  }
196
+
197
  // Delete all the values in our temp table for posts that already have data for $new_key.
198
  $wpdb->query(
199
  $wpdb->prepare(
250
  $this->status->set_msg( sprintf( __( 'The %s importer functionality uses temporary database tables. It seems your WordPress install does not have the capability to do this, please consult your hosting provider.', 'wordpress-seo' ), 'Yoast SEO' ) );
251
  }
252
 
253
+ /**
254
+ * Helper function to search for a key in an array and maybe save it as a meta field.
255
+ *
256
+ * @param string $plugin_key The key in the $data array to check.
257
+ * @param string $yoast_key The identifier we use in our meta settings.
258
+ * @param array $data The array of data for this post to sift through.
259
+ * @param int $post_id The post ID.
260
+ *
261
+ * @return void
262
+ */
263
+ protected function import_meta_helper( $plugin_key, $yoast_key, $data, $post_id ) {
264
+ if ( ! empty( $data[ $plugin_key ] ) ) {
265
+ $this->maybe_save_post_meta( $yoast_key, $data[ $plugin_key ], $post_id );
266
+ }
267
+ }
268
+
269
  /**
270
  * Saves a post meta value if it doesn't already exist.
271
  *
274
  * @param int $post_id The Post to save the meta for.
275
  */
276
  protected function maybe_save_post_meta( $new_key, $value, $post_id ) {
277
+ // Big. Fat. Sigh. Mostly used for _yst_is_cornerstone, but might be useful for other hidden meta's.
278
+ $key = WPSEO_Meta::$meta_prefix . $new_key;
279
+ $wpseo_meta = true;
280
+ if ( substr( $new_key, 0, 1 ) === '_' ) {
281
+ $key = $new_key;
282
+ $wpseo_meta = false;
283
+ }
284
+
285
+ $existing_value = get_post_meta( $post_id, $key, true );
286
  if ( empty( $existing_value ) ) {
287
+ if ( $wpseo_meta ) {
288
+ WPSEO_Meta::set_value( $new_key, $value, $post_id );
289
+ return;
290
+ }
291
+ update_post_meta( $post_id, $new_key, $value );
292
  }
293
  }
294
 
admin/import/plugins/class-import-aioseo.php CHANGED
@@ -17,14 +17,26 @@ class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer {
17
  protected $plugin_name = 'All In One SEO Pack';
18
 
19
  /**
20
- * Meta key, used in SQL LIKE clause for detect query.
21
  *
22
  * @var string
23
  */
24
  protected $meta_key = '_aioseop_%';
25
 
26
  /**
27
- * Array of keys to clone.
 
 
 
 
 
 
 
 
 
 
 
 
28
  *
29
  * @var array
30
  */
@@ -58,9 +70,8 @@ class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer {
58
  $status = parent::import();
59
  if ( $status ) {
60
  $this->import_opengraph();
61
- return true;
62
  }
63
- return false;
64
  }
65
 
66
  /**
@@ -89,14 +100,7 @@ class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer {
89
  $meta = get_post_meta( $post_id, '_aioseop_opengraph_settings', true );
90
  $meta = maybe_unserialize( $meta );
91
 
92
- $import_keys = array(
93
- 'aioseop_opengraph_settings_title' => 'opengraph-title',
94
- 'aioseop_opengraph_settings_desc' => 'opengraph-description',
95
- 'aioseop_opengraph_settings_customimg' => 'opengraph-image',
96
- 'aioseop_opengraph_settings_customimg_twitter' => 'twitter-image',
97
- );
98
-
99
- foreach ( $import_keys as $old_key => $new_key ) {
100
  $this->maybe_save_post_meta( $new_key, $meta[ $old_key ], $post_id );
101
  }
102
  }
17
  protected $plugin_name = 'All In One SEO Pack';
18
 
19
  /**
20
+ * Meta key, used in SQL LIKE clause for delete query.
21
  *
22
  * @var string
23
  */
24
  protected $meta_key = '_aioseop_%';
25
 
26
  /**
27
+ * OpenGraph keys to import.
28
+ *
29
+ * @var array
30
+ */
31
+ protected $import_keys = array(
32
+ 'aioseop_opengraph_settings_title' => 'opengraph-title',
33
+ 'aioseop_opengraph_settings_desc' => 'opengraph-description',
34
+ 'aioseop_opengraph_settings_customimg' => 'opengraph-image',
35
+ 'aioseop_opengraph_settings_customimg_twitter' => 'twitter-image',
36
+ );
37
+
38
+ /**
39
+ * Array of meta keys to detect and import.
40
  *
41
  * @var array
42
  */
70
  $status = parent::import();
71
  if ( $status ) {
72
  $this->import_opengraph();
 
73
  }
74
+ return $status;
75
  }
76
 
77
  /**
100
  $meta = get_post_meta( $post_id, '_aioseop_opengraph_settings', true );
101
  $meta = maybe_unserialize( $meta );
102
 
103
+ foreach ( $this->import_keys as $old_key => $new_key ) {
 
 
 
 
 
 
 
104
  $this->maybe_save_post_meta( $new_key, $meta[ $old_key ], $post_id );
105
  }
106
  }
admin/import/plugins/class-import-greg-high-performance-seo.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File with the class to handle data from Ultimate SEO.
4
+ *
5
+ * @package WPSEO\Admin\Import\Plugins
6
+ */
7
+
8
+ /**
9
+ * Class with functionality to import & clean Ultimate SEO post metadata.
10
+ */
11
+ class WPSEO_Import_Greg_SEO extends WPSEO_Plugin_Importer {
12
+ /**
13
+ * The plugin name.
14
+ *
15
+ * @var string
16
+ */
17
+ protected $plugin_name = "Greg's High Performance SEO";
18
+
19
+ /**
20
+ * Meta key, used in SQL LIKE clause for delete query.
21
+ *
22
+ * @var string
23
+ */
24
+ protected $meta_key = '_ghpseo_%';
25
+
26
+ /**
27
+ * Array of meta keys to detect and import.
28
+ *
29
+ * @var array
30
+ */
31
+ protected $clone_keys = array(
32
+ array(
33
+ 'old_key' => '_ghpseo_alternative_description',
34
+ 'new_key' => 'metadesc',
35
+ ),
36
+ array(
37
+ 'old_key' => '_ghpseo_secondary_title',
38
+ 'new_key' => 'title',
39
+ ),
40
+ );
41
+
42
+ }
admin/import/plugins/class-import-headspace.php CHANGED
@@ -19,14 +19,14 @@ class WPSEO_Import_HeadSpace extends WPSEO_Plugin_Importer {
19
  protected $plugin_name = 'HeadSpace SEO';
20
 
21
  /**
22
- * Meta key, used in SQL LIKE clause for detect query.
23
  *
24
  * @var string
25
  */
26
  protected $meta_key = '_headspace_%';
27
 
28
  /**
29
- * The arrays of keys to clone into Yoast SEO.
30
  *
31
  * @var array
32
  */
19
  protected $plugin_name = 'HeadSpace SEO';
20
 
21
  /**
22
+ * Meta key, used in SQL LIKE clause for delete query.
23
  *
24
  * @var string
25
  */
26
  protected $meta_key = '_headspace_%';
27
 
28
  /**
29
+ * Array of meta keys to detect and import.
30
  *
31
  * @var array
32
  */
admin/import/plugins/class-import-jetpack.php CHANGED
@@ -19,14 +19,14 @@ class WPSEO_Import_Jetpack_SEO extends WPSEO_Plugin_Importer {
19
  protected $plugin_name = 'Jetpack';
20
 
21
  /**
22
- * Meta key, used in SQL LIKE clause for detect query.
23
  *
24
  * @var string
25
  */
26
  protected $meta_key = 'advanced_seo_description';
27
 
28
  /**
29
- * The arrays of keys to clone into Yoast SEO.
30
  *
31
  * @var array
32
  */
19
  protected $plugin_name = 'Jetpack';
20
 
21
  /**
22
+ * Meta key, used in SQL LIKE clause for delete query.
23
  *
24
  * @var string
25
  */
26
  protected $meta_key = 'advanced_seo_description';
27
 
28
  /**
29
+ * Array of meta keys to detect and import.
30
  *
31
  * @var array
32
  */
admin/import/plugins/class-import-platinum-seo-pack.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File with the class to handle data from Platinum SEO Pack.
4
+ *
5
+ * @package WPSEO\Admin\Import\Plugins
6
+ */
7
+
8
+ /**
9
+ * Class with functionality to import & clean Ultimate SEO post metadata.
10
+ */
11
+ class WPSEO_Import_Platinum_SEO extends WPSEO_Plugin_Importer {
12
+ /**
13
+ * The plugin name.
14
+ *
15
+ * @var string
16
+ */
17
+ protected $plugin_name = 'Platinum SEO Pack';
18
+
19
+ /**
20
+ * Meta key, used in SQL LIKE clause for delete query.
21
+ *
22
+ * @var string
23
+ */
24
+ protected $meta_key = 'title';
25
+
26
+ /**
27
+ * Array of meta keys to detect and import.
28
+ *
29
+ * @var array
30
+ */
31
+ protected $clone_keys = array(
32
+ array(
33
+ 'old_key' => 'description',
34
+ 'new_key' => 'metadesc',
35
+ ),
36
+ array(
37
+ 'old_key' => 'title',
38
+ 'new_key' => 'title',
39
+ ),
40
+ );
41
+
42
+ /**
43
+ * Runs the import of post meta keys stored by Platinum SEO Pack.
44
+ *
45
+ * @return bool
46
+ */
47
+ protected function import() {
48
+ $return = parent::import();
49
+ if ( $return ) {
50
+ $this->import_robots_meta();
51
+ }
52
+
53
+ return $return;
54
+ }
55
+
56
+ /**
57
+ * Cleans up all the meta values Platinum SEO pack creates.
58
+ *
59
+ * @return bool
60
+ */
61
+ protected function cleanup() {
62
+ $this->meta_key = 'title';
63
+ parent::cleanup();
64
+
65
+ $this->meta_key = 'description';
66
+ parent::cleanup();
67
+
68
+ $this->meta_key = 'metarobots';
69
+ parent::cleanup();
70
+
71
+ return true;
72
+ }
73
+
74
+ /**
75
+ * Finds all the robotsmeta fields to import and deals with them.
76
+ *
77
+ * There are four potential values that Platinum SEO stores:
78
+ * - index,folllow
79
+ * - index,nofollow
80
+ * - noindex,follow
81
+ * - noindex,nofollow
82
+ *
83
+ * We only have to deal with the latter 3, the first is our default.
84
+ *
85
+ * @return void
86
+ */
87
+ protected function import_robots_meta() {
88
+ $this->import_by_meta_robots( 'index,nofollow', array( 'nofollow' ) );
89
+ $this->import_by_meta_robots( 'noindex,follow', array( 'noindex' ) );
90
+ $this->import_by_meta_robots( 'noindex,nofollow', array( 'noindex', 'nofollow' ) );
91
+ }
92
+
93
+ /**
94
+ * Imports the values for all index, nofollow posts.
95
+ *
96
+ * @param string $value The meta robots value to find posts for.
97
+ * @param array $metas The meta field(s) to save.
98
+ *
99
+ * @return void
100
+ */
101
+ protected function import_by_meta_robots( $value, $metas ) {
102
+ $posts = $this->find_posts_by_robots_meta( $value );
103
+ if ( ! $posts ) {
104
+ return;
105
+ }
106
+
107
+ foreach ( $posts as $post_id ) {
108
+ foreach ( $metas as $meta ) {
109
+ $this->maybe_save_post_meta( 'meta-robots-' . $meta, 1, $post_id );
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Finds posts by a given meta robots value.
116
+ *
117
+ * @param string $meta_value Robots meta value.
118
+ *
119
+ * @return array|bool Array of Post IDs on success, false on failure.
120
+ */
121
+ protected function find_posts_by_robots_meta( $meta_value ) {
122
+ $posts = get_posts(
123
+ array(
124
+ 'post_type' => 'any',
125
+ 'meta_key' => 'robotsmeta',
126
+ 'meta_value' => $meta_value,
127
+ 'order' => 'ASC',
128
+ 'fields' => 'ids',
129
+ 'nopaging' => true,
130
+ )
131
+ );
132
+ if ( empty( $posts ) ) {
133
+ return false;
134
+ }
135
+ return $posts;
136
+ }
137
+
138
+ }
admin/import/plugins/class-import-premium-seo-pack.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File with the class to handle data from Premium SEO Pack.
4
+ *
5
+ * @package WPSEO\Admin\Import\Plugins
6
+ */
7
+
8
+ /**
9
+ * Class with functionality to import & clean Premium SEO Pack post metadata.
10
+ */
11
+ class WPSEO_Import_Premium_SEO_Pack extends WPSEO_Import_Squirrly {
12
+ /**
13
+ * The plugin name.
14
+ *
15
+ * @var string
16
+ */
17
+ protected $plugin_name = 'Premium SEO Pack';
18
+
19
+ /**
20
+ * WPSEO_Import_Premium_SEO_Pack constructor.
21
+ */
22
+ public function __construct() {
23
+ parent::__construct();
24
+
25
+ global $wpdb;
26
+ $this->table_name = $wpdb->prefix . 'psp';
27
+ $this->meta_key = '';
28
+ }
29
+
30
+ /**
31
+ * Returns the query to return an identifier for the posts to import.
32
+ *
33
+ * @return string
34
+ */
35
+ protected function retrieve_posts_query() {
36
+ return "SELECT URL AS identifier FROM {$this->table_name} WHERE blog_id = %d";
37
+ }
38
+
39
+ }
admin/import/plugins/class-import-seo-framework.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File with the class to handle data from SEO Framework.
4
+ *
5
+ * @package WPSEO\Admin\Import\Plugins
6
+ */
7
+
8
+ /**
9
+ * Class with functionality to import & clean SEO Framework post metadata.
10
+ */
11
+ class WPSEO_Import_SEO_Framework extends WPSEO_Plugin_Importer {
12
+ /**
13
+ * The plugin name.
14
+ *
15
+ * @var string
16
+ */
17
+ protected $plugin_name = 'SEO Framework';
18
+
19
+ /**
20
+ * Meta key, used in SQL LIKE clause for delete query.
21
+ *
22
+ * @var string
23
+ */
24
+ protected $meta_key = '_genesis_%';
25
+
26
+ /**
27
+ * Array of meta keys to detect and import.
28
+ *
29
+ * @var array
30
+ */
31
+ protected $clone_keys = array(
32
+ array(
33
+ 'old_key' => '_genesis_description',
34
+ 'new_key' => 'metadesc',
35
+ ),
36
+ array(
37
+ 'old_key' => '_genesis_title',
38
+ 'new_key' => 'title',
39
+ ),
40
+ array(
41
+ 'old_key' => '_genesis_noindex',
42
+ 'new_key' => 'meta-robots-noindex',
43
+ ),
44
+ array(
45
+ 'old_key' => '_genesis_nofollow',
46
+ 'new_key' => 'meta-robots-nofollow',
47
+ ),
48
+ array(
49
+ 'old_key' => '_genesis_canonical_uri',
50
+ 'new_key' => 'canonical',
51
+ ),
52
+ array(
53
+ 'old_key' => '_open_graph_title',
54
+ 'new_key' => 'opengraph-title',
55
+ ),
56
+ array(
57
+ 'old_key' => '_open_graph_description',
58
+ 'new_key' => 'opengraph-description',
59
+ ),
60
+ array(
61
+ 'old_key' => '_social_image_url',
62
+ 'new_key' => 'opengraph-image',
63
+ ),
64
+ array(
65
+ 'old_key' => '_twitter_title',
66
+ 'new_key' => 'twitter-title',
67
+ ),
68
+ array(
69
+ 'old_key' => '_twitter_description',
70
+ 'new_key' => 'twitter-description',
71
+ ),
72
+ );
73
+
74
+ /**
75
+ * Removes all the metadata set by the SEO Framework plugin.
76
+ *
77
+ * @return bool
78
+ */
79
+ protected function cleanup() {
80
+ $set1 = parent::cleanup();
81
+
82
+ $this->meta_key = '_social_image_%';
83
+ $set2 = parent::cleanup();
84
+
85
+ $this->meta_key = '_twitter_%';
86
+ $set3 = parent::cleanup();
87
+
88
+ $this->meta_key = '_open_graph_%';
89
+ $set4 = parent::cleanup();
90
+
91
+ return ( $set1 || $set2 || $set3 || $set4 );
92
+ }
93
+ }
admin/import/plugins/class-import-seopressor.php CHANGED
@@ -19,12 +19,23 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer {
19
  protected $plugin_name = 'SEOpressor';
20
 
21
  /**
22
- * Meta key, used in SQL LIKE clause for detect query.
23
  *
24
  * @var string
25
  */
26
  protected $meta_key = '_seop_settings';
27
 
 
 
 
 
 
 
 
 
 
 
 
28
  /**
29
  * Imports the post meta values to Yoast SEO.
30
  *
@@ -84,22 +95,6 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer {
84
  }
85
  }
86
 
87
- /**
88
- * Represents the Helper function to store the meta value should it be set in SEOPressor's settings.
89
- *
90
- * @param string $seo_pressor_key The key in the SEOPressor array.
91
- * @param string $yoast_key The identifier we use in our meta settings.
92
- * @param array $seopressor_settings The array of settings for this post in SEOpressor.
93
- * @param int $post_id The post ID.
94
- *
95
- * @return void
96
- */
97
- private function import_meta_helper( $seo_pressor_key, $yoast_key, $seopressor_settings, $post_id ) {
98
- if ( ! empty( $seopressor_settings[ $seo_pressor_key ] ) ) {
99
- $this->maybe_save_post_meta( $yoast_key, $seopressor_settings[ $seo_pressor_key ], $post_id );
100
- }
101
- }
102
-
103
  /**
104
  * Imports the focus keywords, and stores them for later use.
105
  *
19
  protected $plugin_name = 'SEOpressor';
20
 
21
  /**
22
+ * Meta key, used in SQL LIKE clause for delete query.
23
  *
24
  * @var string
25
  */
26
  protected $meta_key = '_seop_settings';
27
 
28
+ /**
29
+ * Array of meta keys to detect and import.
30
+ *
31
+ * @var array
32
+ */
33
+ protected $clone_keys = array(
34
+ array(
35
+ 'old_key' => '_seop_settings',
36
+ ),
37
+ );
38
+
39
  /**
40
  * Imports the post meta values to Yoast SEO.
41
  *
95
  }
96
  }
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  /**
99
  * Imports the focus keywords, and stores them for later use.
100
  *
admin/import/plugins/class-import-smartcrawl.php ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File with the class to handle data from Smartcrawl SEO.
4
+ *
5
+ * @package WPSEO\Admin\Import\Plugins
6
+ */
7
+
8
+ /**
9
+ * Class with functionality to import & clean Smartcrawl SEO post metadata.
10
+ */
11
+ class WPSEO_Import_Smartcrawl_SEO extends WPSEO_Plugin_Importer {
12
+ /**
13
+ * The plugin name.
14
+ *
15
+ * @var string
16
+ */
17
+ protected $plugin_name = 'Smartcrawl SEO';
18
+
19
+ /**
20
+ * Meta key, used in SQL LIKE clause for delete query.
21
+ *
22
+ * @var string
23
+ */
24
+ protected $meta_key = '_wds_%';
25
+
26
+ /**
27
+ * Array of meta keys to detect and import.
28
+ *
29
+ * @var array
30
+ */
31
+ protected $clone_keys = array(
32
+ array(
33
+ 'old_key' => '_wds_metadesc',
34
+ 'new_key' => 'metadesc',
35
+ ),
36
+ array(
37
+ 'old_key' => '_wds_title',
38
+ 'new_key' => 'title',
39
+ ),
40
+ array(
41
+ 'old_key' => '_wds_canonical',
42
+ 'new_key' => 'canonical',
43
+ ),
44
+ array(
45
+ 'old_key' => '_wds_focus-keywords',
46
+ 'new_key' => 'focuskw',
47
+ ),
48
+ array(
49
+ 'old_key' => '_wds_meta-robots-noindex',
50
+ 'new_key' => 'meta-robots-noindex',
51
+ ),
52
+ array(
53
+ 'old_key' => '_wds_meta-robots-nofollow',
54
+ 'new_key' => 'meta-robots-nofollow',
55
+ ),
56
+ );
57
+
58
+ /**
59
+ * Used for importing Twitter and Facebook meta's.
60
+ *
61
+ * @var array
62
+ */
63
+ protected $social_keys = array();
64
+
65
+ /**
66
+ * Handles post meta data to import.
67
+ *
68
+ * @return bool Import success status.
69
+ */
70
+ protected function import() {
71
+ $return = parent::import();
72
+ if ( $return ) {
73
+ $this->import_opengraph();
74
+ $this->import_twitter();
75
+ }
76
+
77
+ return $return;
78
+ }
79
+
80
+ /**
81
+ * Imports the OpenGraph meta keys saved by Smartcrawl.
82
+ *
83
+ * @return bool Import status.
84
+ */
85
+ protected function import_opengraph() {
86
+ $this->social_keys = array(
87
+ 'title' => 'opengraph-title',
88
+ 'description' => 'opengraph-description',
89
+ 'images' => 'opengraph-image',
90
+ );
91
+ return $this->post_find_import( '_wds_opengraph' );
92
+ }
93
+
94
+ /**
95
+ * Imports the Twitter meta keys saved by Smartcrawl.
96
+ *
97
+ * @return bool Import status.
98
+ */
99
+ protected function import_twitter() {
100
+ $this->social_keys = array(
101
+ 'title' => 'twitter-title',
102
+ 'description' => 'twitter-description',
103
+ );
104
+ return $this->post_find_import( '_wds_twitter' );
105
+ }
106
+
107
+ /**
108
+ * Imports a post's serialized post meta values.
109
+ *
110
+ * @param int $post_id Post ID.
111
+ * @param string $key The meta key to import.
112
+ *
113
+ * @return void
114
+ */
115
+ protected function import_serialized_post_meta( $post_id, $key ) {
116
+ $data = get_post_meta( $post_id, $key, true );
117
+ $data = maybe_unserialize( $data );
118
+ foreach ( $this->social_keys as $key => $meta_key ) {
119
+ if ( ! isset( $data[ $key ] ) ) {
120
+ return;
121
+ }
122
+ $value = $data[ $key ];
123
+ if ( is_array( $value ) ) {
124
+ $value = $value[0];
125
+ }
126
+ $this->maybe_save_post_meta( $meta_key, $value, $post_id );
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Finds all the posts with a certain meta key and imports its values.
132
+ *
133
+ * @param string $key The meta key to search for.
134
+ *
135
+ * @return bool Import status.
136
+ */
137
+ protected function post_find_import( $key ) {
138
+ $query_posts = new WP_Query( 'post_type=any&meta_key=' . $key . '&order=ASC&fields=ids&nopaging=true' );
139
+
140
+ if ( empty( $query_posts->posts ) ) {
141
+ return false;
142
+ }
143
+
144
+ foreach ( array_values( $query_posts->posts ) as $post_id ) {
145
+ $this->import_serialized_post_meta( $post_id, $key );
146
+ }
147
+
148
+ return true;
149
+ }
150
+ }
admin/import/plugins/class-import-squirrly.php ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File with the class to handle data from Squirrly.
4
+ *
5
+ * @package WPSEO\Admin\Import\Plugins
6
+ */
7
+
8
+ /**
9
+ * Class with functionality to import & clean Squirrly post metadata.
10
+ */
11
+ class WPSEO_Import_Squirrly extends WPSEO_Plugin_Importer {
12
+ /**
13
+ * The plugin name.
14
+ *
15
+ * @var string
16
+ */
17
+ protected $plugin_name = 'Squirrly SEO';
18
+
19
+ /**
20
+ * Holds the name of the table Squirrly uses to store data.
21
+ *
22
+ * @var string
23
+ */
24
+ protected $table_name;
25
+
26
+ /**
27
+ * Meta key, used in SQL LIKE clause for delete query.
28
+ *
29
+ * @var string
30
+ */
31
+ protected $meta_key = '_sq_post_keyword';
32
+
33
+ /**
34
+ * Data to import from (and the target to field) the serialized array stored in the SEO field in the Squirrly table.
35
+ *
36
+ * @var array
37
+ */
38
+ protected $seo_field_keys = array(
39
+ 'noindex' => 'meta-robots-noindex',
40
+ 'nofollow' => 'meta-robots-nofollow',
41
+ 'title' => 'title',
42
+ 'description' => 'metadesc',
43
+ 'canonical' => 'canonical',
44
+ 'cornerstone' => '_yst_is_cornerstone',
45
+ 'tw_media' => 'twitter-image',
46
+ 'tw_title' => 'twitter-title',
47
+ 'tw_description' => 'twitter-description',
48
+ 'og_title' => 'opengraph-title',
49
+ 'og_description' => 'opengraph-description',
50
+ 'og_media' => 'opengraph-image',
51
+ 'focuskw' => 'focuskw',
52
+ );
53
+
54
+ /**
55
+ * WPSEO_Import_Squirrly constructor.
56
+ */
57
+ public function __construct() {
58
+ parent::__construct();
59
+
60
+ global $wpdb;
61
+ $this->table_name = $wpdb->prefix . 'qss';
62
+ }
63
+
64
+ /**
65
+ * Imports the post meta values to Yoast SEO.
66
+ *
67
+ * @return bool Import success status.
68
+ */
69
+ protected function import() {
70
+ $results = $this->retrieve_posts();
71
+ foreach ( $results as $post ) {
72
+ $return = $this->import_post_values( $post->identifier );
73
+ if ( ! $return ) {
74
+ return false;
75
+ }
76
+ }
77
+
78
+ return true;
79
+ }
80
+
81
+ /**
82
+ * Retrieve the posts from the Squirrly Database.
83
+ *
84
+ * @return array Array of post IDs from the DB.
85
+ */
86
+ protected function retrieve_posts() {
87
+ global $wpdb;
88
+ return $wpdb->get_results(
89
+ $wpdb->prepare(
90
+ $this->retrieve_posts_query(),
91
+ get_current_blog_id()
92
+ )
93
+ );
94
+ }
95
+
96
+ /**
97
+ * Returns the query to return an identifier for the posts to import.
98
+ *
99
+ * @return string Query to get post ID's from the DB.
100
+ */
101
+ protected function retrieve_posts_query() {
102
+ return "SELECT post_id AS identifier FROM {$this->table_name} WHERE blog_id = %d";
103
+ }
104
+
105
+ /**
106
+ * Removes the DB table and the post meta field Squirrly creates.
107
+ *
108
+ * @return bool Cleanup status.
109
+ */
110
+ protected function cleanup() {
111
+ global $wpdb;
112
+
113
+ // If we can clean, let's clean.
114
+ $wpdb->query( "DROP TABLE {$this->table_name}" );
115
+
116
+ // This removes the post meta field for the focus keyword from the DB.
117
+ parent::cleanup();
118
+
119
+ // If we can still see the table, something went wrong.
120
+ if ( $this->detect() ) {
121
+ $this->cleanup_error_msg();
122
+ return false;
123
+ }
124
+
125
+ return true;
126
+ }
127
+
128
+ /**
129
+ * Detects whether there is post meta data to import.
130
+ *
131
+ * @return bool Boolean indicating whether there is something to import.
132
+ */
133
+ protected function detect() {
134
+ global $wpdb;
135
+
136
+ $result = $wpdb->get_var( "SHOW TABLES LIKE '{$this->table_name}'" );
137
+ if ( is_wp_error( $result ) || is_null( $result ) ) {
138
+ return false;
139
+ }
140
+
141
+ return true;
142
+ }
143
+
144
+ /**
145
+ * Imports the data of a post out of Squirrly's DB table.
146
+ *
147
+ * @param mixed $post_identifier Post identifier, can be ID or string.
148
+ *
149
+ * @return bool Import status.
150
+ */
151
+ private function import_post_values( $post_identifier ) {
152
+ $data = $this->retrieve_post_data( $post_identifier );
153
+ if ( ! $data ) {
154
+ return false;
155
+ }
156
+
157
+ if ( ! is_numeric( $post_identifier ) ) {
158
+ $post_id = url_to_postid( $post_identifier );
159
+ }
160
+
161
+ if ( is_numeric( $post_identifier ) ) {
162
+ $post_id = (int) $post_identifier;
163
+ $data['focuskw'] = $this->maybe_add_focus_kw( $post_identifier );
164
+ }
165
+
166
+ foreach ( $this->seo_field_keys as $squirrly_key => $yoast_key ) {
167
+ $this->import_meta_helper( $squirrly_key, $yoast_key, $data, $post_id );
168
+ }
169
+ return true;
170
+ }
171
+
172
+ /**
173
+ * Retrieves the Squirrly SEO data for a post from the DB.
174
+ *
175
+ * @param int $post_identifier Post ID.
176
+ *
177
+ * @return array|bool Array of data or false.
178
+ */
179
+ private function retrieve_post_data( $post_identifier ) {
180
+ global $wpdb;
181
+
182
+ if ( is_numeric( $post_identifier ) ) {
183
+ $post_identifier = (int) $post_identifier;
184
+ $query_where = 'post_id = %d';
185
+ }
186
+ if ( ! is_numeric( $post_identifier ) ) {
187
+ $query_where = 'URL = %s';
188
+ }
189
+ $data = $wpdb->get_var(
190
+ $wpdb->prepare(
191
+ "SELECT seo FROM {$this->table_name} WHERE blog_id = %d AND " . $query_where,
192
+ get_current_blog_id(),
193
+ $post_identifier
194
+ )
195
+ );
196
+ if ( ! $data || is_wp_error( $data ) ) {
197
+ return false;
198
+ }
199
+ $data = maybe_unserialize( $data );
200
+ return $data;
201
+ }
202
+
203
+ /**
204
+ * Squirrly stores the focus keyword in post meta.
205
+ *
206
+ * @param int $post_id Post ID.
207
+ *
208
+ * @return string The focus keyword.
209
+ */
210
+ private function maybe_add_focus_kw( $post_id ) {
211
+ $focuskw = get_post_meta( $post_id, '_sq_post_keyword', true );
212
+ if ( $focuskw ) {
213
+ $focuskw = json_decode( $focuskw );
214
+ return $focuskw->keyword;
215
+ }
216
+ return '';
217
+ }
218
+ }
admin/import/plugins/class-import-ultimate-seo.php CHANGED
@@ -17,14 +17,14 @@ class WPSEO_Import_Ultimate_SEO extends WPSEO_Plugin_Importer {
17
  protected $plugin_name = 'Ultimate SEO';
18
 
19