Yoast SEO - Version 9.2

Version Description

Download this release

Release Info

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

Code changes from version 9.1 to 9.2

Files changed (77) hide show
  1. admin/class-admin-asset-manager.php +150 -130
  2. admin/class-admin-init.php +1 -1
  3. admin/class-admin.php +6 -4
  4. admin/class-bulk-editor-list-table.php +11 -11
  5. admin/class-config.php +0 -34
  6. admin/class-export.php +20 -151
  7. admin/class-extension.php +9 -0
  8. admin/class-extensions.php +0 -5
  9. admin/class-gutenberg-compatibility.php +2 -2
  10. admin/class-premium-popup.php +7 -3
  11. admin/class-premium-upsell-admin-block.php +4 -2
  12. admin/class-yoast-modal.php +0 -97
  13. admin/config-ui/class-configuration-page.php +1 -0
  14. admin/config-ui/class-configuration-service.php +1 -3
  15. admin/google_search_console/class-gsc-category-filters.php +5 -2
  16. admin/import/class-import-settings.php +31 -135
  17. admin/metabox/class-metabox-keyword-synonyms-config.php +0 -41
  18. admin/metabox/class-metabox-multiple-keywords-config.php +0 -41
  19. admin/metabox/class-metabox.php +4 -1
  20. admin/onpage/class-ryte-service.php +3 -0
  21. admin/statistics/class-statistics-service.php +5 -2
  22. admin/taxonomy/class-taxonomy.php +1 -0
  23. admin/views/licenses.php +95 -86
  24. admin/views/sidebar.php +2 -0
  25. admin/views/tabs/tool/wpseo-export.php +9 -2
  26. admin/views/tabs/tool/wpseo-import.php +11 -11
  27. admin/views/tool-import-export.php +2 -3
  28. admin/views/user-profile.php +2 -0
  29. admin/watchers/class-slug-change-watcher.php +8 -2
  30. css/dist/admin-global-910-rtl.min.css +0 -1
  31. css/dist/admin-global-910.min.css +0 -1
  32. css/dist/admin-global-920-rtl.min.css +1 -0
  33. css/dist/admin-global-920.min.css +1 -0
  34. css/dist/{adminbar-910-rtl.min.css → adminbar-920-rtl.min.css} +0 -0
  35. css/dist/{adminbar-910.min.css → adminbar-920.min.css} +0 -0
  36. css/dist/{alerts-910-rtl.min.css → alerts-920-rtl.min.css} +0 -0
  37. css/dist/{alerts-910.min.css → alerts-920.min.css} +0 -0
  38. css/dist/{dashboard-910-rtl.min.css → dashboard-920-rtl.min.css} +0 -0
  39. css/dist/{dashboard-910.min.css → dashboard-920.min.css} +0 -0
  40. css/dist/{edit-page-910-rtl.min.css → edit-page-920-rtl.min.css} +0 -0
  41. css/dist/{edit-page-910.min.css → edit-page-920.min.css} +0 -0
  42. css/dist/{featured-image-910-rtl.min.css → featured-image-920-rtl.min.css} +0 -0
  43. css/dist/{featured-image-910.min.css → featured-image-920.min.css} +0 -0
  44. css/dist/{filter-explanation-910-rtl.min.css → filter-explanation-920-rtl.min.css} +0 -0
  45. css/dist/{filter-explanation-910.min.css → filter-explanation-920.min.css} +0 -0
  46. css/dist/{inside-editor-910-rtl.min.css → inside-editor-920-rtl.min.css} +0 -0
  47. css/dist/{inside-editor-910.min.css → inside-editor-920.min.css} +0 -0
  48. css/dist/{metabox-910-rtl.min.css → metabox-920-rtl.min.css} +1 -1
  49. css/dist/{metabox-910.min.css → metabox-920.min.css} +1 -1
  50. css/dist/{metabox-primary-category-910-rtl.min.css → metabox-primary-category-920-rtl.min.css} +0 -0
  51. css/dist/{metabox-primary-category-910.min.css → metabox-primary-category-920.min.css} +0 -0
  52. css/dist/{search-appearance-910-rtl.min.css → search-appearance-920-rtl.min.css} +0 -0
  53. css/dist/{search-appearance-910.min.css → search-appearance-920.min.css} +0 -0
  54. css/dist/{structured-data-blocks-910-rtl.min.css → structured-data-blocks-920-rtl.min.css} +0 -0
  55. css/dist/{structured-data-blocks-910.min.css → structured-data-blocks-920.min.css} +0 -0
  56. css/dist/{toggle-switch-910-rtl.min.css → toggle-switch-920-rtl.min.css} +0 -0
  57. css/dist/{toggle-switch-910.min.css → toggle-switch-920.min.css} +0 -0
  58. css/dist/{wpseo-dismissible-910-rtl.min.css → wpseo-dismissible-920-rtl.min.css} +0 -0
  59. css/dist/{wpseo-dismissible-910.min.css → wpseo-dismissible-920.min.css} +0 -0
  60. css/dist/{yoast-components-910-rtl.min.css → yoast-components-920-rtl.min.css} +0 -0
  61. css/dist/{yoast-components-910.min.css → yoast-components-920.min.css} +0 -0
  62. css/dist/yoast-extensions-910-rtl.min.css +0 -1
  63. css/dist/yoast-extensions-910.min.css +0 -1
  64. css/dist/yoast-extensions-920-rtl.min.css +1 -0
  65. css/dist/yoast-extensions-920.min.css +1 -0
  66. css/dist/{yst_plugin_tools-910-rtl.min.css → yst_plugin_tools-920-rtl.min.css} +0 -0
  67. css/dist/{yst_plugin_tools-910.min.css → yst_plugin_tools-920.min.css} +0 -0
  68. css/dist/{yst_seo_score-910-rtl.min.css → yst_seo_score-920-rtl.min.css} +0 -0
  69. css/dist/{yst_seo_score-910.min.css → yst_seo_score-920.min.css} +0 -0
  70. deprecated/class-yoast-modal.php +79 -0
  71. frontend/class-frontend.php +35 -2
  72. frontend/class-opengraph-oembed.php +71 -0
  73. frontend/class-opengraph.php +18 -4
  74. inc/class-post-type.php +11 -0
  75. inc/class-wpseo-replace-vars.php +9 -1
  76. inc/class-wpseo-utils.php +22 -0
  77. js/dist/analysis-910.min.js +0 -13
admin/class-admin-asset-manager.php CHANGED
@@ -15,11 +15,6 @@ class WPSEO_Admin_Asset_Manager {
15
  */
16
  protected $asset_location;
17
 
18
- /**
19
- * @var array The backport dependencies.
20
- */
21
- protected static $backport_dependencies;
22
-
23
  /**
24
  * Prefix for naming the assets.
25
  */
@@ -173,7 +168,7 @@ class WPSEO_Admin_Asset_Manager {
173
  }
174
 
175
  /**
176
- * Reregisters the globals backport asset with the correct dependencies.
177
  *
178
  * This function can be removed when WordPress 5.1 has been released, because from 5.0 wp-elements will be
179
  * registered earlier, which means we don't have to reregister things.
@@ -181,77 +176,87 @@ class WPSEO_Admin_Asset_Manager {
181
  * @return void
182
  */
183
  public function register_wp_assets() {
184
- // The dependencies that are registered on 'admin_init'.
185
- $previous_deps = self::$backport_dependencies;
186
 
187
- // The dependencies that are present on 'admin_init'.
188
- $current_deps = $this->get_backport_dependencies();
189
 
190
- /*
191
- * This is false when Gutenberg is active, because in that case Gutenberg's scripts are not registered yet
192
- * on 'admin_init', but they are on 'admin_enqueue_scripts'.
193
- */
194
- if ( $current_deps === $previous_deps ) {
195
- return;
196
- }
197
 
198
- wp_deregister_script( self::PREFIX . 'wp-globals-backport' );
 
 
 
199
 
200
  $flat_version = $this->flatten_version( WPSEO_VERSION );
201
- $args = array(
202
- 'name' => 'wp-globals-backport',
203
- 'src' => 'wp-seo-wp-globals-backport-' . $flat_version,
204
- 'deps' => $current_deps,
 
 
 
 
 
 
 
205
  );
206
 
207
- $script = new WPSEO_Admin_Asset( $args );
208
- $this->register_script( $script );
209
- }
 
 
 
 
210
 
211
- /**
212
- * Gets the correct dependencies for the global backport.
213
- *
214
- * @return array The dependencies for the global backport.
215
- */
216
- protected function get_backport_dependencies() {
217
- $backport_wp_dependencies = array( self::PREFIX . 'react-dependencies' );
218
-
219
- // If Gutenberg is present we can borrow their globals for our own.
220
- if ( $this->should_load_gutenberg_assets() ) {
221
- $backport_wp_dependencies[] = 'wp-element';
222
- $backport_wp_dependencies[] = 'wp-data';
223
- $backport_wp_dependencies[] = 'wp-components';
224
-
225
- /*
226
- * The version of TinyMCE that Gutenberg uses is incompatible with
227
- * the one core uses. So we need to make sure that the core version
228
- * is used in the classic editor.
229
- *
230
- * $_GET is used here because as far as I am aware you cannot use
231
- * filter_input to check for the existence of a query variable.
232
- */
233
- if ( wp_script_is( 'tinymce-latest', 'registered' ) && isset( $_GET['classic-editor'] ) ) {
234
- wp_deregister_script( 'tinymce-latest' );
235
- wp_register_script( 'tinymce-latest', includes_url( 'js/tinymce/' ) . 'wp-tinymce.php', array( 'jquery' ), false, true );
236
- }
237
- }
238
- else {
239
- if ( wp_script_is( 'lodash', 'registered' ) ) {
240
- $backport_wp_dependencies[] = 'lodash';
241
- }
242
- else {
243
- if ( ! wp_script_is( self::PREFIX . 'lodash', 'registered' ) ) {
244
- wp_register_script( self::PREFIX . 'lodash-base', plugins_url( 'js/vendor/lodash.min.js', WPSEO_FILE ), array(), false, true );
245
- wp_register_script( self::PREFIX . 'lodash', plugins_url( 'js/vendor/lodash-noconflict.js', WPSEO_FILE ), array( self::PREFIX . 'lodash-base' ), false, true );
246
- }
247
- $backport_wp_dependencies[] = self::PREFIX . 'lodash';
248
- }
249
- }
250
 
251
- // Save the $backport_dependencies to use in register_wp_assets.
252
- self::$backport_dependencies = $backport_wp_dependencies;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
- return $backport_wp_dependencies;
 
 
 
 
 
 
 
 
255
  }
256
 
257
  /**
@@ -275,41 +280,32 @@ class WPSEO_Admin_Asset_Manager {
275
 
276
  $flat_version = $this->flatten_version( WPSEO_VERSION );
277
 
278
- $backport_wp_dependencies = $this->get_backport_dependencies();
279
-
280
- // If Gutenberg's babel polyfill is not present, use our own.
281
- $babel_polyfill = 'wp-polyfill-ecmascript';
282
- if ( ! wp_script_is( 'wp-polyfill-ecmascript', 'registered' ) ) {
283
- $babel_polyfill = self::PREFIX . 'babel-polyfill';
284
- }
285
-
286
  return array(
287
  array(
288
- 'name' => 'react-dependencies',
289
  // Load webpack-commons for bundle support.
290
  'src' => 'commons-' . $flat_version,
291
- 'deps' => array( $babel_polyfill ),
 
 
292
  ),
293
  array(
294
  'name' => 'search-appearance',
295
  'src' => 'search-appearance-' . $flat_version,
296
  'deps' => array(
297
- self::PREFIX . 'react-dependencies',
298
  self::PREFIX . 'components',
 
299
  ),
300
  ),
301
- array(
302
- 'name' => 'wp-globals-backport',
303
- 'src' => 'wp-seo-wp-globals-backport-' . $flat_version,
304
- 'deps' => $backport_wp_dependencies,
305
- ),
306
  array(
307
  'name' => 'yoast-modal',
308
  'src' => 'wp-seo-modal-' . $flat_version,
309
  'deps' => array(
310
  'jquery',
311
- self::PREFIX . 'wp-globals-backport',
 
312
  self::PREFIX . 'components',
 
313
  ),
314
  ),
315
  array(
@@ -317,8 +313,10 @@ class WPSEO_Admin_Asset_Manager {
317
  'src' => 'wp-seo-help-center-' . $flat_version,
318
  'deps' => array(
319
  'jquery',
320
- self::PREFIX . 'wp-globals-backport',
 
321
  self::PREFIX . 'components',
 
322
  ),
323
  ),
324
  array(
@@ -330,7 +328,7 @@ class WPSEO_Admin_Asset_Manager {
330
  'jquery-ui-progressbar',
331
  self::PREFIX . 'select2',
332
  self::PREFIX . 'select2-translations',
333
- self::PREFIX . 'react-dependencies',
334
  ),
335
  ),
336
  array(
@@ -339,20 +337,23 @@ class WPSEO_Admin_Asset_Manager {
339
  'deps' => array(
340
  'jquery',
341
  'jquery-ui-core',
342
- self::PREFIX . 'react-dependencies',
343
  ),
344
  ),
345
  array(
346
  'name' => 'network-admin-script',
347
  'src' => 'wp-seo-network-admin-' . $flat_version,
348
- 'deps' => array( 'jquery' ),
 
 
 
349
  ),
350
  array(
351
  'name' => 'bulk-editor',
352
  'src' => 'wp-seo-bulk-editor-' . $flat_version,
353
  'deps' => array(
354
  'jquery',
355
- self::PREFIX . 'react-dependencies',
356
  ),
357
  ),
358
  array(
@@ -360,7 +361,7 @@ class WPSEO_Admin_Asset_Manager {
360
  'src' => 'wp-seo-admin-global-' . $flat_version,
361
  'deps' => array(
362
  'jquery',
363
- self::PREFIX . 'react-dependencies',
364
  ),
365
  ),
366
  array(
@@ -368,9 +369,13 @@ class WPSEO_Admin_Asset_Manager {
368
  'src' => 'wp-seo-metabox-' . $flat_version,
369
  'deps' => array(
370
  'jquery',
 
 
 
 
371
  self::PREFIX . 'select2',
372
  self::PREFIX . 'select2-translations',
373
- self::PREFIX . 'wp-globals-backport',
374
  ),
375
  'in_footer' => false,
376
  ),
@@ -379,14 +384,14 @@ class WPSEO_Admin_Asset_Manager {
379
  'src' => 'wp-seo-featured-image-' . $flat_version,
380
  'deps' => array(
381
  'jquery',
382
- self::PREFIX . 'react-dependencies',
383
  ),
384
  ),
385
  array(
386
  'name' => 'admin-gsc',
387
  'src' => 'wp-seo-admin-gsc-' . $flat_version,
388
  'deps' => array(
389
- self::PREFIX . 'react-dependencies',
390
  ),
391
  'in_footer' => false,
392
  ),
@@ -394,41 +399,53 @@ class WPSEO_Admin_Asset_Manager {
394
  'name' => 'post-scraper',
395
  'src' => 'wp-seo-post-scraper-' . $flat_version,
396
  'deps' => array(
397
- self::PREFIX . 'replacevar-plugin',
398
- self::PREFIX . 'shortcode-plugin',
399
  'wp-util',
400
  'wp-api',
401
- self::PREFIX . 'wp-globals-backport',
 
 
 
 
 
 
 
 
402
  self::PREFIX . 'analysis',
403
- self::PREFIX . 'react-dependencies',
404
  self::PREFIX . 'components',
 
405
  ),
406
  ),
407
  array(
408
  'name' => 'term-scraper',
409
  'src' => 'wp-seo-term-scraper-' . $flat_version,
410
  'deps' => array(
 
 
 
 
 
 
411
  self::PREFIX . 'replacevar-plugin',
412
- self::PREFIX . 'wp-globals-backport',
413
  self::PREFIX . 'analysis',
414
  self::PREFIX . 'components',
 
415
  ),
416
  ),
417
  array(
418
  'name' => 'replacevar-plugin',
419
  'src' => 'wp-seo-replacevar-plugin-' . $flat_version,
420
  'deps' => array(
421
- self::PREFIX . 'react-dependencies',
422
  self::PREFIX . 'analysis',
423
  self::PREFIX . 'components',
 
424
  ),
425
  ),
426
  array(
427
  'name' => 'shortcode-plugin',
428
  'src' => 'wp-seo-shortcode-plugin-' . $flat_version,
429
  'deps' => array(
430
- self::PREFIX . 'react-dependencies',
431
  self::PREFIX . 'analysis',
 
432
  ),
433
  ),
434
  array(
@@ -439,7 +456,7 @@ class WPSEO_Admin_Asset_Manager {
439
  'jquery-ui-core',
440
  'jquery-ui-progressbar',
441
  self::PREFIX . 'analysis',
442
- self::PREFIX . 'react-dependencies',
443
  ),
444
  ),
445
  array(
@@ -448,8 +465,11 @@ class WPSEO_Admin_Asset_Manager {
448
  'deps' => array(
449
  'jquery',
450
  'wp-util',
451
- self::PREFIX . 'react-dependencies',
452
- self::PREFIX . 'wp-globals-backport',
 
 
 
453
  ),
454
  ),
455
  array(
@@ -476,8 +496,10 @@ class WPSEO_Admin_Asset_Manager {
476
  'src' => 'configuration-wizard-' . $flat_version,
477
  'deps' => array(
478
  'jquery',
479
- self::PREFIX . 'wp-globals-backport',
 
480
  self::PREFIX . 'components',
 
481
  ),
482
  ),
483
  array(
@@ -487,7 +509,7 @@ class WPSEO_Admin_Asset_Manager {
487
  'jquery',
488
  'jquery-ui-core',
489
  'jquery-ui-progressbar',
490
- self::PREFIX . 'react-dependencies',
491
  ),
492
  ),
493
  array(
@@ -495,7 +517,7 @@ class WPSEO_Admin_Asset_Manager {
495
  'src' => 'wp-seo-edit-page-' . $flat_version,
496
  'deps' => array(
497
  'jquery',
498
- self::PREFIX . 'react-dependencies',
499
  ),
500
  ),
501
  array(
@@ -503,7 +525,7 @@ class WPSEO_Admin_Asset_Manager {
503
  'src' => 'wp-seo-quick-edit-handler-' . $flat_version,
504
  'deps' => array(
505
  'jquery',
506
- self::PREFIX . 'react-dependencies',
507
  ),
508
  'in_footer' => true,
509
  ),
@@ -513,7 +535,7 @@ class WPSEO_Admin_Asset_Manager {
513
  'deps' => array(
514
  'wp-api',
515
  'jquery',
516
- self::PREFIX . 'react-dependencies',
517
  ),
518
  ),
519
  array(
@@ -522,8 +544,10 @@ class WPSEO_Admin_Asset_Manager {
522
  'deps' => array(
523
  self::PREFIX . 'api',
524
  'jquery',
525
- self::PREFIX . 'wp-globals-backport',
 
526
  self::PREFIX . 'components',
 
527
  ),
528
  ),
529
  array(
@@ -531,29 +555,40 @@ class WPSEO_Admin_Asset_Manager {
531
  'src' => 'wp-seo-filter-explanation-' . $flat_version,
532
  'deps' => array(
533
  'jquery',
534
- self::PREFIX . 'react-dependencies',
535
  ),
536
  ),
537
  array(
538
  'name' => 'analysis',
539
  'src' => 'analysis-' . $flat_version,
540
  'deps' => array(
541
- self::PREFIX . 'react-dependencies',
 
542
  ),
543
  ),
544
  array(
545
  'name' => 'components',
546
  'src' => 'components-' . $flat_version,
547
- 'deps' => array( self::PREFIX . 'analysis' ),
 
 
 
 
548
  ),
549
  array(
550
  'name' => 'structured-data-blocks',
551
  'src' => 'wp-seo-structured-data-blocks-' . $flat_version,
552
- 'deps' => array( 'wp-blocks', 'wp-i18n', 'wp-element' ),
 
 
 
 
 
 
553
  ),
554
  array(
555
- 'name' => 'babel-polyfill',
556
- 'src' => 'babel-polyfill-' . $flat_version,
557
  ),
558
  );
559
  }
@@ -651,19 +686,4 @@ class WPSEO_Admin_Asset_Manager {
651
  ),
652
  );
653
  }
654
-
655
- /**
656
- * Checks if the Gutenberg assets must be loaded.
657
- *
658
- * @return bool True when the Gutenberg assets must be loaded.
659
- */
660
- protected function should_load_gutenberg_assets() {
661
-
662
- // When working in the classic editor shipped with Gutenberg, the assets shouldn't be loaded. Fixes IE11 bug.
663
- if ( isset( $_GET['classic-editor'] ) ) {
664
- return false;
665
- }
666
-
667
- return wp_script_is( 'wp-element', 'registered' );
668
- }
669
  }
15
  */
16
  protected $asset_location;
17
 
 
 
 
 
 
18
  /**
19
  * Prefix for naming the assets.
20
  */
168
  }
169
 
170
  /**
171
+ * Registers the WordPress dependencies that exist in 5.0 in case they are not present.
172
  *
173
  * This function can be removed when WordPress 5.1 has been released, because from 5.0 wp-elements will be
174
  * registered earlier, which means we don't have to reregister things.
176
  * @return void
177
  */
178
  public function register_wp_assets() {
 
 
179
 
180
+ global $wp_scripts;
 
181
 
182
+ $script = $wp_scripts->query( 'react' );
 
 
 
 
 
 
183
 
184
+ // IE11 needs wp-polyfill to be registered before react.
185
+ if ( $script && ! in_array( 'wp-polyfill', $script->deps, true ) ) {
186
+ $script->deps[] = 'wp-polyfill';
187
+ }
188
 
189
  $flat_version = $this->flatten_version( WPSEO_VERSION );
190
+
191
+ wp_register_script( 'lodash-base', plugins_url( 'js/vendor/lodash.min.js', WPSEO_FILE ), array(), false, true );
192
+ wp_register_script( 'lodash', plugins_url( 'js/vendor/lodash-noconflict.js', WPSEO_FILE ), array( 'lodash-base' ), false, true );
193
+ wp_register_script( 'wp-polyfill', plugins_url( 'js/dist/babel-polyfill-' . $flat_version . '.min.js', WPSEO_FILE ), array(), false, true );
194
+
195
+ wp_register_script(
196
+ 'wp-element',
197
+ plugins_url( 'js/dist/wp-element-' . $flat_version . '.min.js', WPSEO_FILE ),
198
+ array( 'lodash', 'wp-polyfill' ),
199
+ false,
200
+ true
201
  );
202
 
203
+ wp_register_script(
204
+ 'wp-api-fetch',
205
+ plugins_url( 'js/dist/wp-apiFetch-' . $flat_version . '.min.js', WPSEO_FILE ),
206
+ array( 'wp-i18n', 'wp-polyfill' ),
207
+ false,
208
+ true
209
+ );
210
 
211
+ wp_register_script(
212
+ 'wp-components',
213
+ plugins_url( 'js/dist/wp-components-' . $flat_version . '.min.js', WPSEO_FILE ),
214
+ array( 'lodash', 'wp-api-fetch', 'wp-i18n', 'wp-polyfill', 'wp-compose' ),
215
+ false,
216
+ true
217
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
+ wp_register_script(
220
+ 'wp-data',
221
+ plugins_url( 'js/dist/wp-data-' . $flat_version . '.min.js', WPSEO_FILE ),
222
+ array( 'lodash', 'wp-element', 'wp-polyfill', 'wp-compose' ),
223
+ false,
224
+ true
225
+ );
226
+
227
+ wp_register_script(
228
+ 'wp-i18n',
229
+ plugins_url( 'js/dist/wp-i18n-' . $flat_version . '.min.js', WPSEO_FILE ),
230
+ array( 'wp-polyfill' ),
231
+ false,
232
+ true
233
+ );
234
+
235
+ wp_register_script(
236
+ 'wp-rich-text',
237
+ plugins_url( 'js/dist/wp-rich-text-' . $flat_version . '.min.js', WPSEO_FILE ),
238
+ array( 'lodash', 'wp-polyfill', 'wp-data' ),
239
+ false,
240
+ true
241
+ );
242
+
243
+ wp_register_script(
244
+ 'wp-compose',
245
+ plugins_url( 'js/dist/wp-compose-' . $flat_version . '.min.js', WPSEO_FILE ),
246
+ array( 'wp-polyfill' ),
247
+ false,
248
+ true
249
+ );
250
 
251
+ /*
252
+ * wp-annotations only exists from Gutenberg 4.3 and onwards, so we register a no-op in earlier versions.
253
+ * The no-op achieves that our scripts that depend on this are actually loaded. Because WordPress doesn't
254
+ * load a script if any of the dependencies are missing.
255
+ */
256
+ wp_register_script(
257
+ 'wp-annotations',
258
+ null
259
+ );
260
  }
261
 
262
  /**
280
 
281
  $flat_version = $this->flatten_version( WPSEO_VERSION );
282
 
 
 
 
 
 
 
 
 
283
  return array(
284
  array(
285
+ 'name' => 'commons',
286
  // Load webpack-commons for bundle support.
287
  'src' => 'commons-' . $flat_version,
288
+ 'deps' => array(
289
+ 'wp-polyfill'
290
+ ),
291
  ),
292
  array(
293
  'name' => 'search-appearance',
294
  'src' => 'search-appearance-' . $flat_version,
295
  'deps' => array(
 
296
  self::PREFIX . 'components',
297
+ self::PREFIX . 'commons',
298
  ),
299
  ),
 
 
 
 
 
300
  array(
301
  'name' => 'yoast-modal',
302
  'src' => 'wp-seo-modal-' . $flat_version,
303
  'deps' => array(
304
  'jquery',
305
+ 'wp-element',
306
+ 'wp-i18n',
307
  self::PREFIX . 'components',
308
+ self::PREFIX . 'commons',
309
  ),
310
  ),
311
  array(
313
  'src' => 'wp-seo-help-center-' . $flat_version,
314
  'deps' => array(
315
  'jquery',
316
+ 'wp-element',
317
+ 'wp-i18n',
318
  self::PREFIX . 'components',
319
+ self::PREFIX . 'commons',
320
  ),
321
  ),
322
  array(
328
  'jquery-ui-progressbar',
329
  self::PREFIX . 'select2',
330
  self::PREFIX . 'select2-translations',
331
+ self::PREFIX . 'commons',
332
  ),
333
  ),
334
  array(
337
  'deps' => array(
338
  'jquery',
339
  'jquery-ui-core',
340
+ self::PREFIX . 'commons',
341
  ),
342
  ),
343
  array(
344
  'name' => 'network-admin-script',
345
  'src' => 'wp-seo-network-admin-' . $flat_version,
346
+ 'deps' => array(
347
+ 'jquery',
348
+ self::PREFIX . 'commons',
349
+ ),
350
  ),
351
  array(
352
  'name' => 'bulk-editor',
353
  'src' => 'wp-seo-bulk-editor-' . $flat_version,
354
  'deps' => array(
355
  'jquery',
356
+ self::PREFIX . 'commons',
357
  ),
358
  ),
359
  array(
361
  'src' => 'wp-seo-admin-global-' . $flat_version,
362
  'deps' => array(
363
  'jquery',
364
+ self::PREFIX . 'commons',
365
  ),
366
  ),
367
  array(
369
  'src' => 'wp-seo-metabox-' . $flat_version,
370
  'deps' => array(
371
  'jquery',
372
+ 'wp-element',
373
+ 'wp-i18n',
374
+ 'wp-data',
375
+ 'wp-components',
376
  self::PREFIX . 'select2',
377
  self::PREFIX . 'select2-translations',
378
+ self::PREFIX . 'commons',
379
  ),
380
  'in_footer' => false,
381
  ),
384
  'src' => 'wp-seo-featured-image-' . $flat_version,
385
  'deps' => array(
386
  'jquery',
387
+ self::PREFIX . 'commons',
388
  ),
389
  ),
390
  array(
391
  'name' => 'admin-gsc',
392
  'src' => 'wp-seo-admin-gsc-' . $flat_version,
393
  'deps' => array(
394
+ self::PREFIX . 'commons',
395
  ),
396
  'in_footer' => false,
397
  ),
399
  'name' => 'post-scraper',
400
  'src' => 'wp-seo-post-scraper-' . $flat_version,
401
  'deps' => array(
 
 
402
  'wp-util',
403
  'wp-api',
404
+ 'wp-sanitize',
405
+ 'wp-element',
406
+ 'wp-i18n',
407
+ 'wp-data',
408
+ 'wp-api-fetch',
409
+ 'wp-annotations',
410
+ 'wp-compose',
411
+ self::PREFIX . 'replacevar-plugin',
412
+ self::PREFIX . 'shortcode-plugin',
413
  self::PREFIX . 'analysis',
 
414
  self::PREFIX . 'components',
415
+ self::PREFIX . 'commons',
416
  ),
417
  ),
418
  array(
419
  'name' => 'term-scraper',
420
  'src' => 'wp-seo-term-scraper-' . $flat_version,
421
  'deps' => array(
422
+ 'wp-sanitize',
423
+ 'wp-element',
424
+ 'wp-i18n',
425
+ 'wp-data',
426
+ 'wp-api-fetch',
427
+ 'wp-compose',
428
  self::PREFIX . 'replacevar-plugin',
 
429
  self::PREFIX . 'analysis',
430
  self::PREFIX . 'components',
431
+ self::PREFIX . 'commons',
432
  ),
433
  ),
434
  array(
435
  'name' => 'replacevar-plugin',
436
  'src' => 'wp-seo-replacevar-plugin-' . $flat_version,
437
  'deps' => array(
 
438
  self::PREFIX . 'analysis',
439
  self::PREFIX . 'components',
440
+ self::PREFIX . 'commons',
441
  ),
442
  ),
443
  array(
444
  'name' => 'shortcode-plugin',
445
  'src' => 'wp-seo-shortcode-plugin-' . $flat_version,
446
  'deps' => array(
 
447
  self::PREFIX . 'analysis',
448
+ self::PREFIX . 'commons',
449
  ),
450
  ),
451
  array(
456
  'jquery-ui-core',
457
  'jquery-ui-progressbar',
458
  self::PREFIX . 'analysis',
459
+ self::PREFIX . 'commons',
460
  ),
461
  ),
462
  array(
465
  'deps' => array(
466
  'jquery',
467
  'wp-util',
468
+ 'wp-element',
469
+ 'wp-i18n',
470
+ 'wp-components',
471
+ 'wp-data',
472
+ self::PREFIX . 'commons',
473
  ),
474
  ),
475
  array(
496
  'src' => 'configuration-wizard-' . $flat_version,
497
  'deps' => array(
498
  'jquery',
499
+ 'wp-element',
500
+ 'wp-i18n',
501
  self::PREFIX . 'components',
502
+ self::PREFIX . 'commons',
503
  ),
504
  ),
505
  array(
509
  'jquery',
510
  'jquery-ui-core',
511
  'jquery-ui-progressbar',
512
+ self::PREFIX . 'commons',
513
  ),
514
  ),
515
  array(
517
  'src' => 'wp-seo-edit-page-' . $flat_version,
518
  'deps' => array(
519
  'jquery',
520
+ self::PREFIX . 'commons',
521
  ),
522
  ),
523
  array(
525
  'src' => 'wp-seo-quick-edit-handler-' . $flat_version,
526
  'deps' => array(
527
  'jquery',
528
+ self::PREFIX . 'commons',
529
  ),
530
  'in_footer' => true,
531
  ),
535
  'deps' => array(
536
  'wp-api',
537
  'jquery',
538
+ self::PREFIX . 'commons',
539
  ),
540
  ),
541
  array(
544
  'deps' => array(
545
  self::PREFIX . 'api',
546
  'jquery',
547
+ 'wp-element',
548
+ 'wp-i18n',
549
  self::PREFIX . 'components',
550
+ self::PREFIX . 'commons',
551
  ),
552
  ),
553
  array(
555
  'src' => 'wp-seo-filter-explanation-' . $flat_version,
556
  'deps' => array(
557
  'jquery',
558
+ self::PREFIX . 'commons',
559
  ),
560
  ),
561
  array(
562
  'name' => 'analysis',
563
  'src' => 'analysis-' . $flat_version,
564
  'deps' => array(
565
+ 'lodash',
566
+ self::PREFIX . 'commons',
567
  ),
568
  ),
569
  array(
570
  'name' => 'components',
571
  'src' => 'components-' . $flat_version,
572
+ 'deps' => array(
573
+ self::PREFIX . 'analysis',
574
+ self::PREFIX . 'styled-components',
575
+ self::PREFIX . 'commons',
576
+ ),
577
  ),
578
  array(
579
  'name' => 'structured-data-blocks',
580
  'src' => 'wp-seo-structured-data-blocks-' . $flat_version,
581
+ 'deps' => array(
582
+ 'wp-blocks',
583
+ 'wp-i18n',
584
+ 'wp-element',
585
+ self::PREFIX . 'styled-components',
586
+ self::PREFIX . 'commons',
587
+ ),
588
  ),
589
  array(
590
+ 'name' => 'styled-components',
591
+ 'src' => 'styled-components-' . $flat_version,
592
  ),
593
  );
594
  }
686
  ),
687
  );
688
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
689
  }
admin/class-admin-init.php CHANGED
@@ -48,8 +48,8 @@ class WPSEO_Admin_Init {
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' ) );
50
  add_action( 'admin_init', array( $this, 'handle_notifications' ), 15 );
51
- add_action( 'admin_enqueue_scripts', array( $this->asset_manager, 'register_wp_assets' ) );
52
  add_action( 'admin_notices', array( $this, 'permalink_settings_notice' ) );
 
53
 
54
  $listeners = array();
55
  $listeners[] = new WPSEO_Post_Type_Archive_Notification_Handler();
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' ) );
50
  add_action( 'admin_init', array( $this, 'handle_notifications' ), 15 );
 
51
  add_action( 'admin_notices', array( $this, 'permalink_settings_notice' ) );
52
+ add_action( 'admin_enqueue_scripts', array( $this->asset_manager, 'register_wp_assets' ), PHP_INT_MAX );
53
 
54
  $listeners = array();
55
  $listeners[] = new WPSEO_Post_Type_Archive_Notification_Handler();
admin/class-admin.php CHANGED
@@ -41,6 +41,10 @@ class WPSEO_Admin {
41
  add_action( 'delete_category', array( $this, 'schedule_rewrite_flush' ) );
42
  }
43
 
 
 
 
 
44
  $this->admin_features = array(
45
  // Google Search Console.
46
  'google_search_console' => new WPSEO_GSC(),
@@ -88,8 +92,6 @@ class WPSEO_Admin {
88
 
89
  $this->initialize_cornerstone_content();
90
 
91
- new Yoast_Modal();
92
-
93
  if ( WPSEO_Utils::is_plugin_network_active() ) {
94
  $integrations[] = new Yoast_Network_Admin();
95
  }
@@ -217,11 +219,11 @@ class WPSEO_Admin {
217
  }
218
 
219
  // Add link to premium support landing page.
220
- $premium_link = '<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yb' ) ) . '">' . __( 'Premium Support', 'wordpress-seo' ) . '</a>';
221
  array_unshift( $links, $premium_link );
222
 
223
  // Add link to docs.
224
- $faq_link = '<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yc' ) ) . '">' . __( 'FAQ', 'wordpress-seo' ) . '</a>';
225
  array_unshift( $links, $faq_link );
226
 
227
  return $links;
41
  add_action( 'delete_category', array( $this, 'schedule_rewrite_flush' ) );
42
  }
43
 
44
+ if ( WPSEO_Options::get( 'disable-attachment' ) === true ) {
45
+ add_filter( 'wpseo_accessible_post_types', array( 'WPSEO_Post_Type', 'filter_attachment_post_type' ) );
46
+ }
47
+
48
  $this->admin_features = array(
49
  // Google Search Console.
50
  'google_search_console' => new WPSEO_GSC(),
92
 
93
  $this->initialize_cornerstone_content();
94
 
 
 
95
  if ( WPSEO_Utils::is_plugin_network_active() ) {
96
  $integrations[] = new Yoast_Network_Admin();
97
  }
219
  }
220
 
221
  // Add link to premium support landing page.
222
+ $premium_link = '<a style="font-weight: bold;" href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yb' ) ) . '" target="_blank">' . __( 'Premium Support', 'wordpress-seo' ) . '</a>';
223
  array_unshift( $links, $premium_link );
224
 
225
  // Add link to docs.
226
+ $faq_link = '<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yc' ) ) . '" target="_blank">' . __( 'FAQ', 'wordpress-seo' ) . '</a>';
227
  array_unshift( $links, $faq_link );
228
 
229
  return $links;
admin/class-bulk-editor-list-table.php CHANGED
@@ -298,15 +298,15 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
298
  );
299
 
300
 
301
- $post_status = filter_input( INPUT_GET, 'post_status' );
302
- $class = empty( $post_status ) ? ' class="current"' : '';
303
- $localized_text = sprintf(
304
  /* translators: %s expands to the number of posts in localized format. */
305
  _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_posts, 'posts', 'wordpress-seo' ),
306
  number_format_i18n( $total_posts )
307
  );
308
 
309
- $status_links['all'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) . '"' . $class . '>' . $localized_text . '</a>';
310
 
311
  $post_stati = get_post_stati( array( 'show_in_admin_all_list' => true ), 'objects' );
312
  if ( is_array( $post_stati ) && $post_stati !== array() ) {
@@ -328,15 +328,15 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
328
  continue;
329
  }
330
 
331
- $class = '';
332
  if ( $status_name === $post_status ) {
333
- $class = ' class="current"';
334
  }
335
 
336
- $status_links[ $status_name ] = '<a href="' . esc_url( add_query_arg( array( 'post_status' => $status_name ), admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) ) . '"' . $class . '>' . sprintf( translate_nooped_plural( $status->label_count, $total ), number_format_i18n( $total ) ) . '</a>';
337
  }
338
  }
339
- unset( $post_stati, $status, $status_name, $total, $class );
340
 
341
  $trashed_posts = $wpdb->get_var(
342
  "
@@ -345,9 +345,9 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
345
  "
346
  );
347
 
348
- $class = '';
349
  if ( 'trash' === $post_status ) {
350
- $class = 'class="current"';
351
  }
352
 
353
  $localized_text = sprintf(
@@ -356,7 +356,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
356
  number_format_i18n( $trashed_posts )
357
  );
358
 
359
- $status_links['trash'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor&post_status=trash' . $this->page_url ) ) . '"' . $class . '>' . $localized_text . '</a>';
360
 
361
  return $status_links;
362
  }
298
  );
299
 
300
 
301
+ $post_status = filter_input( INPUT_GET, 'post_status' );
302
+ $current_link_attributes = empty( $post_status ) ? ' class="current" aria-current="page"' : '';
303
+ $localized_text = sprintf(
304
  /* translators: %s expands to the number of posts in localized format. */
305
  _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_posts, 'posts', 'wordpress-seo' ),
306
  number_format_i18n( $total_posts )
307
  );
308
 
309
+ $status_links['all'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) . '"' . $current_link_attributes . '>' . $localized_text . '</a>';
310
 
311
  $post_stati = get_post_stati( array( 'show_in_admin_all_list' => true ), 'objects' );
312
  if ( is_array( $post_stati ) && $post_stati !== array() ) {
328
  continue;
329
  }
330
 
331
+ $current_link_attributes = '';
332
  if ( $status_name === $post_status ) {
333
+ $current_link_attributes = ' class="current" aria-current="page"';
334
  }
335
 
336
+ $status_links[ $status_name ] = '<a href="' . esc_url( add_query_arg( array( 'post_status' => $status_name ), admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) ) . '"' . $current_link_attributes . '>' . sprintf( translate_nooped_plural( $status->label_count, $total ), number_format_i18n( $total ) ) . '</a>';
337
  }
338
  }
339
+ unset( $post_stati, $status, $status_name, $total, $current_link_attributes );
340
 
341
  $trashed_posts = $wpdb->get_var(
342
  "
345
  "
346
  );
347
 
348
+ $current_link_attributes = '';
349
  if ( 'trash' === $post_status ) {
350
+ $current_link_attributes = 'class="current" aria-current="page"';
351
  }
352
 
353
  $localized_text = sprintf(
356
  number_format_i18n( $trashed_posts )
357
  );
358
 
359
+ $status_links['trash'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor&post_status=trash' . $this->page_url ) ) . '"' . $current_link_attributes . '>' . $localized_text . '</a>';
360
 
361
  return $status_links;
362
  }
admin/class-config.php CHANGED
@@ -41,24 +41,10 @@ class WPSEO_Admin_Pages {
41
  wp_redirect( admin_url( 'admin.php?page=' . WPSEO_Configuration_Page::PAGE_IDENTIFIER ) );
42
  }
43
 
44
- add_action( 'admin_init', array( $this, 'admin_init' ) );
45
  add_action( 'admin_enqueue_scripts', array( $this, 'config_page_scripts' ) );
46
  add_action( 'admin_enqueue_scripts', array( $this, 'config_page_styles' ) );
47
  }
48
 
49
- /**
50
- * Run admin-specific actions.
51
- */
52
- public function admin_init() {
53
-
54
- $page = filter_input( INPUT_GET, 'page' );
55
- $tool = filter_input( INPUT_GET, 'tool' );
56
- $export_nonce = filter_input( INPUT_POST, WPSEO_Export::NONCE_NAME );
57
-
58
- if ( 'wpseo_tools' === $page && 'import-export' === $tool && $export_nonce !== null ) {
59
- $this->do_yoast_export();
60
- }
61
- }
62
 
63
  /**
64
  * Loads the required styles for the config page.
@@ -158,24 +144,4 @@ class WPSEO_Admin_Pages {
158
  $this->asset_manager->enqueue_script( 'bulk-editor' );
159
  }
160
  }
161
-
162
- /**
163
- * Runs the yoast exporter class to possibly init the file download.
164
- */
165
- private function do_yoast_export() {
166
- check_admin_referer( WPSEO_Export::NONCE_ACTION, WPSEO_Export::NONCE_NAME );
167
-
168
- if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
169
- return;
170
- }
171
-
172
- $wpseo_post = filter_input( INPUT_POST, 'wpseo' );
173
- $include_taxonomy = ! empty( $wpseo_post['include_taxonomy'] );
174
- $export = new WPSEO_Export( $include_taxonomy );
175
-
176
- if ( $export->has_error() ) {
177
- add_action( 'admin_notices', array( $export, 'set_error_hook' ) );
178
-
179
- }
180
- }
181
  } /* End of class */
41
  wp_redirect( admin_url( 'admin.php?page=' . WPSEO_Configuration_Page::PAGE_IDENTIFIER ) );
42
  }
43
 
 
44
  add_action( 'admin_enqueue_scripts', array( $this, 'config_page_scripts' ) );
45
  add_action( 'admin_enqueue_scripts', array( $this, 'config_page_styles' ) );
46
  }
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  /**
50
  * Loads the required styles for the config page.
144
  $this->asset_manager->enqueue_script( 'bulk-editor' );
145
  }
146
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  } /* End of class */
admin/class-export.php CHANGED
@@ -11,12 +11,7 @@
11
  * Class with functionality to export the WP SEO settings
12
  */
13
  class WPSEO_Export {
14
-
15
- const ZIP_FILENAME = 'yoast-seo-settings-export.zip';
16
- const INI_FILENAME = 'settings.ini';
17
-
18
  const NONCE_ACTION = 'wpseo_export';
19
- const NONCE_NAME = 'wpseo_export_nonce';
20
 
21
  /**
22
  * @var string
@@ -28,38 +23,34 @@ class WPSEO_Export {
28
  */
29
  private $error = '';
30
 
31
- /**
32
- * @var string
33
- */
34
- public $export_zip_url = '';
35
-
36
  /**
37
  * @var boolean
38
  */
39
  public $success;
40
 
41
  /**
42
- * Whether or not the export will include taxonomy metadata
43
- *
44
- * @var boolean
45
- */
46
- private $include_taxonomy;
47
-
48
- /**
49
- * @var array
50
  */
51
- private $dir = array();
 
 
 
 
52
 
53
  /**
54
- * Class constructor
55
- *
56
- * @param boolean $include_taxonomy Whether to include the taxonomy metadata the plugin creates.
57
  */
58
- public function __construct( $include_taxonomy = false ) {
59
- $this->include_taxonomy = $include_taxonomy;
60
- $this->dir = wp_upload_dir();
 
 
61
 
62
- $this->export_settings();
 
 
 
 
63
  }
64
 
65
  /**
@@ -88,41 +79,24 @@ class WPSEO_Export {
88
  * Exports the current site's WP SEO settings.
89
  */
90
  private function export_settings() {
91
-
92
  $this->export_header();
93
 
94
  foreach ( WPSEO_Options::get_option_names() as $opt_group ) {
95
  $this->write_opt_group( $opt_group );
96
  }
97
-
98
- $this->taxonomy_metadata();
99
-
100
- if ( ! $this->write_settings_file() ) {
101
- $this->error = __( 'Could not write settings to file.', 'wordpress-seo' );
102
-
103
- return;
104
- }
105
-
106
- if ( $this->zip_file() ) {
107
- // Just exit, because there is a download being served.
108
- exit;
109
- }
110
  }
111
 
112
  /**
113
- * Writes the header of the export file.
114
  */
115
  private function export_header() {
116
  $header = sprintf(
117
  /* translators: %1$s expands to Yoast SEO, %2$s expands to Yoast.com */
118
- esc_html__( 'This is a settings export file for the %1$s plugin by %2$s', 'wordpress-seo' ),
119
  'Yoast SEO',
120
  'Yoast.com'
121
  );
122
- $this->write_line( '; ' . $header . ' - ' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yd' ) ) );
123
- if ( $this->include_taxonomy ) {
124
- $this->write_line( '; ' . __( 'This export includes taxonomy metadata', 'wordpress-seo' ) );
125
- }
126
  }
127
 
128
  /**
@@ -178,109 +152,4 @@ class WPSEO_Export {
178
  }
179
  $this->write_line( $key . ' = ' . $val );
180
  }
181
-
182
- /**
183
- * Adds the taxonomy meta data if there is any
184
- */
185
- private function taxonomy_metadata() {
186
- if ( $this->include_taxonomy ) {
187
- $taxonomy_meta = get_option( 'wpseo_taxonomy_meta' );
188
- if ( is_array( $taxonomy_meta ) ) {
189
- $this->write_line( '[wpseo_taxonomy_meta]', true );
190
- $this->write_setting( 'wpseo_taxonomy_meta', urlencode( wp_json_encode( $taxonomy_meta ) ) );
191
- }
192
- else {
193
- $this->write_line( '; ' . __( 'No taxonomy metadata found', 'wordpress-seo' ), true );
194
- }
195
- }
196
- }
197
-
198
- /**
199
- * Writes the settings to our temporary settings.ini file
200
- *
201
- * @return boolean unsigned
202
- */
203
- private function write_settings_file() {
204
- $handle = fopen( $this->dir['path'] . '/' . self::INI_FILENAME, 'w' );
205
- if ( ! $handle ) {
206
- return false;
207
- }
208
-
209
- $res = fwrite( $handle, $this->export );
210
- if ( ! $res ) {
211
- return false;
212
- }
213
-
214
- fclose( $handle );
215
-
216
- return true;
217
- }
218
-
219
- /**
220
- * Zips the settings ini file
221
- *
222
- * @return bool|null
223
- */
224
- private function zip_file() {
225
- $is_zip_created = $this->create_zip();
226
-
227
- // The settings.ini isn't needed, because it's in the zipfile.
228
- $this->remove_settings_ini();
229
-
230
- if ( ! $is_zip_created ) {
231
- $this->error = __( 'Could not zip settings-file.', 'wordpress-seo' );
232
-
233
- return false;
234
- }
235
-
236
- $this->serve_settings_export();
237
- $this->remove_zip();
238
-
239
- return true;
240
- }
241
-
242
- /**
243
- * Creates the zipfile and returns true if it created successful.
244
- *
245
- * @return bool
246
- */
247
- private function create_zip() {
248
- chdir( $this->dir['path'] );
249
- $zip = new PclZip( './' . self::ZIP_FILENAME );
250
- if ( 0 === $zip->create( './' . self::INI_FILENAME ) ) {
251
- return false;
252
- }
253
-
254
- return file_exists( self::ZIP_FILENAME );
255
- }
256
-
257
- /**
258
- * Downloads the zip file.
259
- */
260
- private function serve_settings_export() {
261
- // Clean any content that has been already output. For example by other plugins or faulty PHP files.
262
- if ( ob_get_contents() ) {
263
- ob_clean();
264
- }
265
- header( 'Content-Type: application/octet-stream; charset=utf-8' );
266
- header( 'Content-Transfer-Encoding: Binary' );
267
- header( 'Content-Disposition: attachment; filename=' . self::ZIP_FILENAME );
268
- header( 'Content-Length: ' . filesize( self::ZIP_FILENAME ) );
269
-
270
- readfile( self::ZIP_FILENAME );
271
- }
272
-
273
- /**
274
- * Removes the settings ini file.
275
- */
276
- private function remove_settings_ini() {
277
- unlink( './' . self::INI_FILENAME );
278
- }
279
-
280
- /**
281
- * Removes the files because they are already downloaded.
282
- */
283
- private function remove_zip() {
284
- unlink( './' . self::ZIP_FILENAME );
285
- }
286
  }
11
  * Class with functionality to export the WP SEO settings
12
  */
13
  class WPSEO_Export {
 
 
 
 
14
  const NONCE_ACTION = 'wpseo_export';
 
15
 
16
  /**
17
  * @var string
23
  */
24
  private $error = '';
25
 
 
 
 
 
 
26
  /**
27
  * @var boolean
28
  */
29
  public $success;
30
 
31
  /**
32
+ * Handles the export request.
 
 
 
 
 
 
 
33
  */
34
+ public function export() {
35
+ check_admin_referer( self::NONCE_ACTION );
36
+ $this->export_settings();
37
+ $this->output();
38
+ }
39
 
40
  /**
41
+ * Outputs the export.
 
 
42
  */
43
+ public function output() {
44
+ if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
45
+ esc_html_e( 'You do not have the required rights to export settings.', 'wordpress-seo' );
46
+ return;
47
+ }
48
 
49
+ echo '<p>';
50
+ /* translators: %1$s expands to Import settings */
51
+ printf( esc_html__( 'Copy all these settings to another site\'s %1$s tab and click "%1$s" there.', 'wordpress-seo' ), __( 'Import settings', 'wordpress-seo' ) );
52
+ echo '</p>';
53
+ echo '<textarea id="wpseo-export" rows="20" cols="100">' . $this->export . '</textarea>';
54
  }
55
 
56
  /**
79
  * Exports the current site's WP SEO settings.
80
  */
81
  private function export_settings() {
 
82
  $this->export_header();
83
 
84
  foreach ( WPSEO_Options::get_option_names() as $opt_group ) {
85
  $this->write_opt_group( $opt_group );
86
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  }
88
 
89
  /**
90
+ * Writes the header of the export.
91
  */
92
  private function export_header() {
93
  $header = sprintf(
94
  /* translators: %1$s expands to Yoast SEO, %2$s expands to Yoast.com */
95
+ esc_html__( 'These are settings for the %1$s plugin by %2$s', 'wordpress-seo' ),
96
  'Yoast SEO',
97
  'Yoast.com'
98
  );
99
+ $this->write_line( '; ' . $header );
 
 
 
100
  }
101
 
102
  /**
152
  }
153
  $this->write_line( $key . ' = ' . $val );
154
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
admin/class-extension.php CHANGED
@@ -31,6 +31,15 @@ class WPSEO_Extension {
31
  return $this->config['title'];
32
  }
33
 
 
 
 
 
 
 
 
 
 
34
  /**
35
  * Returns URL to the page where the product can be bought.
36
  *
31
  return $this->config['title'];
32
  }
33
 
34
+ /**
35
+ * Returns the product title to display.
36
+ *
37
+ * @return string The title to display on the license page.
38
+ */
39
+ public function get_display_title() {
40
+ return empty( $this->config['display_title'] ) ? $this->get_title() : $this->config['display_title'];
41
+ }
42
+
43
  /**
44
  * Returns URL to the page where the product can be bought.
45
  *
admin/class-extensions.php CHANGED
@@ -37,11 +37,6 @@ class WPSEO_Extensions {
37
  'identifier' => 'wpseo-local',
38
  'classname' => 'WPSEO_Local_Core',
39
  ),
40
- 'Local SEO for WooCommerce' => array(
41
- 'slug' => 'local-seo-for-woocommerce',
42
- 'identifier' => 'wpseo-local-woocommerce',
43
- 'classname' => 'WPSEO_Local_WooCommerce',
44
- ),
45
  );
46
 
47
  /**
37
  'identifier' => 'wpseo-local',
38
  'classname' => 'WPSEO_Local_Core',
39
  ),
 
 
 
 
 
40
  );
41
 
42
  /**
admin/class-gutenberg-compatibility.php CHANGED
@@ -13,12 +13,12 @@ class WPSEO_Gutenberg_Compatibility {
13
  /**
14
  * The currently released version of Gutenberg.
15
  */
16
- const CURRENT_RELEASE = '4.1.1';
17
 
18
  /**
19
  * The minimally supported version of Gutenberg by the plugin.
20
  */
21
- const MINIMUM_SUPPORTED = '4.1.1';
22
 
23
  /**
24
  * @var string
13
  /**
14
  * The currently released version of Gutenberg.
15
  */
16
+ const CURRENT_RELEASE = '4.4.0';
17
 
18
  /**
19
  * The minimally supported version of Gutenberg by the plugin.
20
  */
21
+ const MINIMUM_SUPPORTED = '4.4.0';
22
 
23
  /**
24
  * @var string
admin/class-premium-popup.php CHANGED
@@ -77,8 +77,10 @@ class WPSEO_Premium_Popup {
77
  $assets_uri = trailingslashit( plugin_dir_url( WPSEO_FILE ) );
78
 
79
  /* translators: %s expands to Yoast SEO Premium */
80
- $cta_text = sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
81
- $classes = '';
 
 
82
  if ( $popup ) {
83
  $classes = ' hidden';
84
  }
@@ -89,7 +91,9 @@ class WPSEO_Premium_Popup {
89
  <img class="alignright wpseo-premium-popup-icon" src="{$assets_uri}images/Yoast_SEO_Icon.svg" width="150" height="150" alt="Yoast SEO"/>
90
  <{$this->heading_level} id="wpseo-contact-support-popup-title" class="wpseo-premium-popup-title">{$this->title}</{$this->heading_level}>
91
  {$this->content}
92
- <a id="wpseo-{$this->identifier}-popup-button" class="yoast-button-upsell" href="{$this->url}" target="_blank" rel="noreferrer noopener">{$cta_text}</a><br/>
 
 
93
  <small>{$micro_copy}</small>
94
  </div>
95
  EO_POPUP;
77
  $assets_uri = trailingslashit( plugin_dir_url( WPSEO_FILE ) );
78
 
79
  /* translators: %s expands to Yoast SEO Premium */
80
+ $cta_text = esc_html( sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ) );
81
+ $new_tab_message = '<span class="screen-reader-text">' . esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>';
82
+ $caret_icon = '<span aria-hidden="true" class="yoast-button-upsell__caret"></span>';
83
+ $classes = '';
84
  if ( $popup ) {
85
  $classes = ' hidden';
86
  }
91
  <img class="alignright wpseo-premium-popup-icon" src="{$assets_uri}images/Yoast_SEO_Icon.svg" width="150" height="150" alt="Yoast SEO"/>
92
  <{$this->heading_level} id="wpseo-contact-support-popup-title" class="wpseo-premium-popup-title">{$this->title}</{$this->heading_level}>
93
  {$this->content}
94
+ <a id="wpseo-{$this->identifier}-popup-button" class="yoast-button-upsell" href="{$this->url}" target="_blank">
95
+ {$cta_text} {$new_tab_message} {$caret_icon}
96
+ </a><br/>
97
  <small>{$micro_copy}</small>
98
  </div>
99
  EO_POPUP;
admin/class-premium-upsell-admin-block.php CHANGED
@@ -60,13 +60,15 @@ class WPSEO_Premium_Upsell_Admin_Block {
60
  $dismiss_msg = sprintf( __( 'Dismiss %s upgrade notice', 'wordpress-seo' ), 'Yoast SEO Premium' );
61
 
62
  /* translators: %s expands to Yoast SEO Premium */
63
- $button_text = sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
 
 
64
 
65
  $upgrade_button = sprintf(
66
  '<a id="wpseo-%1$s-popup-button" class="yoast-button-upsell" href="%2$s" target="_blank" rel="noreferrer noopener">%3$s</a>',
67
  $this->identifier,
68
  $url,
69
- esc_html( $button_text )
70
  );
71
 
72
  echo '<div class="' . esc_attr( $class ) . '">';
60
  $dismiss_msg = sprintf( __( 'Dismiss %s upgrade notice', 'wordpress-seo' ), 'Yoast SEO Premium' );
61
 
62
  /* translators: %s expands to Yoast SEO Premium */
63
+ $button_text = esc_html( sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ) );
64
+ $button_text .= '<span class="screen-reader-text">' . esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>' .
65
+ '<span aria-hidden="true" class="yoast-button-upsell__caret"></span>';
66
 
67
  $upgrade_button = sprintf(
68
  '<a id="wpseo-%1$s-popup-button" class="yoast-button-upsell" href="%2$s" target="_blank" rel="noreferrer noopener">%3$s</a>',
69
  $this->identifier,
70
  $url,
71
+ $button_text
72
  );
73
 
74
  echo '<div class="' . esc_attr( $class ) . '">';
admin/class-yoast-modal.php DELETED
@@ -1,97 +0,0 @@
1
- <?php
2
- /**
3
- * @package WPSEO\Admin
4
- */
5
-
6
- /**
7
- * Class to implement a React modal.
8
- */
9
- class Yoast_Modal {
10
-
11
- /** @var array The modal configuration. */
12
- private static $config = array();
13
-
14
- /**
15
- * Class constructor.
16
- */
17
- public function __construct() {
18
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
19
- add_action( 'admin_footer', array( $this, 'print_localized_config' ) );
20
- }
21
-
22
- /**
23
- * Enqueues the assets needed for the modal.
24
- */
25
- public function enqueue_assets() {
26
- $asset_manager = new WPSEO_Admin_Asset_Manager();
27
- $asset_manager->enqueue_script( 'yoast-modal' );
28
- }
29
-
30
- /**
31
- * Prints the modals configuration.
32
- */
33
- public function print_localized_config() {
34
- $config = self::$config;
35
- wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'yoast-modal', 'yoastModalConfig', $config );
36
- }
37
-
38
- /**
39
- * Adds a single modal configuration to the modals configuration.
40
- *
41
- * @param array $args The modal configuration arguments.
42
- */
43
- public static function add( $args ) {
44
- $defaults = self::get_defaults();
45
- $single = array_replace_recursive( $defaults, $args );
46
- self::$config[] = $single;
47
- }
48
-
49
- /**
50
- * Gets the modals configuration.
51
- */
52
- public function get_config() {
53
- return self::$config;
54
- }
55
-
56
- /**
57
- * Gets the default configuration for a modal.
58
- *
59
- * @return array {
60
- * The modal default configuration.
61
- *
62
- * @type string $mountHook Any CSS query selector to target an element that will be replaced
63
- * by the modal open button.
64
- * @type string $appElement Element the modal will hide with `aria-hidden`. For better
65
- * accessibility, set it to the most general wrapper and don't use body.
66
- * @type string $openButtonIcon Optional. Icon for the open button.
67
- * @type array $intl Locale and labels for the modal main elements. If omitted, the related
68
- * elements will not be used. Only exception is `modalAriaLabel` which is
69
- * required by the React modal component.
70
- * @type array $classes Optional. CSS classes for the modal buttons.
71
- * @type string $content The name of the React component to use as the modal content.
72
- * }
73
- */
74
- public static function get_defaults() {
75
- $config = array(
76
- 'mountHook' => '',
77
- 'appElement' => '#wpwrap',
78
- 'openButtonIcon' => '',
79
- 'intl' => array(
80
- 'locale' => WPSEO_Utils::get_user_locale(),
81
- 'open' => __( 'Open', 'wordpress-seo' ),
82
- 'modalAriaLabel' => null,
83
- 'heading' => null,
84
- 'closeIconButton' => __( 'Close', 'wordpress-seo' ),
85
- 'closeButton' => null,
86
- ),
87
- 'classes' => array(
88
- 'openButton' => '',
89
- 'closeIconButton' => '',
90
- 'closeButton' => '',
91
- ),
92
- 'content' => null,
93
- );
94
-
95
- return $config;
96
- }
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/config-ui/class-configuration-page.php CHANGED
@@ -79,6 +79,7 @@ class WPSEO_Configuration_Page {
79
  */
80
  wp_enqueue_style( 'forms' );
81
  $asset_manager = new WPSEO_Admin_Asset_Manager();
 
82
  $asset_manager->register_assets();
83
  $asset_manager->enqueue_script( 'configuration-wizard' );
84
  $asset_manager->enqueue_style( 'yoast-components' );
79
  */
80
  wp_enqueue_style( 'forms' );
81
  $asset_manager = new WPSEO_Admin_Asset_Manager();
82
+ $asset_manager->register_wp_assets();
83
  $asset_manager->register_assets();
84
  $asset_manager->enqueue_script( 'configuration-wizard' );
85
  $asset_manager->enqueue_style( 'yoast-components' );
admin/config-ui/class-configuration-service.php CHANGED
@@ -108,9 +108,7 @@ class WPSEO_Configuration_Service {
108
  */
109
  protected function populate_configuration() {
110
  // Switch to the user locale with fallback to the site locale.
111
- if ( function_exists( 'switch_to_locale' ) ) {
112
- switch_to_locale( WPSEO_Utils::get_user_locale() );
113
- }
114
 
115
  // Make sure we have our translations available.
116
  wpseo_load_textdomain();
108
  */
109
  protected function populate_configuration() {
110
  // Switch to the user locale with fallback to the site locale.
111
+ switch_to_locale( WPSEO_Language_Utils::get_user_locale() );
 
 
112
 
113
  // Make sure we have our translations available.
114
  wpseo_load_textdomain();
admin/google_search_console/class-gsc-category-filters.php CHANGED
@@ -157,9 +157,11 @@ class WPSEO_GSC_Category_Filters {
157
  );
158
 
159
  $class = 'gsc_category';
 
160
 
161
  if ( $this->category === $category ) {
162
  $class .= ' current';
 
163
  }
164
 
165
  $help_button = '';
@@ -171,14 +173,15 @@ class WPSEO_GSC_Category_Filters {
171
  }
172
 
173
  return sprintf(
174
- '<a href="%1$s" class="%2$s">%3$s</a> (<span id="gsc_count_%4$s">%5$s</span>) %6$s %7$s',
175
  esc_attr( $href ),
176
  $class,
177
  $this->filter_values[ $category ]['value'],
178
  $category,
179
  $count,
180
  $help_button,
181
- $help_panel
 
182
  );
183
  }
184
 
157
  );
158
 
159
  $class = 'gsc_category';
160
+ $aria_current = '';
161
 
162
  if ( $this->category === $category ) {
163
  $class .= ' current';
164
+ $aria_current = ' aria-current="page"';
165
  }
166
 
167
  $help_button = '';
173
  }
174
 
175
  return sprintf(
176
+ '<a href="%1$s" class="%2$s"%8$s>%3$s</a> (<span id="gsc_count_%4$s">%5$s</span>) %6$s %7$s',
177
  esc_attr( $href ),
178
  $class,
179
  $this->filter_values[ $category ]['value'],
180
  $category,
181
  $count,
182
  $help_button,
183
+ $help_panel,
184
+ $aria_current
185
  );
186
  }
187
 
admin/import/class-import-settings.php CHANGED
@@ -11,157 +11,68 @@
11
  * Class with functionality to import the Yoast SEO settings.
12
  */
13
  class WPSEO_Import_Settings {
 
 
14
  /**
15
  * @var WPSEO_Import_Status
16
  */
17
  public $status;
18
 
19
- /**
20
- * @var array
21
- */
22
- private $file;
23
-
24
- /**
25
- * @var string
26
- */
27
- private $filename;
28
-
29
  /**
30
  * @var string
31
  */
32
- private $old_wpseo_version = null;
33
-
34
- /**
35
- * @var string
36
- */
37
- private $path;
38
-
39
- /**
40
- * @var array
41
- */
42
- private $upload_dir;
43
 
44
  /**
45
- * Class constructor
46
  */
47
  public function __construct() {
48
  $this->status = new WPSEO_Import_Status( 'import', false );
49
- if ( ! $this->handle_upload() ) {
50
- return $this->status;
51
- }
52
-
53
- $this->determine_path();
54
-
55
- if ( ! $this->unzip_file() ) {
56
- $this->clean_up();
57
-
58
- return $this->status;
59
- }
60
-
61
- $this->parse_options();
62
-
63
- $this->clean_up();
64
  }
65
 
66
  /**
67
- * Handle the file upload
68
  *
69
- * @return boolean Import status.
70
  */
71
- private function handle_upload() {
72
- $overrides = array( 'mimes' => array( 'zip' => 'application/zip' ) ); // Explicitly allow zip in multisite.
73
- $this->file = wp_handle_upload( $_FILES['settings_import_file'], $overrides );
74
-
75
- if ( is_wp_error( $this->file ) ) {
76
- $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . $this->file->get_error_message() );
77
 
78
- return false;
79
- }
80
-
81
- if ( is_array( $this->file ) && isset( $this->file['error'] ) ) {
82
- $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . $this->file['error'] );
83
-
84
- return false;
85
  }
86
 
87
- if ( ! isset( $this->file['file'] ) ) {
88
- $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . __( 'Upload failed.', 'wordpress-seo' ) );
89
-
90
- return false;
91
  }
92
 
93
- return true;
94
  }
95
 
96
  /**
97
- * Determine the path to the import file
98
- */
99
- private function determine_path() {
100
- $this->upload_dir = wp_upload_dir();
101
-
102
- if ( ! defined( 'DIRECTORY_SEPARATOR' ) ) {
103
- define( 'DIRECTORY_SEPARATOR', '/' );
104
- }
105
- $this->path = $this->upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'wpseo-import' . DIRECTORY_SEPARATOR;
106
-
107
- if ( ! isset( $GLOBALS['wp_filesystem'] ) || ! is_object( $GLOBALS['wp_filesystem'] ) ) {
108
- $url = wp_nonce_url(
109
- self_admin_url( 'admin.php?page=wpseo_tools&tool=import-export' ),
110
- 'wpseo-import'
111
- );
112
- $credentials = request_filesystem_credentials( esc_url_raw( $url ) );
113
- WP_Filesystem( $credentials );
114
- }
115
- }
116
-
117
- /**
118
- * Unzip the file
119
  *
120
- * @return boolean
 
 
121
  */
122
- private function unzip_file() {
123
- $unzipped = unzip_file( $this->file['file'], $this->path );
124
- $msg_base = __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ';
125
-
126
- if ( is_wp_error( $unzipped ) ) {
127
- /* translators: %s expands to an error message. */
128
- $this->status->set_msg( $msg_base . sprintf( __( 'Unzipping failed with error "%s".', 'wordpress-seo' ), $unzipped->get_error_message() ) );
129
-
130
- return false;
131
- }
132
-
133
- $this->filename = $this->path . 'settings.ini';
134
- if ( ! is_file( $this->filename ) || ! is_readable( $this->filename ) ) {
135
- $this->status->set_msg( $msg_base . __( 'Unzipping failed - file settings.ini not found.', 'wordpress-seo' ) );
136
-
137
- return false;
138
  }
139
 
140
- return true;
141
- }
142
-
143
- /**
144
- * Parse the option file
145
- */
146
- private function parse_options() {
147
- if ( defined( 'INI_SCANNER_RAW' ) ) {
148
- /*
149
- * Implemented INI_SCANNER_RAW to make sure variables aren't parsed.
150
- *
151
- * http://php.net/manual/en/function.parse-ini-file.php#99943
152
- */
153
- $options = parse_ini_file( $this->filename, true, INI_SCANNER_RAW );
154
- }
155
- else {
156
- // PHP 5.2 does not implement the 3rd argument, this is a fallback.
157
- $options = parse_ini_file( $this->filename, true );
158
- }
159
 
160
  if ( is_array( $options ) && $options !== array() ) {
161
  $this->import_options( $options );
 
162
  return;
163
  }
164
- $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . __( 'No settings found in file.', 'wordpress-seo' ) );
 
165
  }
166
 
167
  /**
@@ -171,7 +82,7 @@ class WPSEO_Import_Settings {
171
  * @param array $option_group Option group data.
172
  * @param array $options Options data.
173
  */
174
- private function parse_option_group( $name, $option_group, $options ) {
175
  // Make sure that the imported options are cleaned/converted on import.
176
  $option_instance = WPSEO_Options::get_option_instance( $name );
177
  if ( is_object( $option_instance ) && method_exists( $option_instance, 'import' ) ) {
@@ -179,28 +90,12 @@ class WPSEO_Import_Settings {
179
  }
180
  }
181
 
182
- /**
183
- * Remove the files
184
- */
185
- private function clean_up() {
186
- if ( file_exists( $this->filename ) && is_writable( $this->filename ) ) {
187
- unlink( $this->filename );
188
- }
189
- if ( ! empty( $this->file['file'] ) && file_exists( $this->file['file'] ) && is_writable( $this->file['file'] ) ) {
190
- unlink( $this->file['file'] );
191
- }
192
- if ( file_exists( $this->path ) && is_writable( $this->path ) ) {
193
- $wp_file = new WP_Filesystem_Direct( $this->path );
194
- $wp_file->rmdir( $this->path, true );
195
- }
196
- }
197
-
198
  /**
199
  * Imports the options if found.
200
  *
201
- * @param array $options The options parsed from the ini file.
202
  */
203
- private function import_options( $options ) {
204
  if ( isset( $options['wpseo']['version'] ) && $options['wpseo']['version'] !== '' ) {
205
  $this->old_wpseo_version = $options['wpseo']['version'];
206
  }
@@ -208,6 +103,7 @@ class WPSEO_Import_Settings {
208
  foreach ( $options as $name => $option_group ) {
209
  $this->parse_option_group( $name, $option_group, $options );
210
  }
 
211
  $this->status->set_msg( __( 'Settings successfully imported.', 'wordpress-seo' ) );
212
  $this->status->set_status( true );
213
  }
11
  * Class with functionality to import the Yoast SEO settings.
12
  */
13
  class WPSEO_Import_Settings {
14
+ const NONCE_ACTION = 'wpseo-import-settings';
15
+
16
  /**
17
  * @var WPSEO_Import_Status
18
  */
19
  public $status;
20
 
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * @var string
23
  */
24
+ private $old_wpseo_version;
 
 
 
 
 
 
 
 
 
 
25
 
26
  /**
27
+ * Class constructor.
28
  */
29
  public function __construct() {
30
  $this->status = new WPSEO_Import_Status( 'import', false );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
  /**
34
+ * Imports the data submitted by the user.
35
  *
36
+ * @return void
37
  */
38
+ public function import() {
39
+ check_admin_referer( self::NONCE_ACTION );
 
 
 
 
40
 
41
+ if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
42
+ return;
 
 
 
 
 
43
  }
44
 
45
+ $content = filter_input( INPUT_POST, 'settings_import' );
46
+ if ( empty( $content ) ) {
47
+ return;
 
48
  }
49
 
50
+ $this->parse_options( $content );
51
  }
52
 
53
  /**
54
+ * Parse the options.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  *
56
+ * @param string $raw_options The content to parse.
57
+ *
58
+ * @return void
59
  */
60
+ protected function parse_options( $raw_options ) {
61
+ // If we're not on > PHP 5.3, return, as we'll otherwise error out.
62
+ if ( ! defined( 'WPSEO_NAMESPACES' ) || ! WPSEO_NAMESPACES ) {
63
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
+ // @codingStandardsIgnoreLine
67
+ $options = parse_ini_string( $raw_options, true, INI_SCANNER_RAW ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.parse_ini_stringFound -- We won't get to this function if PHP < 5.3 due to the WPSEO_NAMESPACES check above.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  if ( is_array( $options ) && $options !== array() ) {
70
  $this->import_options( $options );
71
+
72
  return;
73
  }
74
+
75
+ $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . __( 'No settings found.', 'wordpress-seo' ) );
76
  }
77
 
78
  /**
82
  * @param array $option_group Option group data.
83
  * @param array $options Options data.
84
  */
85
+ protected function parse_option_group( $name, $option_group, $options ) {
86
  // Make sure that the imported options are cleaned/converted on import.
87
  $option_instance = WPSEO_Options::get_option_instance( $name );
88
  if ( is_object( $option_instance ) && method_exists( $option_instance, 'import' ) ) {
90
  }
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  /**
94
  * Imports the options if found.
95
  *
96
+ * @param array $options The options parsed from the provided settings.
97
  */
98
+ protected function import_options( $options ) {
99
  if ( isset( $options['wpseo']['version'] ) && $options['wpseo']['version'] !== '' ) {
100
  $this->old_wpseo_version = $options['wpseo']['version'];
101
  }
103
  foreach ( $options as $name => $option_group ) {
104
  $this->parse_option_group( $name, $option_group, $options );
105
  }
106
+
107
  $this->status->set_msg( __( 'Settings successfully imported.', 'wordpress-seo' ) );
108
  $this->status->set_status( true );
109
  }
admin/metabox/class-metabox-keyword-synonyms-config.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
- /**
3
- * WPSEO plugin file.
4
- *
5
- * @package WPSEO\Admin\Metabox
6
- */
7
-
8
- /**
9
- * Button to show the premium upsell.
10
- */
11
- class WPSEO_Metabox_Keyword_Synonyms_Config {
12
-
13
- /**
14
- * Enqueues the translations necessary for the synonyms modal + button
15
- *
16
- * @return void
17
- */
18
- public function enqueue_translations() {
19
- $keyword_synonyms_modal_config = array(
20
- 'openButtonIcon' => '',
21
- 'intl' => array(
22
- 'open' => '+ ' . __( 'Add synonyms', 'wordpress-seo' ),
23
- 'modalAriaLabel' =>
24
- /* translators: %s expands to 'Yoast SEO Premium'. */
25
- sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ),
26
- 'heading' =>
27
- /* translators: %s expands to 'Yoast SEO Premium'. */
28
- sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ),
29
- ),
30
- 'classes' => array(
31
- 'openButton' => 'wpseo-keyword-synonyms button-link',
32
- ),
33
- 'content' => 'KeywordSynonyms',
34
- );
35
-
36
- $translations = new WPSEO_Keyword_Synonyms_Modal();
37
- $translations->enqueue_translations();
38
-
39
- Yoast_Modal::add( $keyword_synonyms_modal_config );
40
- }
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/metabox/class-metabox-multiple-keywords-config.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
- /**
3
- * WPSEO plugin file.
4
- *
5
- * @package WPSEO\Admin\Metabox
6
- */
7
-
8
- /**
9
- * Button to show the premium upsell.
10
- */
11
- class WPSEO_Metabox_Multiple_Keywords_Config {
12
-
13
- /**
14
- * Enqueues the translations necessary for the multiple keywords modal + button
15
- *
16
- * @return void
17
- */
18
- public function enqueue_translations() {
19
- $multiple_keywords_modal_config = array(
20
- 'openButtonIcon' => '',
21
- 'intl' => array(
22
- 'open' => '+ ' . __( 'Add related keyphrase', 'wordpress-seo' ),
23
- 'modalAriaLabel' =>
24
- /* translators: %s expands to 'Yoast SEO Premium'. */
25
- sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ),
26
- 'heading' =>
27
- /* translators: %s expands to 'Yoast SEO Premium'. */
28
- sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ),
29
- ),
30
- 'classes' => array(
31
- 'openButton' => 'wpseo-multiple-keywords button-link',
32
- ),
33
- 'content' => 'MultipleKeywords',
34
- );
35
-
36
- $translations = new WPSEO_Multiple_Keywords_Modal();
37
- $translations->enqueue_translations();
38
-
39
- Yoast_Modal::add( $multiple_keywords_modal_config );
40
- }
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/metabox/class-metabox.php CHANGED
@@ -196,7 +196,9 @@ class WPSEO_Metabox extends WPSEO_Meta {
196
  add_meta_box( 'wpseo_meta', $product_title, array(
197
  $this,
198
  'meta_box',
199
- ), $post_type, 'normal', apply_filters( 'wpseo_metabox_prio', 'high' ) );
 
 
200
  }
201
  }
202
 
@@ -820,6 +822,7 @@ class WPSEO_Metabox extends WPSEO_Meta {
820
  wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'post-scraper', 'wpseoAnalysisWorkerL10n', array(
821
  'url' => $analysis_worker_location->get_url( $analysis_worker_location->get_asset(), WPSEO_Admin_Asset::TYPE_JS ),
822
  'keywords_assessment_url' => $used_keywords_assessment_location->get_url( $used_keywords_assessment_location->get_asset(), WPSEO_Admin_Asset::TYPE_JS ),
 
823
  ) );
824
 
825
  /**
196
  add_meta_box( 'wpseo_meta', $product_title, array(
197
  $this,
198
  'meta_box',
199
+ ), $post_type, 'normal', apply_filters( 'wpseo_metabox_prio', 'high' ), array(
200
+ '__block_editor_compatible_meta_box' => true,
201
+ ) );
202
  }
203
  }
204
 
822
  wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'post-scraper', 'wpseoAnalysisWorkerL10n', array(
823
  'url' => $analysis_worker_location->get_url( $analysis_worker_location->get_asset(), WPSEO_Admin_Asset::TYPE_JS ),
824
  'keywords_assessment_url' => $used_keywords_assessment_location->get_url( $used_keywords_assessment_location->get_asset(), WPSEO_Admin_Asset::TYPE_JS ),
825
+ 'log_level' => WPSEO_Utils::get_analysis_worker_log_level(),
826
  ) );
827
 
828
  /**
admin/onpage/class-ryte-service.php CHANGED
@@ -30,6 +30,9 @@ class WPSEO_Ryte_Service {
30
  * @return WP_REST_Response The response object.
31
  */
32
  public function get_statistics() {
 
 
 
33
  $result = false;
34
 
35
  if ( $this->option->is_enabled() ) {
30
  * @return WP_REST_Response The response object.
31
  */
32
  public function get_statistics() {
33
+ // Switch to the user locale with fallback to the site locale.
34
+ switch_to_locale( WPSEO_Language_Utils::get_user_locale() );
35
+
36
  $result = false;
37
 
38
  if ( $this->option->is_enabled() ) {
admin/statistics/class-statistics-service.php CHANGED
@@ -29,7 +29,6 @@ class WPSEO_Statistics_Service {