All in One SEO Pack - Version 4.1.4.2

Version Description

This update adds major improvements and bugfixes.

Download this release

Release Info

Developer arnaudbroes
Plugin Icon 128x128 All in One SEO Pack
Version 4.1.4.2
Comparing to
See all releases

Code changes from version 4.1.2.2 to 4.1.4.2

Files changed (133) hide show
  1. all_in_one_seo_pack.php +2 -2
  2. app/AIOSEO.php +16 -3
  3. app/Common/Admin/Admin.php +242 -117
  4. app/Common/Admin/Notices/Import.php +1 -16
  5. app/Common/Admin/Notices/Review.php +1 -0
  6. app/Common/Admin/PostSettings.php +35 -5
  7. app/Common/Admin/SetupWizard.php +10 -2
  8. app/Common/Admin/SiteHealth.php +12 -12
  9. app/Common/Admin/Usage.php +10 -1
  10. app/Common/Api/Api.php +6 -2
  11. app/Common/Api/Migration.php +5 -8
  12. app/Common/Api/Notifications.php +2 -8
  13. app/Common/Api/PostsTerms.php +62 -38
  14. app/Common/Api/Settings.php +106 -57
  15. app/Common/Api/Sitemaps.php +37 -8
  16. app/Common/Api/Tools.php +10 -8
  17. app/Common/Api/Wizard.php +70 -66
  18. app/Common/Breadcrumbs/Breadcrumbs.php +7 -6
  19. app/Common/Breadcrumbs/Frontend.php +25 -7
  20. app/Common/Breadcrumbs/Widget.php +3 -1
  21. app/Common/HeadlineAnalyzer/HeadlineAnalyzer.php +2 -1
  22. app/Common/ImportExport/Helpers.php +13 -3
  23. app/Common/ImportExport/ImportExport.php +43 -0
  24. app/Common/ImportExport/RankMath/GeneralSettings.php +2 -2
  25. app/Common/ImportExport/RankMath/TitleMeta.php +16 -16
  26. app/Common/ImportExport/SeoPress/Analytics.php +34 -0
  27. app/Common/ImportExport/SeoPress/Breadcrumbs.php +57 -0
  28. app/Common/ImportExport/SeoPress/GeneralSettings.php +130 -0
  29. app/Common/ImportExport/SeoPress/Helpers.php +88 -9
  30. app/Common/ImportExport/SeoPress/PostMeta.php +174 -0
  31. app/Common/ImportExport/SeoPress/RobotsTxt.php +50 -0
  32. app/Common/ImportExport/SeoPress/Rss.php +47 -0
  33. app/Common/ImportExport/SeoPress/SearchAppearance.php +0 -46
  34. app/Common/ImportExport/SeoPress/SeoPress.php +57 -11
  35. app/Common/ImportExport/SeoPress/Sitemap.php +74 -0
  36. app/Common/ImportExport/SeoPress/SocialMeta.php +130 -0
  37. app/Common/ImportExport/SeoPress/Titles.php +288 -0
  38. app/Common/ImportExport/YoastSeo/GeneralSettings.php +0 -19
  39. app/Common/ImportExport/YoastSeo/PostMeta.php +47 -7
  40. app/Common/ImportExport/YoastSeo/SearchAppearance.php +18 -18
  41. app/Common/ImportExport/YoastSeo/SocialMeta.php +61 -0
  42. app/Common/ImportExport/YoastSeo/UserMeta.php +68 -0
  43. app/Common/ImportExport/YoastSeo/YoastSeo.php +12 -0
  44. app/Common/Main/Activate.php +10 -0
  45. app/Common/Main/Filters.php +63 -5
  46. app/Common/Main/Main.php +44 -10
  47. app/Common/Main/Media.php +2 -2
  48. app/Common/Main/Updates.php +229 -1
  49. app/Common/Meta/Description.php +9 -9
  50. app/Common/Meta/Helpers.php +18 -1
  51. app/Common/Meta/Keywords.php +6 -6
  52. app/Common/Meta/Robots.php +52 -50
  53. app/Common/Meta/Title.php +14 -14
  54. app/Common/Migration/GeneralSettings.php +26 -26
  55. app/Common/Migration/Helpers.php +3 -3
  56. app/Common/Migration/Meta.php +18 -2
  57. app/Common/Migration/Sitemap.php +10 -7
  58. app/Common/Migration/SocialMeta.php +3 -3
  59. app/Common/Models/Model.php +3 -115
  60. app/Common/Models/Notification.php +80 -5
  61. app/Common/Models/Post.php +41 -11
  62. app/Common/Options/Cache.php +93 -0
  63. app/Common/Options/DynamicBackup.php +319 -0
  64. app/Common/Options/DynamicOptions.php +387 -0
  65. app/Common/{Utils → Options}/InternalOptions.php +14 -12
  66. app/Common/{Utils → Options}/Options.php +108 -471
  67. app/Common/Rss.php +2 -2
  68. app/Common/Schema/Breadcrumb.php +1 -1
  69. app/Common/Schema/Graphs/Article.php +1 -0
  70. app/Common/Schema/Graphs/BreadcrumbList.php +2 -2
  71. app/Common/Schema/Graphs/Graph.php +21 -4
  72. app/Common/Schema/Graphs/WebPage.php +7 -3
  73. app/Common/Schema/Graphs/WebSite.php +5 -1
  74. app/Common/Schema/Schema.php +8 -7
  75. app/Common/Sitemap/Content.php +9 -9
  76. app/Common/Sitemap/Helpers.php +22 -7
  77. app/Common/Sitemap/Html/Block.php +137 -0
  78. app/Common/Sitemap/Html/CompactArchive.php +108 -0
  79. app/Common/Sitemap/Html/Frontend.php +498 -0
  80. app/Common/Sitemap/Html/Query.php +262 -0
  81. app/Common/Sitemap/Html/Shortcode.php +36 -0
  82. app/Common/Sitemap/Html/Sitemap.php +189 -0
  83. app/Common/Sitemap/Html/Widget.php +196 -0
  84. app/Common/Sitemap/Image.php +42 -46
  85. app/Common/Sitemap/Priority.php +9 -4
  86. app/Common/Sitemap/Query.php +66 -55
  87. app/Common/Sitemap/Root.php +3 -3
  88. app/Common/Sitemap/Sitemap.php +2 -1
  89. app/Common/Social/Facebook.php +209 -7
  90. app/Common/Social/Helpers.php +0 -69
  91. app/Common/Social/Output.php +1 -0
  92. app/Common/Social/Social.php +0 -1
  93. app/Common/Social/Twitter.php +17 -2
  94. app/Common/Tools/Htaccess.php +2 -1
  95. app/Common/Tools/RobotsTxt.php +30 -9
  96. app/Common/Traits/Helpers/ActionScheduler.php +12 -0
  97. app/Common/Traits/Helpers/Arrays.php +85 -0
  98. app/Common/Traits/Helpers/Constants.php +15 -1
  99. app/Common/Traits/Helpers/DateTime.php +37 -0
  100. app/Common/Traits/Helpers/Language.php +40 -0
  101. app/Common/Traits/Helpers/Strings.php +122 -1
  102. app/Common/Traits/Helpers/Svg.php +51 -0
  103. app/Common/Traits/Helpers/ThirdParty.php +338 -0
  104. app/Common/Traits/Helpers/Vue.php +367 -0
  105. app/Common/Traits/Helpers/Wp.php +549 -0
  106. app/Common/Traits/Helpers/WpContext.php +489 -0
  107. app/Common/Traits/Helpers/WpUri.php +306 -0
  108. app/Common/Traits/Options.php +198 -62
  109. app/Common/Utils/Access.php +88 -55
  110. app/Common/Utils/Addons.php +80 -4
  111. app/Common/Utils/Database.php +11 -29
  112. app/Common/Utils/Helpers.php +93 -2105
  113. app/Common/Utils/Templates.php +2 -2
  114. app/Common/Utils/VueSettings.php +12 -6
  115. app/Common/Views/admin/posts/columns.php +3 -1
  116. app/Common/Views/main/meta.php +2 -2
  117. app/Common/Views/sitemap/html/compact-archive.php +16 -0
  118. app/Common/Views/sitemap/html/widget-options.php +192 -0
  119. app/Lite/Admin/Admin.php +5 -3
  120. app/Lite/Admin/Connect.php +2 -1
  121. app/Lite/Main/Updates.php +0 -44
  122. app/Lite/Meta/Main.php +0 -26
  123. app/Lite/Options/InternalOptions.php +42 -0
  124. app/Lite/Options/Options.php +34 -0
  125. app/Lite/Traits/Options.php +98 -0
  126. app/Lite/Utils/InternalOptions.php +0 -102
  127. app/Lite/Utils/Options.php +0 -107
  128. dist/Lite/assets/css/aioseo-admin-bar.css +2 -2
  129. dist/Lite/assets/css/aioseo-admin-bar.css.gz +0 -0
  130. dist/Lite/assets/css/app.css +1 -1
  131. dist/Lite/assets/css/app.rtl.css +1 -1
  132. dist/Lite/assets/css/chunk-common.css +1 -1
  133. dist/Lite/assets/css/chunk-common.rtl.css +1 -1
all_in_one_seo_pack.php CHANGED
@@ -2,10 +2,10 @@
2
  /**
3
  * Plugin Name: All in One SEO
4
  * Plugin URI: https://aioseo.com/
5
- * Description: SEO for WordPress. Features like XML Sitemaps, SEO for custom post types, SEO for blogs, business sites, ecommerce sites, and much more. More than 75 million downloads since 2007.
6
  * Author: All in One SEO Team
7
  * Author URI: https://aioseo.com/
8
- * Version: 4.1.2.2
9
  * Text Domain: all-in-one-seo-pack
10
  * Domain Path: /i18n/
11
  *
2
  /**
3
  * Plugin Name: All in One SEO
4
  * Plugin URI: https://aioseo.com/
5
+ * Description: SEO for WordPress. Features like XML Sitemaps, SEO for custom post types, SEO for blogs, business sites, ecommerce sites, and much more. More than 80 million downloads since 2007.
6
  * Author: All in One SEO Team
7
  * Author URI: https://aioseo.com/
8
+ * Version: 4.1.4.2
9
  * Text Domain: all-in-one-seo-pack
10
  * Domain Path: /i18n/
11
  *
app/AIOSEO.php CHANGED
@@ -57,6 +57,15 @@ namespace AIOSEO\Plugin {
57
  */
58
  public $options = [];
59
 
 
 
 
 
 
 
 
 
 
60
  /**
61
  * The WordPress filters to run.
62
  *
@@ -275,8 +284,11 @@ namespace AIOSEO\Plugin {
275
  $this->badBotBlocker = new Common\Tools\BadBotBlocker();
276
  $this->headlineAnalyzer = new Common\HeadlineAnalyzer\HeadlineAnalyzer();
277
  $this->breadcrumbs = $this->pro ? new Pro\Breadcrumbs\Breadcrumbs() : new Common\Breadcrumbs\Breadcrumbs();
278
- $this->internalOptions = $this->pro ? new Pro\Utils\InternalOptions() : new Lite\Utils\InternalOptions();
279
- $this->options = $this->pro ? new Pro\Utils\Options() : new Lite\Utils\Options();
 
 
 
280
  $this->backup = new Common\Utils\Backup();
281
  $this->access = $this->pro ? new Pro\Utils\Access() : new Common\Utils\Access();
282
  $this->usage = $this->pro ? new Pro\Admin\Usage() : new Lite\Admin\Usage();
@@ -295,6 +307,7 @@ namespace AIOSEO\Plugin {
295
  $this->migration = $this->pro ? new Pro\Migration\Migration() : new Common\Migration\Migration();
296
  $this->importExport = $this->pro ? new Pro\ImportExport\ImportExport() : new Common\ImportExport\ImportExport();
297
  $this->sitemap = $this->pro ? new Pro\Sitemap\Sitemap() : new Common\Sitemap\Sitemap();
 
298
  $this->templates = new Common\Utils\Templates();
299
 
300
  if ( ! wp_doing_ajax() && ! wp_doing_cron() ) {
@@ -333,7 +346,7 @@ namespace AIOSEO\Plugin {
333
  $this->badBotBlocker->init();
334
 
335
  // We call this again to reset any post types/taxonomies that have not yet been set up.
336
- $this->options->refresh();
337
  }
338
 
339
  /**
57
  */
58
  public $options = [];
59
 
60
+ /**
61
+ * The AIOSEO dynamic options.
62
+ *
63
+ * @since 4.1.4
64
+ *
65
+ * @var array
66
+ */
67
+ public $dynamicOptions = [];
68
+
69
  /**
70
  * The WordPress filters to run.
71
  *
284
  $this->badBotBlocker = new Common\Tools\BadBotBlocker();
285
  $this->headlineAnalyzer = new Common\HeadlineAnalyzer\HeadlineAnalyzer();
286
  $this->breadcrumbs = $this->pro ? new Pro\Breadcrumbs\Breadcrumbs() : new Common\Breadcrumbs\Breadcrumbs();
287
+ $this->dynamicBackup = $this->pro ? new Pro\Options\DynamicBackup() : new Common\Options\DynamicBackup();
288
+ $this->optionsCache = new Common\Options\Cache();
289
+ $this->internalOptions = $this->pro ? new Pro\Options\InternalOptions() : new Lite\Options\InternalOptions();
290
+ $this->options = $this->pro ? new Pro\Options\Options() : new Lite\Options\Options();
291
+ $this->dynamicOptions = $this->pro ? new Pro\Options\DynamicOptions() : new Common\Options\DynamicOptions();
292
  $this->backup = new Common\Utils\Backup();
293
  $this->access = $this->pro ? new Pro\Utils\Access() : new Common\Utils\Access();
294
  $this->usage = $this->pro ? new Pro\Admin\Usage() : new Lite\Admin\Usage();
307
  $this->migration = $this->pro ? new Pro\Migration\Migration() : new Common\Migration\Migration();
308
  $this->importExport = $this->pro ? new Pro\ImportExport\ImportExport() : new Common\ImportExport\ImportExport();
309
  $this->sitemap = $this->pro ? new Pro\Sitemap\Sitemap() : new Common\Sitemap\Sitemap();
310
+ $this->htmlSitemap = new Common\Sitemap\Html\Sitemap();
311
  $this->templates = new Common\Utils\Templates();
312
 
313
  if ( ! wp_doing_ajax() && ! wp_doing_cron() ) {
346
  $this->badBotBlocker->init();
347
 
348
  // We call this again to reset any post types/taxonomies that have not yet been set up.
349
+ $this->dynamicOptions->refresh();
350
  }
351
 
352
  /**
app/Common/Admin/Admin.php CHANGED
@@ -42,6 +42,15 @@ class Admin {
42
  */
43
  protected $pages = [];
44
 
 
 
 
 
 
 
 
 
 
45
  /**
46
  * An array of items to add to the admin bar.
47
  *
@@ -63,113 +72,113 @@ class Admin {
63
  return;
64
  }
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  $this->pages = [
67
  $this->pageSlug => [
68
  'menu_title' => esc_html__( 'Dashboard', 'all-in-one-seo-pack' ),
69
- 'capability' => apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' ),
70
  'parent' => $this->pageSlug
71
  ],
72
  'aioseo-settings' => [
73
  'menu_title' => esc_html__( 'General Settings', 'all-in-one-seo-pack' ),
74
- 'capability' => 'aioseo_general_settings',
75
  'parent' => $this->pageSlug
76
  ],
77
  'aioseo-search-appearance' => [
78
  'menu_title' => esc_html__( 'Search Appearance', 'all-in-one-seo-pack' ),
79
- 'capability' => 'aioseo_search_appearance_settings',
80
  'parent' => $this->pageSlug
81
  ],
82
  'aioseo-social-networks' => [
83
  'menu_title' => esc_html__( 'Social Networks', 'all-in-one-seo-pack' ),
84
- 'capability' => 'aioseo_social_networks_settings',
85
  'parent' => $this->pageSlug
86
  ],
87
  'aioseo-sitemaps' => [
88
  'menu_title' => esc_html__( 'Sitemaps', 'all-in-one-seo-pack' ),
89
- 'capability' => 'aioseo_sitemap_settings',
90
  'parent' => $this->pageSlug
91
  ],
92
  // 'aioseo-internal-links' => [
93
  // 'menu_title' => esc_html__( 'Internal Links', 'all-in-one-seo-pack' ),
94
- // 'capability' => 'aioseo_internal_links_settings',
95
  // 'parent' => $this->pageSlug
96
  // ],
97
  'aioseo-redirects' => [
98
  'menu_title' => esc_html__( 'Redirects', 'all-in-one-seo-pack' ),
99
- 'capability' => 'aioseo_redirects_settings',
100
  'parent' => $this->pageSlug
101
  ],
102
  'aioseo-local-seo' => [
103
  'menu_title' => esc_html__( 'Local SEO', 'all-in-one-seo-pack' ),
104
- 'capability' => 'aioseo_local_seo_settings',
105
  'parent' => $this->pageSlug
106
  ],
107
  'aioseo-seo-analysis' => [
108
  'menu_title' => esc_html__( 'SEO Analysis', 'all-in-one-seo-pack' ),
109
- 'capability' => 'aioseo_seo_analysis_settings',
110
  'parent' => $this->pageSlug
111
  ],
112
  'aioseo-tools' => [
113
  'menu_title' => esc_html__( 'Tools', 'all-in-one-seo-pack' ),
114
- 'capability' => 'aioseo_tools_settings',
115
  'parent' => $this->pageSlug
116
  ],
117
  'aioseo-feature-manager' => [
118
  'menu_title' => esc_html__( 'Feature Manager', 'all-in-one-seo-pack' ),
119
- 'capability' => 'aioseo_feature_manager_settings',
120
  'parent' => $this->pageSlug
121
  ],
122
  'aioseo-monsterinsights' => [
123
  'menu_title' => esc_html__( 'Analytics', 'all-in-one-seo-pack' ),
124
- 'capability' => apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' ),
125
  'parent' => 'aioseo-monsterinsights'
126
  ],
127
  'aioseo-about' => [
128
  'menu_title' => esc_html__( 'About Us', 'all-in-one-seo-pack' ),
129
- 'capability' => apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' ),
130
  'parent' => $this->pageSlug
131
  ]
132
  ];
133
-
134
- add_action( 'sanitize_comment_cookies', [ $this, 'init' ], 20 );
135
-
136
- $this->setupWizard = new SetupWizard();
137
- }
138
-
139
- /**
140
- * Initialize the admin.
141
- *
142
- * @since 4.0.0
143
- *
144
- * @return void
145
- */
146
- public function init() {
147
- // Add the admin bar menu.
148
- if ( is_user_logged_in() && current_user_can( 'aioseo_manage_seo' ) && ( ! is_multisite() || ! is_network_admin() ) ) {
149
- add_action( 'admin_bar_menu', [ $this, 'adminBarMenu' ], 1000 );
150
- }
151
-
152
- if ( is_admin() ) {
153
- // Add the menu to the sidebar.
154
- add_action( 'admin_menu', [ $this, 'addMenu' ] );
155
- add_action( 'admin_menu', [ $this, 'hideScheduledActionsMenu' ], 99999 );
156
- if ( is_multisite() ) {
157
- add_action( 'network_admin_menu', [ $this, 'addRobotsMenu' ] );
158
- }
159
-
160
- // Add the columns to page/posts.
161
- add_action( 'current_screen', [ $this, 'addPostColumns' ], 1 );
162
-
163
- // Add Score to Publish metabox.
164
- add_action( 'post_submitbox_misc_actions', [ $this, 'addPublishScore' ] );
165
-
166
- add_action( 'admin_init', [ $this, 'addPluginScripts' ] );
167
-
168
- // Add redirects messages to trashed posts.
169
- add_filter( 'bulk_post_updated_messages', [ $this, 'appendTrashedMessage' ], 10, 2 );
170
-
171
- $this->registerLinkFormatHooks();
172
- }
173
  }
174
 
175
  /**
@@ -320,14 +329,20 @@ class Admin {
320
  return;
321
  }
322
 
323
- $count = count( Models\Notification::getAllActiveNotifications() );
324
- $count = 10 > $count ? $count : '!';
325
- $count = $count ? '<div class="aioseo-menu-notification-counter">' . $count . '</div>' : '';
 
 
 
 
 
 
326
 
327
  $this->adminBarMenuItems[] = [
328
  'id' => 'aioseo-main',
329
- 'title' => '<div class="ab-item aioseo-logo svg"></div><span class="text">' . esc_html__( 'SEO', 'all-in-one-seo-pack' ) . '</span>' . wp_kses_post( $count ),
330
- 'href' => esc_url( admin_url( 'admin.php?page=aioseo' ) )
331
  ];
332
 
333
  if ( $count ) {
@@ -335,24 +350,30 @@ class Admin {
335
  'parent' => 'aioseo-main',
336
  'id' => 'aioseo-notifications',
337
  'title' => esc_html__( 'Notifications', 'all-in-one-seo-pack' ) . ' <div class="aioseo-menu-notification-indicator"></div>',
338
- 'href' => admin_url( 'admin.php?page=aioseo&notifications=true' ),
339
  ];
340
  }
341
 
342
- if ( ! is_admin() ) {
 
343
  $this->addPageAnalyzerMenuItems();
344
  }
345
 
346
- $this->addSettingsMenuItems();
347
- $this->addPostMenuItems();
 
 
348
 
349
- // Add the menu bar items.
350
  $this->addAdminBarMenuItems();
 
351
  }
352
 
353
  /**
354
  * Actually adds the menu items to the admin bar.
355
  *
 
 
356
  * @return void
357
  */
358
  protected function addAdminBarMenuItems() {
@@ -497,6 +518,10 @@ class Admin {
497
  continue;
498
  }
499
 
 
 
 
 
500
  $this->adminBarMenuItems[] = [
501
  'id' => $id,
502
  'parent' => $parent,
@@ -508,6 +533,7 @@ class Admin {
508
 
509
  /**
510
  * Retreive data to build the admin bar.
 
511
  * @since 4.0.0
512
  *
513
  * @param WP_Post $post The post object.
@@ -538,6 +564,18 @@ class Admin {
538
  }
539
  }
540
 
 
 
 
 
 
 
 
 
 
 
 
 
541
  /**
542
  * Add the menu inside of WordPress.
543
  *
@@ -553,23 +591,40 @@ class Admin {
553
  $page['parent'],
554
  ! empty( $page['page_title'] ) ? $page['page_title'] : $page['menu_title'],
555
  $page['menu_title'],
556
- $page['capability'],
557
  $slug,
558
  [ $this, 'page' ]
559
  );
560
  add_action( "load-{$hook}", [ $this, 'hooks' ] );
 
561
 
562
- if ( ! current_user_can( 'aioseo_admin' ) ) {
563
- remove_submenu_page( 'aioseo', 'aioseo' );
564
- }
565
  }
566
 
567
  global $submenu;
568
- $submenu['tools.php'][] = [
569
- esc_html__( 'Redirection Manager', 'all-in-one-seo-pack' ),
570
- apply_filters( 'aioseo_redirects_settings', 'aioseo_redirects_settings' ),
571
- admin_url( '/admin.php?page=aioseo-redirects' )
572
- ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
  }
574
 
575
  /**
@@ -606,7 +661,7 @@ class Admin {
606
  add_menu_page(
607
  $this->menuName,
608
  $this->menuName,
609
- apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' ),
610
  $slug,
611
  '__return_true',
612
  'data:image/svg+xml;base64,' . base64_encode( aioseo()->helpers->logo( 16, 16, '#A0A5AA' ) ),
@@ -743,44 +798,8 @@ class Admin {
743
  remove_all_actions( 'admin_notices' );
744
  remove_all_actions( 'all_admin_notices' );
745
 
746
- // Scripts.
747
- aioseo()->helpers->enqueueScript(
748
- 'aioseo-vendors',
749
- 'js/chunk-vendors.js'
750
- );
751
- aioseo()->helpers->enqueueScript(
752
- 'aioseo-common',
753
- 'js/chunk-common.js'
754
- );
755
- aioseo()->helpers->enqueueScript(
756
- 'aioseo-' . $page . '-script',
757
- 'js/' . $page . '.js'
758
- );
759
-
760
- // Styles.
761
- $rtl = is_rtl() ? '.rtl' : '';
762
- aioseo()->helpers->enqueueStyle(
763
- 'aioseo-vendors',
764
- "css/chunk-vendors$rtl.css"
765
- );
766
- aioseo()->helpers->enqueueStyle(
767
- 'aioseo-common',
768
- "css/chunk-common$rtl.css"
769
- );
770
- // aioseo()->helpers->enqueueStyle(
771
- // 'aioseo-' . $page . '-style',
772
- // 'css/' . $page . $rtl . '.css'
773
- // );
774
- // aioseo()->helpers->enqueueStyle(
775
- // 'aioseo-' . $page . '-vendors-style',
776
- // 'css/chunk-' . $page . $rtl . '-vendors.css'
777
- // );
778
-
779
- wp_localize_script(
780
- 'aioseo-' . $page . '-script',
781
- 'aioseo',
782
- aioseo()->helpers->getVueData( $page )
783
- );
784
 
785
  add_action( 'admin_footer_text', [ $this, 'addFooterText' ] );
786
 
@@ -797,6 +816,55 @@ class Admin {
797
  }
798
  }
799
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
800
  /**
801
  * Add footer text to the WordPress admin screens.
802
  *
@@ -940,11 +1008,13 @@ class Admin {
940
  * @return array The modified columns.
941
  */
942
  public function postColumns( $columns ) {
943
- $pageAnalysisCapability = aioseo()->access->hasCapability( 'aioseo_page_analysis' );
944
- $generalSettingsCapability = aioseo()->access->hasCapability( 'aioseo_page_general_settings' );
945
  if (
946
- ! current_user_can( 'aioseo_manage_seo' ) ||
947
- ( empty( $pageAnalysisCapability ) && empty( $generalSettingsCapability ) )
 
 
 
948
  ) {
949
  return $columns;
950
  }
@@ -968,6 +1038,7 @@ class Admin {
968
  if ( ! current_user_can( 'edit_post', $postId ) && ! current_user_can( 'aioseo_manage_seo' ) ) {
969
  return;
970
  }
 
971
  if ( 'aioseo-details' === $columnName ) {
972
  // Add this column/post to the localized array.
973
  global $wp_scripts;
@@ -1050,7 +1121,7 @@ class Admin {
1050
  $postTypes = aioseo()->helpers->getPublicPostTypes();
1051
  $showTruSeo = aioseo()->options->advanced->truSeo;
1052
  $isSpecialPage = aioseo()->helpers->isSpecialPage( $post->ID );
1053
- $showMetabox = aioseo()->options->searchAppearance->dynamic->postTypes->{$post->post_type}->advanced->showMetaBox;
1054
 
1055
  $postTypesMB = [];
1056
  foreach ( $postTypes as $pt ) {
@@ -1084,7 +1155,7 @@ class Admin {
1084
  echo sprintf( esc_html__( '%1$s Score', 'all-in-one-seo-pack' ), esc_html( AIOSEO_PLUGIN_SHORT_NAME ) );
1085
  ?>
1086
  </span>
1087
- <div id="aioseo-post-settings-sidebar-button" class="aioseo-score-button classic-editor <?php echo esc_attr( aioseo()->helpers->getScoreClass( $score ) ); ?>">
1088
  <span id="aioseo-post-score"><?php echo esc_attr( $score . '/100' ); ?></span>
1089
  </div>
1090
  </div>
@@ -1210,6 +1281,28 @@ class Admin {
1210
  ];
1211
  }
1212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1213
  /**
1214
  * Updates deprecated options.
1215
  *
@@ -1298,4 +1391,36 @@ class Admin {
1298
  $messages['page']['trashed'] = $messages['page']['trashed'] . '&nbsp;<a href="' . $url . '">' . $addRedirect . '</a> |';
1299
  return $messages;
1300
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1301
  }
42
  */
43
  protected $pages = [];
44
 
45
+ /**
46
+ * The current page we are enqueuing.
47
+ *
48
+ * @since 4.1.3
49
+ *
50
+ * @var string
51
+ */
52
+ protected $currentPage;
53
+
54
  /**
55
  * An array of items to add to the admin bar.
56
  *
72
  return;
73
  }
74
 
75
+ add_action( 'sanitize_comment_cookies', [ $this, 'init' ], 20 );
76
+
77
+ $this->setupWizard = new SetupWizard();
78
+ }
79
+
80
+ /**
81
+ * Initialize the admin.
82
+ *
83
+ * @since 4.0.0
84
+ *
85
+ * @return void
86
+ */
87
+ public function init() {
88
+ // Add the admin bar menu.
89
+ if ( is_user_logged_in() && ( ! is_multisite() || ! is_network_admin() ) ) {
90
+ add_action( 'admin_bar_menu', [ $this, 'adminBarMenu' ], 1000 );
91
+ }
92
+
93
+ if ( is_admin() ) {
94
+ // Add the menu to the sidebar.
95
+ add_action( 'admin_menu', [ $this, 'addMenu' ] );
96
+ add_action( 'admin_menu', [ $this, 'hideScheduledActionsMenu' ], 99999 );
97
+ if ( is_multisite() ) {
98
+ add_action( 'network_admin_menu', [ $this, 'addRobotsMenu' ] );
99
+ }
100
+
101
+ // Add the columns to page/posts.
102
+ add_action( 'current_screen', [ $this, 'addPostColumns' ], 1 );
103
+
104
+ // Add Score to Publish metabox.
105
+ add_action( 'post_submitbox_misc_actions', [ $this, 'addPublishScore' ] );
106
+
107
+ add_action( 'admin_init', [ $this, 'addPluginScripts' ] );
108
+
109
+ // Add redirects messages to trashed posts.
110
+ add_filter( 'bulk_post_updated_messages', [ $this, 'appendTrashedMessage' ], 10, 2 );
111
+
112
+ $this->registerLinkFormatHooks();
113
+ }
114
+
115
+ $this->loadTextDomain();
116
+ $this->setPages();
117
+ }
118
+
119
+ /**
120
+ * Sets our menu pages.
121
+ * It is important this runs AFTER we've loaded the text domain.
122
+ *
123
+ * @since 4.1.4
124
+ *
125
+ * @return void
126
+ */
127
+ private function setPages() {
128
  $this->pages = [
129
  $this->pageSlug => [
130
  'menu_title' => esc_html__( 'Dashboard', 'all-in-one-seo-pack' ),
 
131
  'parent' => $this->pageSlug
132
  ],
133
  'aioseo-settings' => [
134
  'menu_title' => esc_html__( 'General Settings', 'all-in-one-seo-pack' ),
 
135
  'parent' => $this->pageSlug
136
  ],
137
  'aioseo-search-appearance' => [
138
  'menu_title' => esc_html__( 'Search Appearance', 'all-in-one-seo-pack' ),
 
139
  'parent' => $this->pageSlug
140
  ],
141
  'aioseo-social-networks' => [
142
  'menu_title' => esc_html__( 'Social Networks', 'all-in-one-seo-pack' ),
 
143
  'parent' => $this->pageSlug
144
  ],
145
  'aioseo-sitemaps' => [
146
  'menu_title' => esc_html__( 'Sitemaps', 'all-in-one-seo-pack' ),
 
147
  'parent' => $this->pageSlug
148
  ],
149
  // 'aioseo-internal-links' => [
150
  // 'menu_title' => esc_html__( 'Internal Links', 'all-in-one-seo-pack' ),
 
151
  // 'parent' => $this->pageSlug
152
  // ],
153
  'aioseo-redirects' => [
154
  'menu_title' => esc_html__( 'Redirects', 'all-in-one-seo-pack' ),
 
155
  'parent' => $this->pageSlug
156
  ],
157
  'aioseo-local-seo' => [
158
  'menu_title' => esc_html__( 'Local SEO', 'all-in-one-seo-pack' ),
 
159
  'parent' => $this->pageSlug
160
  ],
161
  'aioseo-seo-analysis' => [
162
  'menu_title' => esc_html__( 'SEO Analysis', 'all-in-one-seo-pack' ),
 
163
  'parent' => $this->pageSlug
164
  ],
165
  'aioseo-tools' => [
166
  'menu_title' => esc_html__( 'Tools', 'all-in-one-seo-pack' ),
 
167
  'parent' => $this->pageSlug
168
  ],
169
  'aioseo-feature-manager' => [
170
  'menu_title' => esc_html__( 'Feature Manager', 'all-in-one-seo-pack' ),
 
171
  'parent' => $this->pageSlug
172
  ],
173
  'aioseo-monsterinsights' => [
174
  'menu_title' => esc_html__( 'Analytics', 'all-in-one-seo-pack' ),
 
175
  'parent' => 'aioseo-monsterinsights'
176
  ],
177
  'aioseo-about' => [
178
  'menu_title' => esc_html__( 'About Us', 'all-in-one-seo-pack' ),
 
179
  'parent' => $this->pageSlug
180
  ]
181
  ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
 
184
  /**
329
  return;
330
  }
331
 
332
+ $firstPageSlug = $this->getFirstAvailablePageSlug();
333
+ if ( ! $firstPageSlug ) {
334
+ return;
335
+ }
336
+
337
+ $count = count( Models\Notification::getAllActiveNotifications() );
338
+ $htmlCount = 10 > $count ? $count : '!';
339
+ $htmlCount = $htmlCount ? '<div class="aioseo-menu-notification-counter">' . $htmlCount . '</div>' : '';
340
+ $htmlCount .= '<div id="aioseo-menu-new-notifications"></div>';
341
 
342
  $this->adminBarMenuItems[] = [
343
  'id' => 'aioseo-main',
344
+ 'title' => '<div class="ab-item aioseo-logo svg"></div><span class="text">' . esc_html__( 'SEO', 'all-in-one-seo-pack' ) . '</span>' . wp_kses_post( $htmlCount ),
345
+ 'href' => esc_url( admin_url( 'admin.php?page=' . $firstPageSlug ) )
346
  ];
347
 
348
  if ( $count ) {
350
  'parent' => 'aioseo-main',
351
  'id' => 'aioseo-notifications',
352
  'title' => esc_html__( 'Notifications', 'all-in-one-seo-pack' ) . ' <div class="aioseo-menu-notification-indicator"></div>',
353
+ 'href' => admin_url( 'admin.php?page=' . $firstPageSlug . '&notifications=true' ),
354
  ];
355
  }
356
 
357
+ $htmlSitemapRequested = aioseo()->htmlSitemap->isDedicatedPage;
358
+ if ( ! is_admin() && ! $htmlSitemapRequested ) {
359
  $this->addPageAnalyzerMenuItems();
360
  }
361
 
362
+ if ( $htmlSitemapRequested ) {
363
+ global $wp_admin_bar;
364
+ $wp_admin_bar->remove_node( 'edit' );
365
+ }
366
 
367
+ $this->addSettingsMenuItems();
368
  $this->addAdminBarMenuItems();
369
+ $this->addPostMenuItems();
370
  }
371
 
372
  /**
373
  * Actually adds the menu items to the admin bar.
374
  *
375
+ * @since 4.0.0
376
+ *
377
  * @return void
378
  */
379
  protected function addAdminBarMenuItems() {
518
  continue;
519
  }
520
 
521
+ if ( ! current_user_can( $this->getPageRequiredCapability( $id ) ) ) {
522
+ continue;
523
+ }
524
+
525
  $this->adminBarMenuItems[] = [
526
  'id' => $id,
527
  'parent' => $parent,
533
 
534
  /**
535
  * Retreive data to build the admin bar.
536
+ *
537
  * @since 4.0.0
538
  *
539
  * @param WP_Post $post The post object.
564
  }
565
  }
566
 
567
+ /**
568
+ * Get the required capability for given admin page.
569
+ *
570
+ * @since 4.1.3
571
+ *
572
+ * @param string $pageSlug The slug of the page.
573
+ * @return string The required capability.
574
+ */
575
+ public function getPageRequiredCapability( $pageSlug ) { // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
576
+ return apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' );
577
+ }
578
+
579
  /**
580
  * Add the menu inside of WordPress.
581
  *
591
  $page['parent'],
592
  ! empty( $page['page_title'] ) ? $page['page_title'] : $page['menu_title'],
593
  $page['menu_title'],
594
+ $this->getPageRequiredCapability( $slug ),
595
  $slug,
596
  [ $this, 'page' ]
597
  );
598
  add_action( "load-{$hook}", [ $this, 'hooks' ] );
599
+ }
600
 
601
+ if ( ! current_user_can( $this->getPageRequiredCapability( $this->pageSlug ) ) ) {
602
+ remove_submenu_page( $this->pageSlug, $this->pageSlug );
 
603
  }
604
 
605
  global $submenu;
606
+ if ( current_user_can( $this->getPageRequiredCapability( 'aioseo-redirects' ) ) ) {
607
+ $submenu['tools.php'][] = [
608
+ esc_html__( 'Redirection Manager', 'all-in-one-seo-pack' ),
609
+ $this->getPageRequiredCapability( 'aioseo-redirects' ),
610
+ admin_url( '/admin.php?page=aioseo-redirects' )
611
+ ];
612
+ }
613
+
614
+ // We use the global submenu, because we are adding an external link here.
615
+ $count = count( Models\Notification::getAllActiveNotifications() );
616
+ $firstPageSlug = $this->getFirstAvailablePageSlug();
617
+ if (
618
+ $count &&
619
+ ! empty( $submenu[ $this->pageSlug ] ) &&
620
+ ! empty( $firstPageSlug )
621
+ ) {
622
+ array_unshift( $submenu[ $this->pageSlug ], [
623
+ esc_html__( 'Notifications', 'all-in-one-seo-pack' ) . '<div class="aioseo-menu-notification-indicator"></div>',
624
+ $this->getPageRequiredCapability( $firstPageSlug ),
625
+ admin_url( 'admin.php?page=' . $firstPageSlug . '&notifications=true' )
626
+ ] );
627
+ }
628
  }
629
 
630
  /**
661
  add_menu_page(
662
  $this->menuName,
663
  $this->menuName,
664
+ $this->getPageRequiredCapability( $slug ),
665
  $slug,
666
  '__return_true',
667
  'data:image/svg+xml;base64,' . base64_encode( aioseo()->helpers->logo( 16, 16, '#A0A5AA' ) ),
798
  remove_all_actions( 'admin_notices' );
799
  remove_all_actions( 'all_admin_notices' );
800
 
801
+ $this->currentPage = $page;
802
+ add_action( 'admin_enqueue_scripts', [ $this, 'enqueueAssets' ], 11 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
803
 
804
  add_action( 'admin_footer_text', [ $this, 'addFooterText' ] );
805
 
816
  }
817
  }
818
 
819
+ /**
820
+ * Enqueue admin assets for the current page.
821
+ *
822
+ * @since 4.1.3
823
+ *
824
+ * @return void
825
+ */
826
+ public function enqueueAssets() {
827
+ // Scripts.
828
+ aioseo()->helpers->enqueueScript(
829
+ 'aioseo-vendors',
830
+ 'js/chunk-vendors.js'
831
+ );
832
+ aioseo()->helpers->enqueueScript(
833
+ 'aioseo-common',
834
+ 'js/chunk-common.js'
835
+ );
836
+ aioseo()->helpers->enqueueScript(
837
+ 'aioseo-' . $this->currentPage . '-script',
838
+ 'js/' . $this->currentPage . '.js'
839
+ // [ 'aioseo-common', 'aioseo-venders', 'aioseo-app' ]
840
+ );
841
+
842
+ // Styles.
843
+ $rtl = is_rtl() ? '.rtl' : '';
844
+ aioseo()->helpers->enqueueStyle(
845
+ 'aioseo-vendors',
846
+ "css/chunk-vendors$rtl.css"
847
+ );
848
+ aioseo()->helpers->enqueueStyle(
849
+ 'aioseo-common',
850
+ "css/chunk-common$rtl.css"
851
+ );
852
+ // aioseo()->helpers->enqueueStyle(
853
+ // 'aioseo-' . $this->currentPage . '-style',
854
+ // 'css/' . $this->currentPage . $rtl . '.css'
855
+ // );
856
+ // aioseo()->helpers->enqueueStyle(
857
+ // 'aioseo-' . $this->currentPage . '-vendors-style',
858
+ // 'css/chunk-' . $this->currentPage . $rtl . '-vendors.css'
859
+ // );
860
+
861
+ wp_localize_script(
862
+ 'aioseo-' . $this->currentPage . '-script',
863
+ 'aioseo',
864
+ aioseo()->helpers->getVueData( $this->currentPage )
865
+ );
866
+ }
867
+
868
  /**
869
  * Add footer text to the WordPress admin screens.
870
  *
1008
  * @return array The modified columns.
1009
  */
1010
  public function postColumns( $columns ) {
1011
+ $canManageSeo = apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' );
 
1012
  if (
1013
+ ! current_user_can( $canManageSeo ) &&
1014
+ (
1015
+ ! current_user_can( 'aioseo_page_general_settings' ) &&
1016
+ ! current_user_can( 'aioseo_page_analysis' )
1017
+ )
1018
  ) {
1019
  return $columns;
1020
  }
1038
  if ( ! current_user_can( 'edit_post', $postId ) && ! current_user_can( 'aioseo_manage_seo' ) ) {
1039
  return;
1040
  }
1041
+
1042
  if ( 'aioseo-details' === $columnName ) {
1043
  // Add this column/post to the localized array.
1044
  global $wp_scripts;
1121
  $postTypes = aioseo()->helpers->getPublicPostTypes();
1122
  $showTruSeo = aioseo()->options->advanced->truSeo;
1123
  $isSpecialPage = aioseo()->helpers->isSpecialPage( $post->ID );
1124
+ $showMetabox = aioseo()->dynamicOptions->searchAppearance->postTypes->{$post->post_type}->advanced->showMetaBox;
1125
 
1126
  $postTypesMB = [];
1127
  foreach ( $postTypes as $pt ) {
1155
  echo sprintf( esc_html__( '%1$s Score', 'all-in-one-seo-pack' ), esc_html( AIOSEO_PLUGIN_SHORT_NAME ) );
1156
  ?>
1157
  </span>
1158
+ <div id="aioseo-post-settings-sidebar-button" class="aioseo-score-button classic-editor <?php echo esc_attr( $this->getScoreClass( $score ) ); ?>">
1159
  <span id="aioseo-post-score"><?php echo esc_attr( $score . '/100' ); ?></span>
1160
  </div>
1161
  </div>
1281
  ];
1282
  }
1283
 
1284
+ /**
1285
+ * Get the first available page item for the current user.
1286
+ *
1287
+ * @since 4.1.3
1288
+ *
1289
+ * @return bool|string The page slug.
1290
+ */
1291
+ public function getFirstAvailablePageSlug() {
1292
+ foreach ( $this->pages as $slug => $page ) {
1293
+ // Ignore other pages.
1294
+ if ( $this->pageSlug !== $page['parent'] ) {
1295
+ continue;
1296
+ }
1297
+
1298
+ if ( current_user_can( $this->getPageRequiredCapability( $slug ) ) ) {
1299
+ return $slug;
1300
+ }
1301
+ }
1302
+
1303
+ return false;
1304
+ }
1305
+
1306
  /**
1307
  * Updates deprecated options.
1308
  *
1391
  $messages['page']['trashed'] = $messages['page']['trashed'] . '&nbsp;<a href="' . $url . '">' . $addRedirect . '</a> |';
1392
  return $messages;
1393
  }
1394
+
1395
+ /**
1396
+ * Get the class name for the Score button.
1397
+ * Depending on the score the button should have different color.
1398
+ *
1399
+ * @since 4.0.0
1400
+ *
1401
+ * @param int $score The content to retrieve from the remote URL.
1402
+ *
1403
+ * @return string The class name for Score button.
1404
+ */
1405
+ private function getScoreClass( $score ) {
1406
+ $scoreClass = 50 < $score ? 'score-orange' : 'score-red';
1407
+ if ( 0 === $score ) {
1408
+ $scoreClass = 'score-none';
1409
+ }
1410
+ if ( $score >= 80 ) {
1411
+ $scoreClass = 'score-green';
1412
+ }
1413
+ return $scoreClass;
1414
+ }
1415
+
1416
+ /**
1417
+ * Loads the plugin text domain.
1418
+ *
1419
+ * @since 4.1.4
1420
+ *
1421
+ * @return void
1422
+ */
1423
+ public function loadTextDomain() {
1424
+ aioseo()->helpers->loadTextDomain( 'all-in-one-seo-pack' );
1425
+ }
1426
  }
app/Common/Admin/Notices/Import.php CHANGED
@@ -20,22 +20,7 @@ class Import {
20
  * @return void
21
  */
22
  public function maybeShowNotice() {
23
- $transients = aioseo()->db
24
- ->start( 'options' )
25
- ->select( 'option_name as name' )
26
- ->whereRaw( "`option_name` LIKE '_aioseo_cache_%'" )
27
- ->run()
28
- ->result();
29
-
30
- $foundImportTransient = false;
31
- foreach ( $transients as $transient ) {
32
- if ( preg_match( '#import_.*_meta_.*#', $transient->name ) ) {
33
- $foundImportTransient = true;
34
- break;
35
- }
36
- }
37
-
38
- if ( ! $foundImportTransient ) {
39
  return;
40
  }
41
 
20
  * @return void
21
  */
22
  public function maybeShowNotice() {
23
+ if ( ! aioseo()->importExport->isImportRunning() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  return;
25
  }
26
 
app/Common/Admin/Notices/Review.php CHANGED
@@ -137,6 +137,7 @@ class Review {
137
  * Print the script for dismissing the notice.
138
  *
139
  * @since 4.0.13
 
140
  * @return void
141
  */
142
  public function printScript() {
137
  * Print the script for dismissing the notice.
138
  *
139
  * @since 4.0.13
140
+ *
141
  * @return void
142
  */
143
  public function printScript() {
app/Common/Admin/PostSettings.php CHANGED
@@ -71,6 +71,10 @@ class PostSettings {
71
  aioseo()->helpers->getVueData( $page )
72
  );
73
 
 
 
 
 
74
  $rtl = is_rtl() ? '.rtl' : '';
75
  aioseo()->helpers->enqueueStyle(
76
  'aioseo-post-settings-metabox',
@@ -84,6 +88,26 @@ class PostSettings {
84
  }
85
  }
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  /**
88
  * Adds a meta box to page/posts screens.
89
  *
@@ -92,9 +116,9 @@ class PostSettings {
92
  * @return void
93
  */
94
  public function addPostSettingsMetabox() {
95
- $options = aioseo()->options->noConflict();
96
- $screen = get_current_screen();
97
- $postType = $screen->post_type;
98
 
99
  $pageAnalysisSettingsCapability = aioseo()->access->hasCapability( 'aioseo_page_analysis' );
100
  $generalSettingsCapability = aioseo()->access->hasCapability( 'aioseo_page_general_settings' );
@@ -103,8 +127,8 @@ class PostSettings {
103
  $advancedSettingsCapability = aioseo()->access->hasCapability( 'aioseo_page_advanced_settings' );
104
 
105
  if (
106
- $options->searchAppearance->dynamic->postTypes->has( $postType ) &&
107
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->showMetaBox &&
108
  ! (
109
  empty( $pageAnalysisSettingsCapability ) &&
110
  empty( $generalSettingsCapability ) &&
@@ -195,6 +219,12 @@ class PostSettings {
195
 
196
  $currentPost = json_decode( stripslashes( $_POST['aioseo-post-settings'] ), true ); // phpcs:ignore HM.Security.ValidatedSanitizedInput
197
 
 
 
 
 
 
 
198
  Models\Post::savePost( $postId, $currentPost );
199
 
200
  }
71
  aioseo()->helpers->getVueData( $page )
72
  );
73
 
74
+ if ( 'post' === $page ) {
75
+ $this->enqueuePublishPanelAssets();
76
+ }
77
+
78
  $rtl = is_rtl() ? '.rtl' : '';
79
  aioseo()->helpers->enqueueStyle(
80
  'aioseo-post-settings-metabox',
88
  }
89
  }
90
 
91
+ /**
92
+ * Enqueues the JS/CSS for the Block Editor integrations.
93
+ *
94
+ * @since 4.1.4
95
+ *
96
+ * @return void
97
+ */
98
+ private function enqueuePublishPanelAssets() {
99
+ aioseo()->helpers->enqueueScript(
100
+ 'aioseo-publish-panel',
101
+ 'js/publish-panel.js'
102
+ );
103
+
104
+ $rtl = is_rtl() ? '.rtl' : '';
105
+ aioseo()->helpers->enqueueStyle(
106
+ 'aioseo-publish-panel',
107
+ "css/publish-panel$rtl.css"
108
+ );
109
+ }
110
+
111
  /**
112
  * Adds a meta box to page/posts screens.
113
  *
116
  * @return void
117
  */
118
  public function addPostSettingsMetabox() {
119
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
120
+ $screen = get_current_screen();
121
+ $postType = $screen->post_type;
122
 
123
  $pageAnalysisSettingsCapability = aioseo()->access->hasCapability( 'aioseo_page_analysis' );
124
  $generalSettingsCapability = aioseo()->access->hasCapability( 'aioseo_page_general_settings' );
127
  $advancedSettingsCapability = aioseo()->access->hasCapability( 'aioseo_page_advanced_settings' );
128
 
129
  if (
130
+ $dynamicOptions->searchAppearance->postTypes->has( $postType ) &&
131
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->showMetaBox &&
132
  ! (
133
  empty( $pageAnalysisSettingsCapability ) &&
134
  empty( $generalSettingsCapability ) &&
219
 
220
  $currentPost = json_decode( stripslashes( $_POST['aioseo-post-settings'] ), true ); // phpcs:ignore HM.Security.ValidatedSanitizedInput
221
 
222
+ // If there is no data, there likely was an error, e.g. if the hidden field wasn't populated on load and the user saved the post without making changes in the metabox - #2254
223
+ // In that case we should return to prevent a complete reset of the data.
224
+ if ( empty( $currentPost ) ) {
225
+ return;
226
+ }
227
+
228
  Models\Post::savePost( $postId, $currentPost );
229
 
230
  }
app/Common/Admin/SetupWizard.php CHANGED
@@ -64,7 +64,7 @@ class SetupWizard {
64
  * @return void
65
  */
66
  public function addDashboardPage() {
67
- add_dashboard_page( '', '', 'aioseo_setup_wizard', 'aioseo-setup-wizard', '' );
68
  remove_submenu_page( 'index.php', 'aioseo-setup-wizard' );
69
  }
70
 
@@ -87,7 +87,7 @@ class SetupWizard {
87
  if (
88
  ! isset( $_GET['page'] ) ||
89
  'aioseo-setup-wizard' !== wp_unslash( $_GET['page'] ) || // phpcs:ignore HM.Security.ValidatedSanitizedInput.InputNotSanitized
90
- ! current_user_can( 'aioseo_setup_wizard' )
91
  ) {
92
  return;
93
  }
@@ -169,6 +169,14 @@ class SetupWizard {
169
  aioseo()->helpers->getVueData( 'setup-wizard' )
170
  );
171
 
 
 
 
 
 
 
 
 
172
  wp_enqueue_style( 'common' );
173
  wp_enqueue_media();
174
  }
64
  * @return void
65
  */
66
  public function addDashboardPage() {
67
+ add_dashboard_page( '', '', aioseo()->admin->getPageRequiredCapability( 'aioseo-setup-wizard' ), 'aioseo-setup-wizard', '' );
68
  remove_submenu_page( 'index.php', 'aioseo-setup-wizard' );
69
  }
70
 
87
  if (
88
  ! isset( $_GET['page'] ) ||
89
  'aioseo-setup-wizard' !== wp_unslash( $_GET['page'] ) || // phpcs:ignore HM.Security.ValidatedSanitizedInput.InputNotSanitized
90
+ ! current_user_can( aioseo()->admin->getPageRequiredCapability( 'aioseo-setup-wizard' ) )
91
  ) {
92
  return;
93
  }
169
  aioseo()->helpers->getVueData( 'setup-wizard' )
170
  );
171
 
172
+ wp_localize_script(
173
+ 'aioseo-setup-wizard-script',
174
+ 'aioseoTranslations',
175
+ [
176
+ 'translations' => aioseo()->helpers->getJedLocaleData( 'all-in-one-seo-pack' )
177
+ ]
178
+ );
179
+
180
  wp_enqueue_style( 'common' );
181
  wp_enqueue_media();
182
  }
app/Common/Admin/SiteHealth.php CHANGED
@@ -335,9 +335,9 @@ class SiteHealth {
335
 
336
  foreach ( aioseo()->helpers->getPublicPostTypes() as $postType ) {
337
  if (
338
- aioseo()->options->searchAppearance->dynamic->postTypes->has( $postType['name'] ) &&
339
- ! aioseo()->options->searchAppearance->dynamic->postTypes->{ $postType['name'] }->advanced->robotsMeta->default &&
340
- aioseo()->options->searchAppearance->dynamic->postTypes->{ $postType['name'] }->advanced->robotsMeta->noindex
341
  ) {
342
  $noindexed[] = $postType['label'] . ' (' . $postType['name'] . ')';
343
  }
@@ -345,9 +345,9 @@ class SiteHealth {
345
 
346
  foreach ( aioseo()->helpers->getPublicTaxonomies() as $taxonomy ) {
347
  if (
348
- aioseo()->options->searchAppearance->dynamic->taxonomies->has( $taxonomy['name'] ) &&
349
- ! aioseo()->options->searchAppearance->dynamic->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->default &&
350
- aioseo()->options->searchAppearance->dynamic->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->noindex
351
  ) {
352
  $noindexed[] = $taxonomy['label'] . ' (' . $taxonomy['name'] . ')';
353
  }
@@ -401,9 +401,9 @@ class SiteHealth {
401
 
402
  foreach ( aioseo()->helpers->getPublicPostTypes() as $postType ) {
403
  if (
404
- aioseo()->options->searchAppearance->dynamic->postTypes->has( $postType['name'] ) &&
405
- ! aioseo()->options->searchAppearance->dynamic->postTypes->{ $postType['name'] }->advanced->robotsMeta->default &&
406
- aioseo()->options->searchAppearance->dynamic->postTypes->{ $postType['name'] }->advanced->robotsMeta->nofollow
407
  ) {
408
  $nofollowed[] = $postType['label'] . ' (' . $postType['name'] . ')';
409
  }
@@ -411,9 +411,9 @@ class SiteHealth {
411
 
412
  foreach ( aioseo()->helpers->getPublicTaxonomies() as $taxonomy ) {
413
  if (
414
- aioseo()->options->searchAppearance->dynamic->taxonomies->has( $taxonomy['name'] ) &&
415
- ! aioseo()->options->searchAppearance->dynamic->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->default &&
416
- aioseo()->options->searchAppearance->dynamic->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->nofollow
417
  ) {
418
  $nofollowed[] = $taxonomy['label'] . ' (' . $taxonomy['name'] . ')';
419
  }
335
 
336
  foreach ( aioseo()->helpers->getPublicPostTypes() as $postType ) {
337
  if (
338
+ aioseo()->dynamicOptions->searchAppearance->postTypes->has( $postType['name'] ) &&
339
+ ! aioseo()->dynamicOptions->searchAppearance->postTypes->{ $postType['name'] }->advanced->robotsMeta->default &&
340
+ aioseo()->dynamicOptions->searchAppearance->postTypes->{ $postType['name'] }->advanced->robotsMeta->noindex
341
  ) {
342
  $noindexed[] = $postType['label'] . ' (' . $postType['name'] . ')';
343
  }
345
 
346
  foreach ( aioseo()->helpers->getPublicTaxonomies() as $taxonomy ) {
347
  if (
348
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->has( $taxonomy['name'] ) &&
349
+ ! aioseo()->dynamicOptions->searchAppearance->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->default &&
350
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->noindex
351
  ) {
352
  $noindexed[] = $taxonomy['label'] . ' (' . $taxonomy['name'] . ')';
353
  }
401
 
402
  foreach ( aioseo()->helpers->getPublicPostTypes() as $postType ) {
403
  if (
404
+ aioseo()->dynamicOptions->searchAppearance->postTypes->has( $postType['name'] ) &&
405
+ ! aioseo()->dynamicOptions->searchAppearance->postTypes->{ $postType['name'] }->advanced->robotsMeta->default &&
406
+ aioseo()->dynamicOptions->searchAppearance->postTypes->{ $postType['name'] }->advanced->robotsMeta->nofollow
407
  ) {
408
  $nofollowed[] = $postType['label'] . ' (' . $postType['name'] . ')';
409
  }
411
 
412
  foreach ( aioseo()->helpers->getPublicTaxonomies() as $taxonomy ) {
413
  if (
414
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->has( $taxonomy['name'] ) &&
415
+ ! aioseo()->dynamicOptions->searchAppearance->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->default &&
416
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->{ $taxonomy['name'] }->advanced->robotsMeta->nofollow
417
  ) {
418
  $nofollowed[] = $taxonomy['label'] . ' (' . $taxonomy['name'] . ')';
419
  }
app/Common/Admin/Usage.php CHANGED
@@ -11,7 +11,16 @@ if ( ! defined( 'ABSPATH' ) ) {
11
  *
12
  * @since 4.0.0
13
  */
14
- class Usage {
 
 
 
 
 
 
 
 
 
15
  /**
16
  * Source of notifications content.
17
  *
11
  *
12
  * @since 4.0.0
13
  */
14
+ abstract class Usage {
15
+ /**
16
+ * Returns the current plugin version type ("lite" or "pro").
17
+ *
18
+ * @since 4.1.3
19
+ *
20
+ * @return string The version type.
21
+ */
22
+ abstract public function getType();
23
+
24
  /**
25
  * Source of notifications content.
26
  *
app/Common/Api/Api.php CHANGED
@@ -85,7 +85,6 @@ class Api {
85
  'aioseo_search_appearance_settings',
86
  'aioseo_social_networks_settings',
87
  'aioseo_sitemap_settings',
88
- 'aioseo_internal_links_settings',
89
  'aioseo_redirects_settings',
90
  'aioseo_seo_analysis_settings',
91
  'aioseo_tools_settings',
@@ -106,6 +105,7 @@ class Api {
106
  'settings/do-task' => [ 'callback' => [ 'Settings', 'doTask' ], 'access' => 'aioseo_tools_settings' ],
107
  'sitemap/deactivate-conflicting-plugins' => [ 'callback' => [ 'Sitemaps', 'deactivateConflictingPlugins' ] ],
108
  'sitemap/delete-static-files' => [ 'callback' => [ 'Sitemaps', 'deleteStaticFiles' ] ],
 
109
  'tools/delete-robots-txt' => [ 'callback' => [ 'Tools', 'deleteRobotsTxt' ], 'access' => 'aioseo_tools_settings' ],
110
  'tools/import-robots-txt' => [ 'callback' => [ 'Tools', 'importRobotsTxt' ], 'access' => 'aioseo_tools_settings' ],
111
  'wizard' => [ 'callback' => [ 'Wizard', 'saveWizard' ], 'access' => 'aioseo_setup_wizard' ],
@@ -224,7 +224,7 @@ class Api {
224
  * @param \WP_REST_Request $request The REST Request.
225
  * @return bool True if validated, false if not.
226
  */
227
- private function validateAccess( $request ) {
228
  $route = str_replace( '/' . $this->namespace . '/', '', $request->get_route() );
229
  $routeData = isset( $this->getRoutes()[ $request->get_method() ][ $route ] ) ? $this->getRoutes()[ $request->get_method() ][ $route ] : [];
230
 
@@ -242,6 +242,10 @@ class Api {
242
  }
243
  }
244
 
 
 
 
 
245
  return false;
246
  }
247
  }
85
  'aioseo_search_appearance_settings',
86
  'aioseo_social_networks_settings',
87
  'aioseo_sitemap_settings',
 
88
  'aioseo_redirects_settings',
89
  'aioseo_seo_analysis_settings',
90
  'aioseo_tools_settings',
105
  'settings/do-task' => [ 'callback' => [ 'Settings', 'doTask' ], 'access' => 'aioseo_tools_settings' ],
106
  'sitemap/deactivate-conflicting-plugins' => [ 'callback' => [ 'Sitemaps', 'deactivateConflictingPlugins' ] ],
107
  'sitemap/delete-static-files' => [ 'callback' => [ 'Sitemaps', 'deleteStaticFiles' ] ],
108
+ 'sitemap/validate-html-sitemap-slug' => [ 'callback' => [ 'Sitemaps', 'validateHtmlSitemapSlug' ] ],
109
  'tools/delete-robots-txt' => [ 'callback' => [ 'Tools', 'deleteRobotsTxt' ], 'access' => 'aioseo_tools_settings' ],
110
  'tools/import-robots-txt' => [ 'callback' => [ 'Tools', 'importRobotsTxt' ], 'access' => 'aioseo_tools_settings' ],
111
  'wizard' => [ 'callback' => [ 'Wizard', 'saveWizard' ], 'access' => 'aioseo_setup_wizard' ],
224
  * @param \WP_REST_Request $request The REST Request.
225
  * @return bool True if validated, false if not.
226
  */
227
+ public function validateAccess( $request ) {
228
  $route = str_replace( '/' . $this->namespace . '/', '', $request->get_route() );
229
  $routeData = isset( $this->getRoutes()[ $request->get_method() ][ $route ] ) ? $this->getRoutes()[ $request->get_method() ][ $route ] : [];
230
 
242
  }
243
  }
244
 
245
+ if ( current_user_can( apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' ) ) ) {
246
+ return true;
247
+ }
248
+
249
  return false;
250
  }
251
  }
app/Common/Api/Migration.php CHANGED
@@ -39,13 +39,13 @@ class Migration {
39
  }
40
 
41
  $objectName = $match[1];
42
- if ( in_array( $objectName, $postTypes, true ) && aioseo()->options->searchAppearance->dynamic->postTypes->has( $objectName ) ) {
43
- aioseo()->options->searchAppearance->dynamic->postTypes->$objectName->title = '#post_title #separator_sa #site_title';
44
  continue;
45
  }
46
 
47
- if ( in_array( $objectName, $taxonomies, true ) && aioseo()->options->searchAppearance->dynamic->taxonomies->has( $objectName ) ) {
48
- aioseo()->options->searchAppearance->dynamic->taxonomies->$objectName->title = '#taxonomy_title #separator_sa #site_title';
49
  }
50
  }
51
 
@@ -56,10 +56,7 @@ class Migration {
56
  return new \WP_REST_Response( [
57
  'success' => true,
58
  'message' => 'Title formats have been reset; post/term migration has been scheduled.',
59
- 'notifications' => [
60
- 'active' => Models\Notification::getAllActiveNotifications(),
61
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
62
- ]
63
  ], 200 );
64
  }
65
  }
39
  }
40
 
41
  $objectName = $match[1];
42
+ if ( in_array( $objectName, $postTypes, true ) && aioseo()->dynamicOptions->searchAppearance->postTypes->has( $objectName ) ) {
43
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$objectName->title = '#post_title #separator_sa #site_title';
44
  continue;
45
  }
46
 
47
+ if ( in_array( $objectName, $taxonomies, true ) && aioseo()->dynamicOptions->searchAppearance->taxonomies->has( $objectName ) ) {
48
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$objectName->title = '#taxonomy_title #separator_sa #site_title';
49
  }
50
  }
51
 
56
  return new \WP_REST_Response( [
57
  'success' => true,
58
  'message' => 'Title formats have been reset; post/term migration has been scheduled.',
59
+ 'notifications' => Models\Notification::getNotifications()
 
 
 
60
  ], 200 );
61
  }
62
  }
app/Common/Api/Notifications.php CHANGED
@@ -171,10 +171,7 @@ class Notifications {
171
 
172
  return new \WP_REST_Response( [
173
  'success' => true,
174
- 'notifications' => [
175
- 'active' => Models\Notification::getAllActiveNotifications(),
176
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
177
- ]
178
  ], 200 );
179
  }
180
 
@@ -211,10 +208,7 @@ class Notifications {
211
 
212
  return new \WP_REST_Response( [
213
  'success' => true,
214
- 'notifications' => [
215
- 'active' => Models\Notification::getAllActiveNotifications(),
216
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
217
- ]
218
  ], 200 );
219
  }
220
  }
171
 
172
  return new \WP_REST_Response( [
173
  'success' => true,
174
+ 'notifications' => Models\Notification::getNotifications()
 
 
 
175
  ], 200 );
176
  }
177
 
208
 
209
  return new \WP_REST_Response( [
210
  'success' => true,
211
+ 'notifications' => Models\Notification::getNotifications()
 
 
 
212
  ], 200 );
213
  }
214
  }
app/Common/Api/PostsTerms.php CHANGED
@@ -38,41 +38,51 @@ class PostsTerms {
38
  ], 400 );
39
  }
40
 
41
- $objects = [];
42
- $options = aioseo()->options->noConflict();
 
 
43
  if ( 'posts' === $body['type'] ) {
44
 
45
  $postTypes = aioseo()->helpers->getPublicPostTypes( true );
46
  foreach ( $postTypes as $postType ) {
47
  // Check if post type isn't noindexed.
48
- if ( $options->searchAppearance->dynamic->postTypes->has( $postType ) && ! $options->searchAppearance->dynamic->postTypes->$postType->show ) {
49
  $postTypes = aioseo()->helpers->unsetValue( $postTypes, $postType );
50
  }
51
  }
52
 
53
- $objects = get_posts( [
54
- 's' => $body['query'],
55
- 'numberposts' => 20,
56
- 'post_status' => [ 'publish', 'draft' ],
57
- 'post_type' => $postTypes,
58
- 'orderby' => 'post_title'
59
- ] );
 
 
 
 
60
  } elseif ( 'terms' === $body['type'] ) {
61
 
62
  $taxonomies = aioseo()->helpers->getPublicTaxonomies( true );
63
  foreach ( $taxonomies as $taxonomy ) {
64
  // Check if taxonomy isn't noindexed.
65
- if ( $options->searchAppearance->dynamic->taxonomies->has( $taxonomy ) && ! $options->searchAppearance->dynamic->taxonomies->$taxonomy->show ) {
66
  $taxonomies = aioseo()->helpers->unsetValue( $taxonomies, $taxonomy );
67
  }
68
  }
69
 
70
- $objects = get_terms( [
71
- 'name__like' => $body['query'],
72
- 'number' => 20,
73
- 'taxonomy' => $taxonomies,
74
- 'orderby' => 'name'
75
- ] );
 
 
 
 
76
  }
77
 
78
  if ( empty( $objects ) ) {
@@ -87,14 +97,16 @@ class PostsTerms {
87
  if ( 'posts' === $body['type'] ) {
88
  $parsed[] = [
89
  'type' => $object->post_type,
90
- 'value' => $object->ID,
 
91
  'label' => $object->post_title,
92
  'link' => get_permalink( $object->ID )
93
  ];
94
  } elseif ( 'terms' === $body['type'] ) {
95
  $parsed[] = [
96
  'type' => $object->taxonomy,
97
- 'value' => $object->term_id,
 
98
  'label' => $object->name,
99
  'link' => get_term_link( $object->term_id )
100
  ];
@@ -125,11 +137,7 @@ class PostsTerms {
125
  ], 400 );
126
  }
127
 
128
- $thePost = aioseo()->db
129
- ->start( 'aioseo_posts' )
130
- ->where( 'post_id', $args['postId'] )
131
- ->run()
132
- ->model( 'AIOSEO\\Plugin\\Common\\Models\\Post' );
133
 
134
  return new \WP_REST_Response( [
135
  'success' => true,
@@ -137,12 +145,35 @@ class PostsTerms {
137
  'postData' => [
138
  'parsedTitle' => aioseo()->tags->replaceTags( $thePost->title, $args['postId'] ),
139
  'parsedDescription' => aioseo()->tags->replaceTags( $thePost->description, $args['postId'] ),
140
- 'content' => aioseo()->helpers->doShortcodes( aioseo()->helpers->getAnalysisContent( $args['postId'] ) ),
141
  'slug' => get_post_field( 'post_name', $args['postId'] )
142
  ]
143
  ], 200 );
144
  }
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  /**
147
  * Update post settings.
148
  *
@@ -173,12 +204,13 @@ class PostsTerms {
173
  $body['twitter_title'] = ! empty( $body['twitter_title'] ) ? sanitize_text_field( $body['twitter_title'] ) : null;
174
  $body['twitter_description'] = ! empty( $body['twitter_description'] ) ? sanitize_text_field( $body['twitter_description'] ) : null;
175
 
176
- $saveStatus = Models\Post::savePost( $postId, $body );
 
177
 
178
- if ( ! empty( $saveStatus ) ) {
179
  return new \WP_REST_Response( [
180
  'success' => false,
181
- 'message' => 'Failed update query: ' . $saveStatus
182
  ], 401 );
183
  }
184
 
@@ -209,11 +241,7 @@ class PostsTerms {
209
  ], 400 );
210
  }
211
 
212
- $thePost = aioseo()->db
213
- ->start( 'aioseo_posts' )
214
- ->where( 'post_id', $postId )
215
- ->run()
216
- ->model( 'AIOSEO\\Plugin\\Common\\Models\\Post' );
217
 
218
  if ( $thePost->exists() ) {
219
  $metaTitle = aioseo()->meta->title->getPostTypeTitle( $post->post_type );
@@ -290,11 +318,7 @@ class PostsTerms {
290
  ], 400 );
291
  }
292
 
293
- $thePost = aioseo()->db
294
- ->start( 'aioseo_posts' )
295
- ->where( 'post_id', $postId )
296
- ->run()
297
- ->model( 'AIOSEO\\Plugin\\Common\\Models\\Post' );
298
 
299
  $thePost->post_id = $postId;
300
  if ( ! empty( $body['keyphrases'] ) ) {
38
  ], 400 );
39
  }
40
 
41
+ $searchQuery = aioseo()->db->db->esc_like( $body['query'] );
42
+
43
+ $objects = [];
44
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
45
  if ( 'posts' === $body['type'] ) {
46
 
47
  $postTypes = aioseo()->helpers->getPublicPostTypes( true );
48
  foreach ( $postTypes as $postType ) {
49
  // Check if post type isn't noindexed.
50
+ if ( $dynamicOptions->searchAppearance->postTypes->has( $postType ) && ! $dynamicOptions->searchAppearance->postTypes->$postType->show ) {
51
  $postTypes = aioseo()->helpers->unsetValue( $postTypes, $postType );
52
  }
53
  }
54
 
55
+ $objects = aioseo()->db
56
+ ->start( 'posts' )
57
+ ->select( 'ID, post_type, post_title, post_name' )
58
+ ->whereRaw( "( post_title LIKE '%{$searchQuery}%' OR post_name LIKE '%{$searchQuery}%' OR ID = '{$searchQuery}' )" )
59
+ ->whereIn( 'post_type', $postTypes )
60
+ ->whereIn( 'post_status', [ 'publish', 'draft', 'future', 'pending' ] )
61
+ ->orderBy( 'post_title' )
62
+ ->limit( 10 )
63
+ ->run()
64
+ ->result();
65
+
66
  } elseif ( 'terms' === $body['type'] ) {
67
 
68
  $taxonomies = aioseo()->helpers->getPublicTaxonomies( true );
69
  foreach ( $taxonomies as $taxonomy ) {
70
  // Check if taxonomy isn't noindexed.
71
+ if ( $dynamicOptions->searchAppearance->taxonomies->has( $taxonomy ) && ! $dynamicOptions->searchAppearance->taxonomies->$taxonomy->show ) {
72
  $taxonomies = aioseo()->helpers->unsetValue( $taxonomies, $taxonomy );
73
  }
74
  }
75
 
76
+ $objects = aioseo()->db
77
+ ->start( 'terms as t' )
78
+ ->select( 't.term_id as term_id, t.slug as slug, t.name as name, tt.taxonomy as taxonomy' )
79
+ ->join( 'term_taxonomy as tt', 't.term_id = tt.term_id', 'INNER' )
80
+ ->whereRaw( "( t.name LIKE '%{$searchQuery}%' OR t.slug LIKE '%{$searchQuery}%' OR t.term_id = '{$searchQuery}' )" )
81
+ ->whereIn( 'tt.taxonomy', $taxonomies )
82
+ ->orderBy( 't.name' )
83
+ ->limit( 10 )
84
+ ->run()
85
+ ->result();
86
  }
87
 
88
  if ( empty( $objects ) ) {
97
  if ( 'posts' === $body['type'] ) {
98
  $parsed[] = [
99
  'type' => $object->post_type,
100
+ 'value' => (int) $object->ID,
101
+ 'slug' => $object->post_name,
102
  'label' => $object->post_title,
103
  'link' => get_permalink( $object->ID )
104
  ];
105
  } elseif ( 'terms' === $body['type'] ) {
106
  $parsed[] = [
107
  'type' => $object->taxonomy,
108
+ 'value' => (int) $object->term_id,
109
+ 'slug' => $object->slug,
110
  'label' => $object->name,
111
  'link' => get_term_link( $object->term_id )
112
  ];
137
  ], 400 );
138
  }
139
 
140
+ $thePost = Models\Post::getPost( $args['postId'] );
 
 
 
 
141
 
142
  return new \WP_REST_Response( [
143
  'success' => true,
145
  'postData' => [
146
  'parsedTitle' => aioseo()->tags->replaceTags( $thePost->title, $args['postId'] ),
147
  'parsedDescription' => aioseo()->tags->replaceTags( $thePost->description, $args['postId'] ),
148
+ 'content' => aioseo()->helpers->doShortcodes( self::getAnalysisContent( $args['postId'] ) ),
149
  'slug' => get_post_field( 'post_name', $args['postId'] )
150
  ]
151
  ], 200 );
152
  }
153
 
154
+ /**
155
+ * Returns the posts custom fields.
156
+ *
157
+ * @since 4.0.6
158
+ *
159
+ * @param WP_Post|int $post The post.
160
+ * @return string The custom field content.
161
+ */
162
+ private static function getAnalysisContent( $post = null ) {
163
+ $post = ( $post && is_object( $post ) ) ? $post : aioseo()->helpers->getPost( $post );
164
+ $customFieldKeys = aioseo()->dynamicOptions->searchAppearance->postTypes->{$post->post_type}->customFields;
165
+
166
+ if ( empty( $customFieldKeys ) ) {
167
+ return get_post_field( 'post_content', $post->ID );
168
+ }
169
+
170
+ $customFieldKeys = explode( ' ', sanitize_text_field( $customFieldKeys ) );
171
+ $customFieldContent = aioseo()->helpers->getCustomFieldsContent( $post->ID, $customFieldKeys );
172
+ $analysisContent = $post->post_content . apply_filters( 'aioseo_analysis_content', $customFieldContent );
173
+
174
+ return sanitize_post_field( 'post_content', $analysisContent, $post->ID, 'display' );
175
+ }
176
+
177
  /**
178
  * Update post settings.
179
  *
204
  $body['twitter_title'] = ! empty( $body['twitter_title'] ) ? sanitize_text_field( $body['twitter_title'] ) : null;
205
  $body['twitter_description'] = ! empty( $body['twitter_description'] ) ? sanitize_text_field( $body['twitter_description'] ) : null;
206
 
207
+ // @TODO: Refactor this as it's not the best way to look for errors.
208
+ $error = Models\Post::savePost( $postId, $body );
209
 
210
+ if ( ! empty( $error ) ) {
211
  return new \WP_REST_Response( [
212
  'success' => false,
213
+ 'message' => 'Failed update query: ' . $error
214
  ], 401 );
215
  }
216
 
241
  ], 400 );
242
  }
243
 
244
+ $thePost = Models\Post::getPost( $postId );
 
 
 
 
245
 
246
  if ( $thePost->exists() ) {
247
  $metaTitle = aioseo()->meta->title->getPostTypeTitle( $post->post_type );
318
  ], 400 );
319
  }
320
 
321
+ $thePost = Models\Post::getPost( $postId );
 
 
 
 
322
 
323
  $thePost->post_id = $postId;
324
  if ( ! empty( $body['keyphrases'] ) ) {
app/Common/Api/Settings.php CHANGED
@@ -116,9 +116,10 @@ class Settings {
116
  * @return \WP_REST_Response The response.
117
  */
118
  public static function saveChanges( $request ) {
119
- $body = $request->get_json_params();
120
- $options = ! empty( $body['options'] ) ? $body['options'] : [];
121
- $network = ! empty( $body['network'] ) ? (bool) $body['network'] : false;
 
122
 
123
  // If this is the network admin, reset the options.
124
  if ( $network ) {
@@ -126,16 +127,14 @@ class Settings {
126
  }
127
 
128
  aioseo()->options->sanitizeAndSave( $options );
 
129
 
130
  // Re-initialize notices.
131
  aioseo()->notices->init();
132
 
133
  return new \WP_REST_Response( [
134
  'success' => true,
135
- 'notifications' => [
136
- 'active' => Models\Notification::getAllActiveNotifications(),
137
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
138
- ],
139
  'redirection' => aioseo()->options->getRedirection()
140
  ], 200 );
141
  }
@@ -152,51 +151,38 @@ class Settings {
152
  $body = $request->get_json_params();
153
  $settings = ! empty( $body['settings'] ) ? $body['settings'] : [];
154
 
 
 
155
  foreach ( $settings as $setting ) {
 
 
 
 
 
 
156
  switch ( $setting ) {
157
- case 'webmaster-tools':
158
- aioseo()->options->webmasterTools->reset();
159
- break;
160
- case 'rss-content':
161
- aioseo()->options->rssContent->reset();
162
- break;
163
- case 'search-appearance':
164
- aioseo()->options->searchAppearance->reset();
165
- break;
166
- case 'access-control':
167
- aioseo()->options->accessControl->reset();
168
- aioseo()->access->addCapabilities();
169
- break;
170
- case 'advanced':
171
- aioseo()->options->advanced->reset();
172
- break;
173
- case 'social-networks':
174
- aioseo()->options->social->reset();
175
- break;
176
- case 'sitemaps':
177
- aioseo()->options->sitemap->reset();
178
- break;
179
- case 'local-business-seo':
180
- aioseo()->options->localBusiness->reset();
181
- break;
182
- case 'robots-txt':
183
  aioseo()->options->tools->robots->reset();
184
  break;
185
- case 'bad-bot-blocker':
186
  aioseo()->options->deprecated->tools->blocker->reset();
187
  break;
188
- case 'image-seo':
189
- aioseo()->options->image->reset();
190
- break;
191
- case 'breadcrumbs':
192
- aioseo()->options->breadcrumbs->reset();
193
- break;
 
 
 
 
 
194
  }
195
  }
196
 
197
  return new \WP_REST_Response( [
198
- 'success' => true,
199
- 'options' => aioseo()->options->all()
200
  ], 200 );
201
  }
202
 
@@ -222,15 +208,51 @@ class Settings {
222
  }
223
 
224
  if ( ! empty( $contents['settings'] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  aioseo()->options->sanitizeAndSave( $contents['settings'] );
226
  }
227
 
228
  if ( ! empty( $contents['postOptions'] ) ) {
 
229
  foreach ( $contents['postOptions'] as $postType => $postData ) {
230
  // Posts.
231
  if ( ! empty( $postData['posts'] ) ) {
232
  foreach ( $postData['posts'] as $post ) {
233
  unset( $post['id'] );
 
 
234
  $thePost = Models\Post::getPost( $post['post_id'] );
235
  $thePost->set( $post );
236
  $thePost->save();
@@ -273,29 +295,56 @@ class Settings {
273
  ];
274
 
275
  if ( ! empty( $settings ) ) {
276
- $options = aioseo()->options->noConflict();
 
 
277
  foreach ( $settings as $setting ) {
278
- if ( $options->has( $setting ) ) {
279
- $allSettings['settings'][ $setting ] = $options->$setting->all();
280
 
281
- // It there is a related deprecated $setting, include it.
282
- if ( $options->deprecated->has( $setting ) ) {
283
- $allSettings['settings']['deprecated'][ $setting ] = $options->deprecated->$setting->all();
284
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  }
286
  }
287
  }
288
 
289
  if ( ! empty( $postOptions ) ) {
 
290
  foreach ( $postOptions as $postType ) {
291
- $allSettings['postOptions'][ $postType ] = [
292
- 'posts' => aioseo()->db->start( 'aioseo_posts as ap' )
293
- ->select( 'ap.*' )
294
- ->join( 'posts as p', 'ap.post_id = p.ID' )
295
- ->where( 'p.post_type', $postType )
296
- ->run()
297
- ->result()
298
- ];
 
 
 
 
 
 
299
  }
300
  }
301
 
116
  * @return \WP_REST_Response The response.
117
  */
118
  public static function saveChanges( $request ) {
119
+ $body = $request->get_json_params();
120
+ $options = ! empty( $body['options'] ) ? $body['options'] : [];
121
+ $dynamicOptions = ! empty( $body['dynamicOptions'] ) ? $body['dynamicOptions'] : [];
122
+ $network = ! empty( $body['network'] ) ? (bool) $body['network'] : false;
123
 
124
  // If this is the network admin, reset the options.
125
  if ( $network ) {
127
  }
128
 
129
  aioseo()->options->sanitizeAndSave( $options );
130
+ aioseo()->dynamicOptions->sanitizeAndSave( $dynamicOptions );
131
 
132
  // Re-initialize notices.
133
  aioseo()->notices->init();
134
 
135
  return new \WP_REST_Response( [
136
  'success' => true,
137
+ 'notifications' => Models\Notification::getNotifications(),
 
 
 
138
  'redirection' => aioseo()->options->getRedirection()
139
  ], 200 );
140
  }
151
  $body = $request->get_json_params();
152
  $settings = ! empty( $body['settings'] ) ? $body['settings'] : [];
153
 
154
+ $notAllowedOptions = aioseo()->access->getNotAllowedOptions();
155
+
156
  foreach ( $settings as $setting ) {
157
+ $optionAccess = in_array( $setting, [ 'robots', 'blocker' ], true ) ? 'tools' : $setting;
158
+
159
+ if ( in_array( $optionAccess, $notAllowedOptions, true ) ) {
160
+ continue;
161
+ }
162
+
163
  switch ( $setting ) {
164
+ case 'robots':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  aioseo()->options->tools->robots->reset();
166
  break;
167
+ case 'blocker':
168
  aioseo()->options->deprecated->tools->blocker->reset();
169
  break;
170
+ default:
171
+ if ( aioseo()->options->has( $setting ) ) {
172
+ aioseo()->options->$setting->reset();
173
+ }
174
+ if ( aioseo()->dynamicOptions->has( $setting ) ) {
175
+ aioseo()->dynamicOptions->$setting->reset();
176
+ }
177
+ }
178
+
179
+ if ( 'access-control' === $setting ) {
180
+ aioseo()->access->addCapabilities();
181
  }
182
  }
183
 
184
  return new \WP_REST_Response( [
185
+ 'success' => true
 
186
  ], 200 );
187
  }
188
 
208
  }
209
 
210
  if ( ! empty( $contents['settings'] ) ) {
211
+ // Clean up the array removing options the user should not manage.
212
+ $notAllowedOptions = aioseo()->access->getNotAllowedOptions();
213
+ $contents['settings'] = array_diff_key( $contents['settings'], $notAllowedOptions );
214
+ if ( ! empty( $contents['settings']['deprecated'] ) ) {
215
+ $contents['settings']['deprecated'] = array_diff_key( $contents['settings']['deprecated'], $notAllowedOptions );
216
+ }
217
+
218
+ // Remove any dynamic options and save them separately since this has been refactored.
219
+ $commonDynamic = [
220
+ 'sitemap',
221
+ 'searchAppearance',
222
+ 'breadcrumbs',
223
+ 'accessControl'
224
+ ];
225
+
226
+ foreach ( $commonDynamic as $cd ) {
227
+ if ( ! empty( $contents['settings'][ $cd ]['dynamic'] ) ) {
228
+ $contents['settings']['dynamic'][ $cd ] = $contents['settings'][ $cd ]['dynamic'];
229
+ unset( $contents['settings'][ $cd ]['dynamic'] );
230
+ }
231
+ }
232
+
233
+ // These options have a very different structure so we'll do them separately.
234
+ if ( ! empty( $contents['settings']['social']['facebook']['general']['dynamic'] ) ) {
235
+ $contents['settings']['dynamic']['social']['facebook']['general'] = $contents['settings']['social']['facebook']['general']['dynamic'];
236
+ unset( $contents['settings']['social']['facebook']['general']['dynamic'] );
237
+ }
238
+
239
+ if ( ! empty( $contents['settings']['dynamic'] ) ) {
240
+ aioseo()->dynamicOptions->sanitizeAndSave( $contents['settings']['dynamic'] );
241
+ unset( $contents['settings']['dynamic'] );
242
+ }
243
+
244
  aioseo()->options->sanitizeAndSave( $contents['settings'] );
245
  }
246
 
247
  if ( ! empty( $contents['postOptions'] ) ) {
248
+ $notAllowedFields = aioseo()->access->getNotAllowedPageFields();
249
  foreach ( $contents['postOptions'] as $postType => $postData ) {
250
  // Posts.
251
  if ( ! empty( $postData['posts'] ) ) {
252
  foreach ( $postData['posts'] as $post ) {
253
  unset( $post['id'] );
254
+ // Clean up the array removing fields the user should not manage.
255
+ $post = array_diff_key( $post, $notAllowedFields );
256
  $thePost = Models\Post::getPost( $post['post_id'] );
257
  $thePost->set( $post );
258
  $thePost->save();
295
  ];
296
 
297
  if ( ! empty( $settings ) ) {
298
+ $options = aioseo()->options->noConflict();
299
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
300
+ $notAllowedOptions = aioseo()->access->getNotAllowedOptions();
301
  foreach ( $settings as $setting ) {
302
+ $optionAccess = in_array( $setting, [ 'robots', 'blocker' ], true ) ? 'tools' : $setting;
 
303
 
304
+ if ( in_array( $optionAccess, $notAllowedOptions, true ) ) {
305
+ continue;
306
+ }
307
+
308
+ switch ( $setting ) {
309
+ case 'robots':
310
+ $allSettings['settings']['tools']['robots'] = $options->tools->robots->all();
311
+ break;
312
+ default:
313
+ if ( $options->has( $setting ) ) {
314
+ $allSettings['settings'][ $setting ] = $options->$setting->all();
315
+ }
316
+
317
+ // If there are related dynamic settings, let's include them.
318
+ if ( $dynamicOptions->has( $setting ) ) {
319
+ $allSettings['settings']['dynamic'][ $setting ] = $dynamicOptions->$setting->all();
320
+ }
321
+
322
+ // It there is a related deprecated $setting, include it.
323
+ if ( $options->deprecated->has( $setting ) ) {
324
+ $allSettings['settings']['deprecated'][ $setting ] = $options->deprecated->$setting->all();
325
+ }
326
+ break;
327
  }
328
  }
329
  }
330
 
331
  if ( ! empty( $postOptions ) ) {
332
+ $notAllowedFields = aioseo()->access->getNotAllowedPageFields();
333
  foreach ( $postOptions as $postType ) {
334
+ $posts = aioseo()->db->start( 'aioseo_posts as ap' )
335
+ ->select( 'ap.*' )
336
+ ->join( 'posts as p', 'ap.post_id = p.ID' )
337
+ ->where( 'p.post_type', $postType )
338
+ ->run()
339
+ ->result();
340
+
341
+ foreach ( $posts as $post ) {
342
+ // Clean up the array removing fields the user should not manage.
343
+ $post = array_diff_key( (array) $post, $notAllowedFields );
344
+ if ( count( $post ) > 2 ) {
345
+ $allSettings['postOptions'][ $postType ]['posts'][] = $post;
346
+ }
347
+ }
348
  }
349
  }
350
 
app/Common/Api/Sitemaps.php CHANGED
@@ -68,10 +68,7 @@ class Sitemaps {
68
 
69
  return new \WP_REST_Response( [
70
  'success' => true,
71
- 'notifications' => [
72
- 'active' => Models\Notification::getAllActiveNotifications(),
73
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
74
- ]
75
  ], 200 );
76
  }
77
 
@@ -109,10 +106,42 @@ class Sitemaps {
109
 
110
  return new \WP_REST_Response( [
111
  'success' => true,
112
- 'notifications' => [
113
- 'active' => Models\Notification::getAllActiveNotifications(),
114
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
115
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  ], 200 );
117
  }
118
  }
68
 
69
  return new \WP_REST_Response( [
70
  'success' => true,
71
+ 'notifications' => Models\Notification::getNotifications()
 
 
 
72
  ], 200 );
73
  }
74
 
106
 
107
  return new \WP_REST_Response( [
108
  'success' => true,
109
+ 'notifications' => Models\Notification::getNotifications()
110
+ ], 200 );
111
+ }
112
+
113
+ /**
114
+ * Check whether the slug for the HTML sitemap is not in use.
115
+ *
116
+ * @since 4.1.3
117
+ *
118
+ * @param \WP_REST_Request $request The REST Request
119
+ * @return \WP_REST_Response The response.
120
+ */
121
+ public static function validateHtmlSitemapSlug( $request ) {
122
+ $body = $request->get_json_params();
123
+
124
+ $pageUrl = ! empty( $body['pageUrl'] ) ? sanitize_text_field( $body['pageUrl'] ) : '';
125
+ if ( empty( $pageUrl ) ) {
126
+ return new \WP_REST_Response( [
127
+ 'success' => false,
128
+ 'message' => 'No path was provided.'
129
+ ], 400 );
130
+ }
131
+
132
+ $pageUrl = wp_parse_url( $pageUrl );
133
+ if ( empty( $pageUrl['path'] ) ) {
134
+ return new \WP_REST_Response( [
135
+ 'success' => false,
136
+ 'message' => 'The given path is invalid.'
137
+ ], 400 );
138
+ }
139
+
140
+ $path = trim( $pageUrl['path'], '/' );
141
+ $exists = aioseo()->helpers->pathExists( $path );
142
+
143
+ return new \WP_REST_Response( [
144
+ 'exists' => $exists
145
  ], 200 );
146
  }
147
  }
app/Common/Api/Tools.php CHANGED
@@ -47,10 +47,7 @@ class Tools {
47
 
48
  return new \WP_REST_Response( [
49
  'success' => true,
50
- 'notifications' => [
51
- 'active' => Models\Notification::getAllActiveNotifications(),
52
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
53
- ]
54
  ], 200 );
55
  }
56
 
@@ -74,10 +71,7 @@ class Tools {
74
 
75
  return new \WP_REST_Response( [
76
  'success' => true,
77
- 'notifications' => [
78
- 'active' => Models\Notification::getAllActiveNotifications(),
79
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
80
- ]
81
  ], 200 );
82
  }
83
 
@@ -216,6 +210,14 @@ class Tools {
216
  $body = $request->get_json_params();
217
  $htaccess = ! empty( $body['htaccess'] ) ? sanitize_textarea_field( $body['htaccess'] ) : '';
218
 
 
 
 
 
 
 
 
 
219
  if ( ! aioseo()->htaccess->saveContents( $htaccess ) ) {
220
  return new \WP_REST_Response( [
221
  'success' => false,
47
 
48
  return new \WP_REST_Response( [
49
  'success' => true,
50
+ 'notifications' => Models\Notification::getNotifications()
 
 
 
51
  ], 200 );
52
  }
53
 
71
 
72
  return new \WP_REST_Response( [
73
  'success' => true,
74
+ 'notifications' => Models\Notification::getNotifications()
 
 
 
75
  ], 200 );
76
  }
77
 
210
  $body = $request->get_json_params();
211
  $htaccess = ! empty( $body['htaccess'] ) ? sanitize_textarea_field( $body['htaccess'] ) : '';
212
 
213
+ if ( empty( $htaccess ) ) {
214
+ return new \WP_REST_Response( [
215
+ 'success' => false,
216
+ 'message' => __( '.htaccess file is empty.', 'all-in-one-seo-pack' )
217
+ ], 400 );
218
+ }
219
+
220
+ $htaccess = aioseo()->helpers->decodeHtmlEntities( $htaccess );
221
  if ( ! aioseo()->htaccess->saveContents( $htaccess ) ) {
222
  return new \WP_REST_Response( [
223
  'success' => false,
app/Common/Api/Wizard.php CHANGED
@@ -23,9 +23,11 @@ class Wizard {
23
  * @return \WP_REST_Response The response.
24
  */
25
  public static function saveWizard( $request ) {
26
- $body = $request->get_json_params();
27
- $section = ! empty( $body['section'] ) ? sanitize_text_field( $body['section'] ) : null;
28
- $wizard = ! empty( $body['wizard'] ) ? $body['wizard'] : null;
 
 
29
 
30
  aioseo()->internalOptions->internal->wizard = wp_json_encode( $wizard );
31
 
@@ -77,21 +79,31 @@ class Wizard {
77
  // If the home page is a static page, let's find and set that,
78
  // otherwise set our home page settings.
79
  $staticHomePage = 'page' === get_option( 'show_on_front' ) ? get_post( get_option( 'page_on_front' ) ) : null;
80
- if ( ! empty( $category['siteTitle'] ) ) {
81
- if ( $staticHomePage ) {
82
- $page = Models\Post::getPost( $staticHomePage->ID );
 
 
83
  $page->title = $category['siteTitle'];
84
- } else {
85
- aioseo()->options->searchAppearance->global->siteTitle = $category['siteTitle'];
86
  }
87
- }
88
 
89
- if ( ! empty( $category['metaDescription'] ) ) {
90
- if ( $staticHomePage ) {
91
- $page = Models\Post::getPost( $staticHomePage->ID );
92
  $page->description = $category['metaDescription'];
93
- } else {
94
- aioseo()->options->searchAppearance->global->metaDescription = $category['metaDescription'];
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
  }
97
  }
@@ -100,44 +112,44 @@ class Wizard {
100
  if ( 'additionalInformation' === $section && ! empty( $wizard['additionalInformation'] ) ) {
101
  $additionalInformation = $wizard['additionalInformation'];
102
  if ( ! empty( $additionalInformation['siteRepresents'] ) ) {
103
- aioseo()->options->searchAppearance->global->schema->siteRepresents = $additionalInformation['siteRepresents'];
104
  }
105
 
106
  if ( ! empty( $additionalInformation['person'] ) ) {
107
- aioseo()->options->searchAppearance->global->schema->person = $additionalInformation['person'];
108
  }
109
 
110
  if ( ! empty( $additionalInformation['organizationName'] ) ) {
111
- aioseo()->options->searchAppearance->global->schema->organizationName = $additionalInformation['organizationName'];
112
  }
113
 
114
  if ( ! empty( $additionalInformation['phone'] ) ) {
115
- aioseo()->options->searchAppearance->global->schema->phone = $additionalInformation['phone'];
116
  }
117
 
118
  if ( ! empty( $additionalInformation['organizationLogo'] ) ) {
119
- aioseo()->options->searchAppearance->global->schema->organizationLogo = $additionalInformation['organizationLogo'];
120
  }
121
 
122
  if ( ! empty( $additionalInformation['personName'] ) ) {
123
- aioseo()->options->searchAppearance->global->schema->personName = $additionalInformation['personName'];
124
  }
125
 
126
  if ( ! empty( $additionalInformation['personLogo'] ) ) {
127
- aioseo()->options->searchAppearance->global->schema->personLogo = $additionalInformation['personLogo'];
128
  }
129
 
130
  if ( ! empty( $additionalInformation['contactType'] ) ) {
131
- aioseo()->options->searchAppearance->global->schema->contactType = $additionalInformation['contactType'];
132
  }
133
 
134
  if ( ! empty( $additionalInformation['contactManual'] ) ) {
135
- aioseo()->options->searchAppearance->global->schema->contactManual = $additionalInformation['contactManual'];
136
  }
137
 
138
  if ( ! empty( $additionalInformation['socialShareImage'] ) ) {
139
- aioseo()->options->social->facebook->general->defaultImagePosts = $additionalInformation['socialShareImage'];
140
- aioseo()->options->social->twitter->general->defaultImagePosts = $additionalInformation['socialShareImage'];
141
  }
142
 
143
  if ( ! empty( $additionalInformation['social'] ) && ! empty( $additionalInformation['social']['profiles'] ) ) {
@@ -145,66 +157,66 @@ class Wizard {
145
  if ( ! empty( $profiles['sameUsername'] ) ) {
146
  $sameUsername = $profiles['sameUsername'];
147
  if ( isset( $sameUsername['enable'] ) ) {
148
- aioseo()->options->social->profiles->sameUsername->enable = $sameUsername['enable'];
149
  }
150
 
151
  if ( ! empty( $sameUsername['username'] ) ) {
152
- aioseo()->options->social->profiles->sameUsername->username = $sameUsername['username'];
153
  }
154
 
155
  if ( ! empty( $sameUsername['included'] ) ) {
156
- aioseo()->options->social->profiles->sameUsername->included = $sameUsername['included'];
157
  }
158
  }
159
 
160
  if ( ! empty( $profiles['urls'] ) ) {
161
  $urls = $profiles['urls'];
162
  if ( ! empty( $urls['facebookPageUrl'] ) ) {
163
- aioseo()->options->social->profiles->urls->facebookPageUrl = $urls['facebookPageUrl'];
164
  }
165
 
166
  if ( ! empty( $urls['twitterUrl'] ) ) {
167
- aioseo()->options->social->profiles->urls->twitterUrl = $urls['twitterUrl'];
168
  }
169
 
170
  if ( ! empty( $urls['instagramUrl'] ) ) {
171
- aioseo()->options->social->profiles->urls->instagramUrl = $urls['instagramUrl'];
172
  }
173
 
174
  if ( ! empty( $urls['pinterestUrl'] ) ) {
175
- aioseo()->options->social->profiles->urls->pinterestUrl = $urls['pinterestUrl'];
176
  }
177
 
178
  if ( ! empty( $urls['youtubeUrl'] ) ) {
179
- aioseo()->options->social->profiles->urls->youtubeUrl = $urls['youtubeUrl'];
180
  }
181
 
182
  if ( ! empty( $urls['linkedinUrl'] ) ) {
183
- aioseo()->options->social->profiles->urls->linkedinUrl = $urls['linkedinUrl'];
184
  }
185
 
186
  if ( ! empty( $urls['tumblrUrl'] ) ) {
187
- aioseo()->options->social->profiles->urls->tumblrUrl = $urls['tumblrUrl'];
188
  }
189
 
190
  if ( ! empty( $urls['yelpPageUrl'] ) ) {
191
- aioseo()->options->social->profiles->urls->yelpPageUrl = $urls['yelpPageUrl'];
192
  }
193
 
194
  if ( ! empty( $urls['soundCloudUrl'] ) ) {
195
- aioseo()->options->social->profiles->urls->soundCloudUrl = $urls['soundCloudUrl'];
196
  }
197
 
198
  if ( ! empty( $urls['wikipediaUrl'] ) ) {
199
- aioseo()->options->social->profiles->urls->wikipediaUrl = $urls['wikipediaUrl'];
200
  }
201
 
202
  if ( ! empty( $urls['myspaceUrl'] ) ) {
203
- aioseo()->options->social->profiles->urls->myspaceUrl = $urls['myspaceUrl'];
204
  }
205
 
206
  if ( ! empty( $urls['googlePlacesUrl'] ) ) {
207
- aioseo()->options->social->profiles->urls->googlePlacesUrl = $urls['googlePlacesUrl'];
208
  }
209
  }
210
  }
@@ -279,55 +291,47 @@ class Wizard {
279
  ) {
280
  // Robots.
281
  if ( ! empty( $searchAppearance['postTypes']['postTypes']['all'] ) ) {
282
- $options = aioseo()->options->noConflict();
283
  foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
284
- if ( $options->searchAppearance->dynamic->postTypes->has( $postType ) ) {
285
- $options->searchAppearance->dynamic->postTypes->$postType->show = true;
286
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default = true;
287
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->noindex = false;
288
  }
289
  }
290
-
291
- aioseo()->options->refresh();
292
  } else {
293
- $options = aioseo()->options->noConflict();
294
  foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
295
- if ( $options->searchAppearance->dynamic->postTypes->has( $postType ) ) {
296
  if ( in_array( $postType, (array) $searchAppearance['postTypes']['postTypes']['included'], true ) ) {
297
- $options->searchAppearance->dynamic->postTypes->$postType->show = true;
298
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default = true;
299
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->noindex = false;
300
  } else {
301
- $options->searchAppearance->dynamic->postTypes->$postType->show = false;
302
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default = false;
303
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->noindex = true;
304
  }
305
  }
306
  }
307
-
308
- aioseo()->options->refresh();
309
  }
310
 
311
  // Sitemaps.
312
  if ( isset( $searchAppearance['postTypes']['postTypes']['all'] ) ) {
313
- aioseo()->options->sitemap->general->postTypes->all = $searchAppearance['postTypes']['postTypes']['all'];
314
  }
315
 
316
  if ( isset( $searchAppearance['postTypes']['postTypes']['included'] ) ) {
317
- aioseo()->options->sitemap->general->postTypes->included = $searchAppearance['postTypes']['postTypes']['included'];
318
  }
319
  }
320
 
321
  if ( isset( $searchAppearance['multipleAuthors'] ) ) {
322
- aioseo()->options->searchAppearance->archives->author->show = $searchAppearance['multipleAuthors'];
323
- aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->default = $searchAppearance['multipleAuthors'];
324
- aioseo()->options->searchAppearance->archives->author->advanced->robotsMeta->noindex = ! $searchAppearance['multipleAuthors'];
325
  }
326
 
327
- $options = aioseo()->options->noConflict();
328
- if ( isset( $searchAppearance['redirectAttachmentPages'] ) && $options->searchAppearance->dynamic->postTypes->has( 'attachment' ) ) {
329
- $options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls = $searchAppearance['redirectAttachmentPages'] ? 'attachment' : 'disabled';
330
- aioseo()->options->refresh();
331
  }
332
  }
333
 
23
  * @return \WP_REST_Response The response.
24
  */
25
  public static function saveWizard( $request ) {
26
+ $body = $request->get_json_params();
27
+ $section = ! empty( $body['section'] ) ? sanitize_text_field( $body['section'] ) : null;
28
+ $wizard = ! empty( $body['wizard'] ) ? $body['wizard'] : null;
29
+ $options = aioseo()->options->noConflict();
30
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
31
 
32
  aioseo()->internalOptions->internal->wizard = wp_json_encode( $wizard );
33
 
79
  // If the home page is a static page, let's find and set that,
80
  // otherwise set our home page settings.
81
  $staticHomePage = 'page' === get_option( 'show_on_front' ) ? get_post( get_option( 'page_on_front' ) ) : null;
82
+ if ( ! empty( $staticHomePage ) ) {
83
+ $update = false;
84
+ $page = Models\Post::getPost( $staticHomePage->ID );
85
+ if ( ! empty( $category['siteTitle'] ) ) {
86
+ $update = true;
87
  $page->title = $category['siteTitle'];
 
 
88
  }
 
89
 
90
+ if ( ! empty( $category['metaDescription'] ) ) {
91
+ $update = true;
 
92
  $page->description = $category['metaDescription'];
93
+ }
94
+
95
+ if ( $update ) {
96
+ $page->save();
97
+ }
98
+ }
99
+
100
+ if ( empty( $staticHomePage ) ) {
101
+ if ( ! empty( $category['siteTitle'] ) ) {
102
+ $options->searchAppearance->global->siteTitle = $category['siteTitle'];
103
+ }
104
+
105
+ if ( ! empty( $category['metaDescription'] ) ) {
106
+ $options->searchAppearance->global->metaDescription = $category['metaDescription'];
107
  }
108
  }
109
  }
112
  if ( 'additionalInformation' === $section && ! empty( $wizard['additionalInformation'] ) ) {
113
  $additionalInformation = $wizard['additionalInformation'];
114
  if ( ! empty( $additionalInformation['siteRepresents'] ) ) {
115
+ $options->searchAppearance->global->schema->siteRepresents = $additionalInformation['siteRepresents'];
116
  }
117
 
118
  if ( ! empty( $additionalInformation['person'] ) ) {
119
+ $options->searchAppearance->global->schema->person = $additionalInformation['person'];
120
  }
121
 
122
  if ( ! empty( $additionalInformation['organizationName'] ) ) {
123
+ $options->searchAppearance->global->schema->organizationName = $additionalInformation['organizationName'];
124
  }
125
 
126
  if ( ! empty( $additionalInformation['phone'] ) ) {
127
+ $options->searchAppearance->global->schema->phone = $additionalInformation['phone'];
128
  }
129
 
130
  if ( ! empty( $additionalInformation['organizationLogo'] ) ) {
131
+ $options->searchAppearance->global->schema->organizationLogo = $additionalInformation['organizationLogo'];
132
  }
133
 
134
  if ( ! empty( $additionalInformation['personName'] ) ) {
135
+ $options->searchAppearance->global->schema->personName = $additionalInformation['personName'];
136
  }
137
 
138
  if ( ! empty( $additionalInformation['personLogo'] ) ) {
139
+ $options->searchAppearance->global->schema->personLogo = $additionalInformation['personLogo'];
140
  }
141
 
142
  if ( ! empty( $additionalInformation['contactType'] ) ) {
143
+ $options->searchAppearance->global->schema->contactType = $additionalInformation['contactType'];
144
  }
145
 
146
  if ( ! empty( $additionalInformation['contactManual'] ) ) {
147
+ $options->searchAppearance->global->schema->contactManual = $additionalInformation['contactManual'];
148
  }
149
 
150
  if ( ! empty( $additionalInformation['socialShareImage'] ) ) {
151
+ $options->social->facebook->general->defaultImagePosts = $additionalInformation['socialShareImage'];
152
+ $options->social->twitter->general->defaultImagePosts = $additionalInformation['socialShareImage'];
153
  }
154
 
155
  if ( ! empty( $additionalInformation['social'] ) && ! empty( $additionalInformation['social']['profiles'] ) ) {
157
  if ( ! empty( $profiles['sameUsername'] ) ) {
158
  $sameUsername = $profiles['sameUsername'];
159
  if ( isset( $sameUsername['enable'] ) ) {
160
+ $options->social->profiles->sameUsername->enable = $sameUsername['enable'];
161
  }
162
 
163
  if ( ! empty( $sameUsername['username'] ) ) {
164
+ $options->social->profiles->sameUsername->username = $sameUsername['username'];
165
  }
166
 
167
  if ( ! empty( $sameUsername['included'] ) ) {
168
+ $options->social->profiles->sameUsername->included = $sameUsername['included'];
169
  }
170
  }
171
 
172
  if ( ! empty( $profiles['urls'] ) ) {
173
  $urls = $profiles['urls'];
174
  if ( ! empty( $urls['facebookPageUrl'] ) ) {
175
+ $options->social->profiles->urls->facebookPageUrl = $urls['facebookPageUrl'];
176
  }
177
 
178
  if ( ! empty( $urls['twitterUrl'] ) ) {
179
+ $options->social->profiles->urls->twitterUrl = $urls['twitterUrl'];
180
  }
181
 
182
  if ( ! empty( $urls['instagramUrl'] ) ) {
183
+ $options->social->profiles->urls->instagramUrl = $urls['instagramUrl'];
184
  }
185
 
186
  if ( ! empty( $urls['pinterestUrl'] ) ) {
187
+ $options->social->profiles->urls->pinterestUrl = $urls['pinterestUrl'];
188
  }
189
 
190
  if ( ! empty( $urls['youtubeUrl'] ) ) {
191
+ $options->social->profiles->urls->youtubeUrl = $urls['youtubeUrl'];
192
  }
193
 
194
  if ( ! empty( $urls['linkedinUrl'] ) ) {
195
+ $options->social->profiles->urls->linkedinUrl = $urls['linkedinUrl'];
196
  }
197
 
198
  if ( ! empty( $urls['tumblrUrl'] ) ) {
199
+ $options->social->profiles->urls->tumblrUrl = $urls['tumblrUrl'];
200
  }
201
 
202
  if ( ! empty( $urls['yelpPageUrl'] ) ) {
203
+ $options->social->profiles->urls->yelpPageUrl = $urls['yelpPageUrl'];
204
  }
205
 
206
  if ( ! empty( $urls['soundCloudUrl'] ) ) {
207
+ $options->social->profiles->urls->soundCloudUrl = $urls['soundCloudUrl'];
208
  }
209
 
210
  if ( ! empty( $urls['wikipediaUrl'] ) ) {
211
+ $options->social->profiles->urls->wikipediaUrl = $urls['wikipediaUrl'];
212
  }
213
 
214
  if ( ! empty( $urls['myspaceUrl'] ) ) {
215
+ $options->social->profiles->urls->myspaceUrl = $urls['myspaceUrl'];
216
  }
217
 
218
  if ( ! empty( $urls['googlePlacesUrl'] ) ) {
219
+ $options->social->profiles->urls->googlePlacesUrl = $urls['googlePlacesUrl'];
220
  }
221
  }
222
  }
291
  ) {
292
  // Robots.
293
  if ( ! empty( $searchAppearance['postTypes']['postTypes']['all'] ) ) {
 
294
  foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
295
+ if ( $dynamicOptions->searchAppearance->postTypes->has( $postType ) ) {
296
+ $dynamicOptions->searchAppearance->postTypes->$postType->show = true;
297
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = true;
298
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = false;
299
  }
300
  }
 
 
301
  } else {
 
302
  foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
303
+ if ( $dynamicOptions->searchAppearance->postTypes->has( $postType ) ) {
304
  if ( in_array( $postType, (array) $searchAppearance['postTypes']['postTypes']['included'], true ) ) {
305
+ $dynamicOptions->searchAppearance->postTypes->$postType->show = true;
306
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = true;
307
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = false;
308
  } else {
309
+ $dynamicOptions->searchAppearance->postTypes->$postType->show = false;
310
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = false;
311
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = true;
312
  }
313
  }
314
  }
 
 
315
  }
316
 
317
  // Sitemaps.
318
  if ( isset( $searchAppearance['postTypes']['postTypes']['all'] ) ) {
319
+ $options->sitemap->general->postTypes->all = $searchAppearance['postTypes']['postTypes']['all'];
320
  }
321
 
322
  if ( isset( $searchAppearance['postTypes']['postTypes']['included'] ) ) {
323
+ $options->sitemap->general->postTypes->included = $searchAppearance['postTypes']['postTypes']['included'];
324
  }
325
  }
326
 
327
  if ( isset( $searchAppearance['multipleAuthors'] ) ) {
328
+ $options->searchAppearance->archives->author->show = $searchAppearance['multipleAuthors'];
329
+ $options->searchAppearance->archives->author->advanced->robotsMeta->default = $searchAppearance['multipleAuthors'];
330
+ $options->searchAppearance->archives->author->advanced->robotsMeta->noindex = ! $searchAppearance['multipleAuthors'];
331
  }
332
 
333
+ if ( isset( $searchAppearance['redirectAttachmentPages'] ) && $dynamicOptions->searchAppearance->postTypes->has( 'attachment' ) ) {
334
+ $dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = $searchAppearance['redirectAttachmentPages'] ? 'attachment' : 'disabled';
 
 
335
  }
336
  }
337
 
app/Common/Breadcrumbs/Breadcrumbs.php CHANGED
@@ -404,7 +404,7 @@ namespace AIOSEO\Plugin\Common\Breadcrumbs {
404
  if ( ! empty( $termHierarchy['terms'] ) ) {
405
  foreach ( $termHierarchy['terms'] as $termId ) {
406
  $term = get_term( $termId, $termHierarchy['taxonomy'] );
407
- $crumbs[] = $this->makeCrumb( $term->name, get_term_link( $term, $termHierarchy['taxonomy'] ), 'taxonomy', $termHierarchy['taxonomy'], 'parent' );
408
  }
409
  }
410
 
@@ -449,8 +449,8 @@ namespace AIOSEO\Plugin\Common\Breadcrumbs {
449
  * @param mixed $reference The breadcrumb reference.
450
  * @return bool Show current item.
451
  */
452
- public function showCurrentItem( $type = null, $reference = null ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
453
- return aioseo()->options->breadcrumbs->showCurrentItem;
454
  }
455
 
456
  /**
@@ -630,10 +630,11 @@ namespace {
630
  *
631
  * @since 4.1.1
632
  *
633
- * @return void
 
634
  */
635
- function aioseo_breadcrumbs() {
636
- aioseo()->breadcrumbs->frontend->display();
637
  }
638
  }
639
  }
404
  if ( ! empty( $termHierarchy['terms'] ) ) {
405
  foreach ( $termHierarchy['terms'] as $termId ) {
406
  $term = get_term( $termId, $termHierarchy['taxonomy'] );
407
+ $crumbs[] = $this->makeCrumb( $term->name, get_term_link( $term, $termHierarchy['taxonomy'] ), 'taxonomy', $term, 'parent' );
408
  }
409
  }
410
 
449
  * @param mixed $reference The breadcrumb reference.
450
  * @return bool Show current item.
451
  */
452
+ public function showCurrentItem( $type = null, $reference = null ) {
453
+ return apply_filters( 'aioseo_breadcrumbs_show_current_item', aioseo()->options->breadcrumbs->showCurrentItem, $type, $reference );
454
  }
455
 
456
  /**
630
  *
631
  * @since 4.1.1
632
  *
633
+ * @param boolean $echo Echo or return the output.
634
+ * @return string|void The output.
635
  */
636
+ function aioseo_breadcrumbs( $echo = true ) {
637
+ return aioseo()->breadcrumbs->frontend->display( $echo );
638
  }
639
  }
640
  }
app/Common/Breadcrumbs/Frontend.php CHANGED
@@ -30,11 +30,16 @@ class Frontend {
30
  */
31
  public function getBreadcrumbs() {
32
  if ( ! empty( $this->breadcrumbs ) ) {
33
- return $this->breadcrumbs;
 
 
 
 
 
34
  }
35
 
36
  $type = '';
37
- $reference = get_queried_object();
38
 
39
  if ( is_single() ) {
40
  $type = 'single';
@@ -95,7 +100,7 @@ class Frontend {
95
  ];
96
  }
97
 
98
- return aioseo()->breadcrumbs->buildBreadcrumbs( $type, $reference, $paged );
99
  }
100
 
101
  /**
@@ -123,7 +128,7 @@ class Frontend {
123
  * @return string|void A html breadcrumb.
124
  */
125
  public function display( $echo = true ) {
126
- if ( ! is_object( get_queried_object() ) || ! aioseo()->options->breadcrumbs->enable ) {
127
  return;
128
  }
129
 
@@ -143,8 +148,8 @@ class Frontend {
143
  // Strip link from Last crumb.
144
  if (
145
  0 === $breadcrumbsCount &&
146
- aioseo()->options->breadcrumbs->showCurrentItem &&
147
- ! aioseo()->options->breadcrumbs->linkCurrentItem &&
148
  'default' === $breadcrumbDisplay['templateType']
149
  ) {
150
  $breadcrumbDisplay['template'] = $this->stripLink( $breadcrumbDisplay['template'] );
@@ -266,6 +271,19 @@ TEMPLATE;
266
  * @return string The separator html.
267
  */
268
  public function getSeparator() {
269
- return apply_filters( 'aioseo_breadcrumbs_separator', '<span class="aioseo-breadcrumb-separator">' . esc_html( aioseo()->options->breadcrumbs->separator ) . '</span>' );
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  }
271
  }
30
  */
31
  public function getBreadcrumbs() {
32
  if ( ! empty( $this->breadcrumbs ) ) {
33
+ return apply_filters( 'aioseo_breadcrumbs_trail', $this->breadcrumbs );
34
+ }
35
+
36
+ $queriedObject = get_queried_object();
37
+ if ( ! is_object( $queriedObject ) ) {
38
+ return;
39
  }
40
 
41
  $type = '';
42
+ $reference = $queriedObject;
43
 
44
  if ( is_single() ) {
45
  $type = 'single';
100
  ];
101
  }
102
 
103
+ return apply_filters( 'aioseo_breadcrumbs_trail', aioseo()->breadcrumbs->buildBreadcrumbs( $type, $reference, $paged ) );
104
  }
105
 
106
  /**
128
  * @return string|void A html breadcrumb.
129
  */
130
  public function display( $echo = true ) {
131
+ if ( ! aioseo()->options->breadcrumbs->enable || ! apply_filters( 'aioseo_breadcrumbs_output', true ) ) {
132
  return;
133
  }
134
 
148
  // Strip link from Last crumb.
149
  if (
150
  0 === $breadcrumbsCount &&
151
+ aioseo()->breadcrumbs->showCurrentItem() &&
152
+ ! $this->linkCurrentItem() &&
153
  'default' === $breadcrumbDisplay['templateType']
154
  ) {
155
  $breadcrumbDisplay['template'] = $this->stripLink( $breadcrumbDisplay['template'] );
271
  * @return string The separator html.
272
  */
273
  public function getSeparator() {
274
+ $separator = apply_filters( 'aioseo_breadcrumbs_separator_symbol', aioseo()->options->breadcrumbs->separator );
275
+
276
+ return apply_filters( 'aioseo_breadcrumbs_separator', '<span class="aioseo-breadcrumb-separator">' . esc_html( $separator ) . '</span>' );
277
+ }
278
+
279
+ /**
280
+ * Function to filter the linkCurrentItem option.
281
+ *
282
+ * @since 4.1.3
283
+ *
284
+ * @return bool Link current item.
285
+ */
286
+ public function linkCurrentItem() {
287
+ return apply_filters( 'aioseo_breadcrumbs_link_current_item', aioseo()->options->breadcrumbs->linkCurrentItem );
288
  }
289
  }
app/Common/Breadcrumbs/Widget.php CHANGED
@@ -58,7 +58,9 @@ class Widget extends \WP_Widget {
58
 
59
  // Title.
60
  if ( ! empty( $instance['title'] ) ) {
61
- echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,Generic.Files.LineLength.MaxExceeded
 
 
62
  }
63
 
64
  // Breadcrumb.
58
 
59
  // Title.
60
  if ( ! empty( $instance['title'] ) ) {
61
+ echo $args['before_title'] . apply_filters( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
62
+ 'widget_title', $instance['title'], $instance, $this->id_base
63
+ ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
64
  }
65
 
66
  // Breadcrumb.
app/Common/HeadlineAnalyzer/HeadlineAnalyzer.php CHANGED
@@ -55,7 +55,8 @@ class HeadlineAnalyzer {
55
 
56
  aioseo()->helpers->enqueueStyle(
57
  'aioseo-headline-analyzer',
58
- 'css/headline-analyzer.css'
 
59
  );
60
  }
61
 
55
 
56
  aioseo()->helpers->enqueueStyle(
57
  'aioseo-headline-analyzer',
58
+ 'css/headline-analyzer.css',
59
+ false
60
  );
61
  }
62
 
app/Common/ImportExport/Helpers.php CHANGED
@@ -12,6 +12,16 @@ if ( ! defined( 'ABSPATH' ) ) {
12
  * @since 4.0.0
13
  */
14
  abstract class Helpers {
 
 
 
 
 
 
 
 
 
 
15
  /**
16
  * Maps a list of old settings from V3 to their counterparts in V4.
17
  *
@@ -32,13 +42,15 @@ abstract class Helpers {
32
  return;
33
  }
34
 
 
 
35
  foreach ( $mappings as $name => $values ) {
36
  if ( ! isset( $group[ $name ] ) ) {
37
  continue;
38
  }
39
 
40
  $error = false;
41
- $options = aioseo()->options->noConflict();
42
  $lastOption = '';
43
  for ( $i = 0; $i < count( $values['newOption'] ); $i++ ) {
44
  $lastOption = $values['newOption'][ $i ];
@@ -79,7 +91,5 @@ abstract class Helpers {
79
  break;
80
  }
81
  }
82
-
83
- aioseo()->options->refresh();
84
  }
85
  }
12
  * @since 4.0.0
13
  */
14
  abstract class Helpers {
15
+ /**
16
+ * Converts macros to smart tags.
17
+ *
18
+ * @since 4.1.3
19
+ *
20
+ * @param string $value The string with macros.
21
+ * @return string The string with macros converted.
22
+ */
23
+ abstract public function macrosToSmartTags( $value );
24
+
25
  /**
26
  * Maps a list of old settings from V3 to their counterparts in V4.
27
  *
42
  return;
43
  }
44
 
45
+ $mainOptions = aioseo()->options->noConflict();
46
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
47
  foreach ( $mappings as $name => $values ) {
48
  if ( ! isset( $group[ $name ] ) ) {
49
  continue;
50
  }
51
 
52
  $error = false;
53
+ $options = ! empty( $values['dynamic'] ) ? $dynamicOptions : $mainOptions;
54
  $lastOption = '';
55
  for ( $i = 0; $i < count( $values['newOption'] ); $i++ ) {
56
  $lastOption = $values['newOption'][ $i ];
91
  break;
92
  }
93
  }
 
 
94
  }
95
  }
app/Common/ImportExport/ImportExport.php CHANGED
@@ -31,6 +31,7 @@ class ImportExport {
31
  public function __construct() {
32
  $this->yoastSeo = new YoastSeo\YoastSeo( $this );
33
  $this->rankMath = new RankMath\RankMath( $this );
 
34
  }
35
 
36
  /**
@@ -297,6 +298,9 @@ class ImportExport {
297
  * @return void
298
  */
299
  public function startImport( $plugin, $settings ) {
 
 
 
300
  foreach ( $this->plugins as $pluginData ) {
301
  if ( $pluginData['slug'] === $plugin ) {
302
  $pluginData['class']->doImport( $settings );
@@ -305,6 +309,45 @@ class ImportExport {
305
  }
306
  }
307
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  /**
309
  * Adds plugins to the import/export.
310
  *
31
  public function __construct() {
32
  $this->yoastSeo = new YoastSeo\YoastSeo( $this );
33
  $this->rankMath = new RankMath\RankMath( $this );
34
+ $this->seoPress = new SeoPress\SeoPress( $this );
35
  }
36
 
37
  /**
298
  * @return void
299
  */
300
  public function startImport( $plugin, $settings ) {
301
+ // First cancel any scans running that might interfere with our import.
302
+ $this->cancelScans();
303
+
304
  foreach ( $this->plugins as $pluginData ) {
305
  if ( $pluginData['slug'] === $plugin ) {
306
  $pluginData['class']->doImport( $settings );
309
  }
310
  }
311
 
312
+ /**
313
+ * Cancel scans that are currently running and could conflict with our migration.
314
+ *
315
+ * @since 4.1.4
316
+ *
317
+ * @return void
318
+ */
319
+ private function cancelScans() {
320
+ // Figure out how to check if these addons are enabled and then get the action names that way.
321
+ aioseo()->helpers->unscheduleAction( 'aioseo_video_sitemap_scan' );
322
+ aioseo()->helpers->unscheduleAction( 'aioseo_image_sitemap_scan' );
323
+ }
324
+
325
+ /**
326
+ * Checks if an import is currently running.
327
+ *
328
+ * @since 4.1.4
329
+ *
330
+ * @return boolean True if an import is currently running.
331
+ */
332
+ public function isImportRunning() {
333
+ $transients = aioseo()->db
334
+ ->start( 'options' )
335
+ ->select( 'option_name as name' )
336
+ ->whereRaw( "`option_name` LIKE '_aioseo_cache_%'" )
337
+ ->run()
338
+ ->result();
339
+
340
+ $foundImportTransient = false;
341
+ foreach ( $transients as $transient ) {
342
+ if ( preg_match( '#import_.*_meta_.*#', $transient->name ) ) {
343
+ $foundImportTransient = true;
344
+ break;
345
+ }
346
+ }
347
+
348
+ return $foundImportTransient;
349
+ }
350
+
351
  /**
352
  * Adds plugins to the import/export.
353
  *
app/Common/ImportExport/RankMath/GeneralSettings.php CHANGED
@@ -63,9 +63,9 @@ class GeneralSettings {
63
  private function migrateRedirectAttachments() {
64
  if ( isset( $this->options['attachment_redirect_urls'] ) ) {
65
  if ( 'on' === $this->options['attachment_redirect_urls'] ) {
66
- aioseo()->options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls = 'attachment_parent';
67
  } else {
68
- aioseo()->options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls = 'disabled';
69
  }
70
  }
71
  }
63
  private function migrateRedirectAttachments() {
64
  if ( isset( $this->options['attachment_redirect_urls'] ) ) {
65
  if ( 'on' === $this->options['attachment_redirect_urls'] ) {
66
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'attachment_parent';
67
  } else {
68
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'disabled';
69
  }
70
  }
71
  }
app/Common/ImportExport/RankMath/TitleMeta.php CHANGED
@@ -188,7 +188,7 @@ class TitleMeta extends ImportExport\SearchAppearance {
188
  foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
189
  // Reset existing values first.
190
  foreach ( $this->robotMetaSettings as $robotsMetaName ) {
191
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->$robotsMetaName = false;
192
  }
193
 
194
  foreach ( $this->options as $name => $value ) {
@@ -202,7 +202,7 @@ class TitleMeta extends ImportExport\SearchAppearance {
202
  $value = aioseo()->helpers->pregReplace( '#%category%#', '', $value );
203
  $value = aioseo()->helpers->pregReplace( '#%excerpt%#', '', $value );
204
  }
205
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->title =
206
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value ) );
207
  break;
208
  case 'description':
@@ -210,11 +210,11 @@ class TitleMeta extends ImportExport\SearchAppearance {
210
  $value = aioseo()->helpers->pregReplace( '#%category%#', '', $value );
211
  $value = aioseo()->helpers->pregReplace( '#%excerpt%#', '', $value );
212
  }
213
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->metaDescription =
214
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value ) );
215
  break;
216
  case 'custom_robots':
217
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default = 'off' === $value;
218
  break;
219
  case 'robots':
220
  if ( ! empty( $value ) ) {
@@ -222,33 +222,33 @@ class TitleMeta extends ImportExport\SearchAppearance {
222
  if ( 'index' === $robotsName ) {
223
  continue;
224
  }
225
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->$robotsName = true;
226
  }
227
  }
228
  break;
229
  case 'advanced_robots':
230
  if ( ! empty( $value['max-snippet'] ) ) {
231
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->maxSnippet = intval( $value['max-snippet'] );
232
  }
233
  if ( ! empty( $value['max-video-preview'] ) ) {
234
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->maxVideoPreview = intval( $value['max-video-preview'] );
235
  }
236
  if ( ! empty( $value['max-image-preview'] ) ) {
237
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->maxImagePreview =
238
  aioseo()->helpers->sanitizeOption( $value['max-image-preview'] );
239
  }
240
  break;
241
  case 'add_meta_box':
242
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->showMetaBox = 'on' === $value;
243
  break;
244
  case 'default_rich_snippet':
245
  $value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
246
  if ( 'off' === lcfirst( $value ) || in_array( $postType, [ 'page', 'attachment' ], true ) ) {
247
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->schemaType = 'none';
248
  break;
249
  }
250
  if ( in_array( ucfirst( $value ), ImportExport\SearchAppearance::$supportedSchemaGraphs, true ) ) {
251
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->schemaType = ucfirst( $value );
252
  }
253
  break;
254
  case 'default_article_type':
@@ -257,9 +257,9 @@ class TitleMeta extends ImportExport\SearchAppearance {
257
  }
258
  $value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
259
  if ( in_array( ucfirst( $value ), ImportExport\SearchAppearance::$supportedArticleGraphs, true ) ) {
260
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->articleType = ucfirst( $value );
261
  } else {
262
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->articleType = 'BlogPosting';
263
  }
264
  break;
265
  default:
@@ -290,11 +290,11 @@ class TitleMeta extends ImportExport\SearchAppearance {
290
 
291
  switch ( $match[1] ) {
292
  case 'title':
293
- aioseo()->options->searchAppearance->dynamic->archives->$postType->title =
294
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value, 'archive' ) );
295
  break;
296
  case 'description':
297
- aioseo()->options->searchAppearance->dynamic->archives->$postType->metaDescription =
298
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value, 'archive' ) );
299
  break;
300
  default:
@@ -413,7 +413,7 @@ class TitleMeta extends ImportExport\SearchAppearance {
413
  'type' => 'warning',
414
  'level' => [ 'all' ],
415
  'button1_label' => __( 'Fix Now', 'all-in-one-seo-pack' ),
416
- 'button1_action' => 'http://route#aioseo-search-appearance:schema-markup',
417
  'button2_label' => __( 'Remind Me Later', 'all-in-one-seo-pack' ),
418
  'button2_action' => 'http://action#notification/v3-migration-schema-number-reminder',
419
  'start' => gmdate( 'Y-m-d H:i:s' )
188
  foreach ( aioseo()->helpers->getPublicPostTypes( true ) as $postType ) {
189
  // Reset existing values first.
190
  foreach ( $this->robotMetaSettings as $robotsMetaName ) {
191
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->$robotsMetaName = false;
192
  }
193
 
194
  foreach ( $this->options as $name => $value ) {
202
  $value = aioseo()->helpers->pregReplace( '#%category%#', '', $value );
203
  $value = aioseo()->helpers->pregReplace( '#%excerpt%#', '', $value );
204
  }
205
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->title =
206
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value ) );
207
  break;
208
  case 'description':
210
  $value = aioseo()->helpers->pregReplace( '#%category%#', '', $value );
211
  $value = aioseo()->helpers->pregReplace( '#%excerpt%#', '', $value );
212
  }
213
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->metaDescription =
214
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value ) );
215
  break;
216
  case 'custom_robots':
217
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = 'off' === $value;
218
  break;
219
  case 'robots':
220
  if ( ! empty( $value ) ) {
222
  if ( 'index' === $robotsName ) {
223
  continue;
224
  }
225
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->$robotsName = true;
226
  }
227
  }
228
  break;
229
  case 'advanced_robots':
230
  if ( ! empty( $value['max-snippet'] ) ) {
231
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->maxSnippet = intval( $value['max-snippet'] );
232
  }
233
  if ( ! empty( $value['max-video-preview'] ) ) {
234
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->maxVideoPreview = intval( $value['max-video-preview'] );
235
  }
236
  if ( ! empty( $value['max-image-preview'] ) ) {
237
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->maxImagePreview =
238
  aioseo()->helpers->sanitizeOption( $value['max-image-preview'] );
239
  }
240
  break;
241
  case 'add_meta_box':
242
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showMetaBox = 'on' === $value;
243
  break;
244
  case 'default_rich_snippet':
245
  $value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
246
  if ( 'off' === lcfirst( $value ) || in_array( $postType, [ 'page', 'attachment' ], true ) ) {
247
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->schemaType = 'none';
248
  break;
249
  }
250
  if ( in_array( ucfirst( $value ), ImportExport\SearchAppearance::$supportedSchemaGraphs, true ) ) {
251
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->schemaType = ucfirst( $value );
252
  }
253
  break;
254
  case 'default_article_type':
257
  }
258
  $value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
259
  if ( in_array( ucfirst( $value ), ImportExport\SearchAppearance::$supportedArticleGraphs, true ) ) {
260
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = ucfirst( $value );
261
  } else {
262
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'BlogPosting';
263
  }
264
  break;
265
  default:
290
 
291
  switch ( $match[1] ) {
292
  case 'title':
293
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->title =
294
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value, 'archive' ) );
295
  break;
296
  case 'description':
297
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->metaDescription =
298
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->rankMath->helpers->macrosToSmartTags( $value, 'archive' ) );
299
  break;
300
  default:
413
  'type' => 'warning',
414
  'level' => [ 'all' ],
415
  'button1_label' => __( 'Fix Now', 'all-in-one-seo-pack' ),
416
+ 'button1_action' => 'http://route#aioseo-search-appearance&aioseo-scroll=schema-graph-phone&aioseo-highlight=schema-graph-phone:schema-markup',
417
  'button2_label' => __( 'Remind Me Later', 'all-in-one-seo-pack' ),
418
  'button2_action' => 'http://action#notification/v3-migration-schema-number-reminder',
419
  'start' => gmdate( 'Y-m-d H:i:s' )
app/Common/ImportExport/SeoPress/Analytics.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the Analytics Settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class Analytics {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_google_analytics_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ $settings = [
29
+ 'seopress_google_analytics_other_tracking' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'miscellaneousVerification' ] ],
30
+ ];
31
+
32
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
33
+ }
34
+ }
app/Common/ImportExport/SeoPress/Breadcrumbs.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the Breadcrumb settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class Breadcrumbs {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_pro_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ $this->migrate();
29
+ }
30
+
31
+ /**
32
+ * Migrates the Breadcrumbs settings.
33
+ *
34
+ * @since 4.1.4
35
+ *
36
+ * @return void
37
+ */
38
+ private function migrate() {
39
+ if ( ! empty( $this->options['seopress_breadcrumbs_i18n_search'] ) ) {
40
+ aioseo()->options->breadcrumbs->searchResultFormat = sprintf( '%1$s #breadcrumb_archive_post_type_name', $this->options['seopress_breadcrumbs_i18n_search'] );
41
+ }
42
+
43
+ if ( ! empty( $this->options['seopress_breadcrumbs_remove_blog_page'] ) ) {
44
+ aioseo()->options->breadcrumbs->showBlogHome = false;
45
+ }
46
+
47
+ $settings = [
48
+ 'seopress_breadcrumbs_enable' => [ 'type' => 'boolean', 'newOption' => [ 'breadcrumbs', 'enable' ] ],
49
+ 'seopress_breadcrumbs_separator' => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'separator' ] ],
50
+ 'seopress_breadcrumbs_i18n_home' => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'homepageLabel' ] ],
51
+ 'seopress_breadcrumbs_i18n_here' => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'breadcrumbPrefix' ] ],
52
+ 'seopress_breadcrumbs_i18n_404' => [ 'type' => 'string', 'newOption' => [ 'breadcrumbs', 'errorFormat404' ] ],
53
+ ];
54
+
55
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
56
+ }
57
+ }
app/Common/ImportExport/SeoPress/GeneralSettings.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the General Settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class GeneralSettings {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_advanced_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ $this->roles = aioseo()->access->getRoles();
29
+
30
+ $this->migrateBlockMetaboxRoles();
31
+ $this->migrateBlockContentAnalysisRoles();
32
+ $this->migrateAttachmentRedirects();
33
+
34
+ $settings = [
35
+ 'seopress_advanced_advanced_google' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'google' ] ],
36
+ 'seopress_advanced_advanced_bing' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'bing' ] ],
37
+ 'seopress_advanced_advanced_pinterest' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'pinterest' ] ],
38
+ 'seopress_advanced_advanced_yandex' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'yandex' ] ],
39
+ ];
40
+
41
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
42
+ }
43
+
44
+ /**
45
+ * Migrates Block AIOSEO metabox setting.
46
+ *
47
+ * @since 4.1.4
48
+ *
49
+ * @return void
50
+ */
51
+ private function migrateBlockMetaboxRoles() {
52
+ $seoPressRoles = $this->options['seopress_advanced_security_metaboxe_role'];
53
+ if ( empty( $seoPressRoles ) ) {
54
+ return;
55
+ }
56
+
57
+ $roleSettings = [ 'useDefault', 'pageAnalysis', 'pageGeneralSettings', 'pageSocialSettings', 'pageSchemaSettings', 'pageAdvancedSettings' ];
58
+
59
+ foreach ( $seoPressRoles as $wpRole => $value ) {
60
+ $role = $this->roles[ $wpRole ];
61
+ if ( empty( $role ) || aioseo()->access->isAdmin( $role ) ) {
62
+ continue;
63
+ }
64
+
65
+ if ( aioseo()->options->accessControl->has( $role ) ) {
66
+ foreach ( $roleSettings as $setting ) {
67
+ aioseo()->options->accessControl->$role->$setting = false;
68
+ }
69
+ } elseif ( aioseo()->dynamicOptions->accessControl->has( $role ) ) {
70
+ foreach ( $roleSettings as $setting ) {
71
+ aioseo()->dynamicOptions->accessControl->$role->$setting = false;
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Migrates Block Content analysis metabox setting.
79
+ *
80
+ * @since 4.1.4
81
+ *
82
+ * @return void
83
+ */
84
+ private function migrateBlockContentAnalysisRoles() {
85
+ $seoPressRoles = $this->options['seopress_advanced_security_metaboxe_ca_role'];
86
+ if ( empty( $seoPressRoles ) ) {
87
+ return;
88
+ }
89
+
90
+ $roleSettings = [ 'useDefault', 'pageAnalysis' ];
91
+
92
+ foreach ( $seoPressRoles as $wpRole => $value ) {
93
+ $role = $this->roles[ $wpRole ];
94
+ if ( empty( $role ) || aioseo()->access->isAdmin( $role ) ) {
95
+ continue;
96
+ }
97
+
98
+ if ( aioseo()->options->accessControl->has( $role ) ) {
99
+ foreach ( $roleSettings as $setting ) {
100
+ aioseo()->options->accessControl->$role->$setting = false;
101
+ }
102
+ } elseif ( aioseo()->dynamicOptions->accessControl->has( $role ) ) {
103
+ foreach ( $roleSettings as $setting ) {
104
+ aioseo()->dynamicOptions->accessControl->$role->$setting = false;
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Migrates redirect attachment pages settings.
112
+ *
113
+ * @since 4.1.4
114
+ *
115
+ * @return void
116
+ */
117
+ private function migrateAttachmentRedirects() {
118
+ if ( ! empty( $this->options['seopress_advanced_advanced_attachments'] ) ) {
119
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'attachment_parent';
120
+ }
121
+
122
+ if ( ! empty( $this->options['seopress_advanced_advanced_attachments_file'] ) ) {
123
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'attachment';
124
+ }
125
+
126
+ if ( empty( $this->options['seopress_advanced_advanced_attachments'] ) && empty( $this->options['seopress_advanced_advanced_attachments_file'] ) ) {
127
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'disabled';
128
+ }
129
+ }
130
+ }
app/Common/ImportExport/SeoPress/Helpers.php CHANGED
@@ -13,25 +13,104 @@ use AIOSEO\Plugin\Common\ImportExport;
13
  /**
14
  * Contains helper methods for the import from SEOPress.
15
  *
16
- * @since 4.0.0
17
  */
18
  class Helpers extends ImportExport\Helpers {
19
  /**
20
  * Converts the macros from SEOPress to our own smart tags.
21
  *
22
- * @since 4.0.0
23
  *
24
- * @param string $string The string with macros.
25
- * @return string $string The string with smart tags.
 
26
  */
27
- public function macrosToSmartTags( $string ) {
28
- $macros = [
29
- '%%tagline%%' => '#tagline',
30
- ];
31
 
32
  foreach ( $macros as $macro => $tag ) {
33
  $string = aioseo()->helpers->pregReplace( "#$macro(?![a-zA-Z0-9_])#im", $tag, $string );
34
  }
35
- return $string;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
  }
13
  /**
14
  * Contains helper methods for the import from SEOPress.
15
  *
16
+ * @since 4.1.4
17
  */
18
  class Helpers extends ImportExport\Helpers {
19
  /**
20
  * Converts the macros from SEOPress to our own smart tags.
21
  *
22
+ * @since 4.1.4
23
  *
24
+ * @param string $string The string with macros.
25
+ * @param string $pageType The page type.
26
+ * @return string $string The string with smart tags.
27
  */
28
+ public function macrosToSmartTags( $string, $postType = null ) {
29
+ $macros = $this->getMacros( $postType );
 
 
30
 
31
  foreach ( $macros as $macro => $tag ) {
32
  $string = aioseo()->helpers->pregReplace( "#$macro(?![a-zA-Z0-9_])#im", $tag, $string );
33
  }
34
+
35
+ return trim( $string );
36
+ }
37
+
38
+ /**
39
+ * Returns the macro mappings.
40
+ *
41
+ * @since 4.1.4
42
+ *
43
+ * @param string $postType The post type.
44
+ * @param string $pageType The page type.
45
+ * @return array $macros The macros.
46
+ */
47
+ protected function getMacros( $postType = null, $pageType = null ) {
48
+ $macros = [
49
+ '%%sep%%' => '#separator_sa',
50
+ '%%sitetitle%%' => '#site_title',
51
+ '%%sitename%%' => '#site_title',
52
+ '%%tagline%%' => '#tagline',
53
+ '%%sitedesc%%' => '#tagline',
54
+ '%%title%%' => '#site_title',
55
+ '%%post_title%%' => '#post_title',
56
+ '%%post_excerpt%%' => '#post_excerpt',
57
+ '%%excerpt%%' => '#post_excerpt',
58
+ '%%post_content%%' => '#post_content',
59
+ '%%post_url%%' => '#permalink',
60
+ '%%post_date%%' => '#post_date',
61
+ '%%post_permalink%%' => '#permalink',
62
+ '%%date%%' => '#post_date',
63
+ '%%post_author%%' => '#author_name',
64
+ '%%post_category%%' => '#categories',
65
+ '%%_category_title%%' => '#taxonomy_title',
66
+ '%%_category_description%%' => '#taxonomy_description',
67
+ '%%tag_title%%' => '#taxonomy_title',
68
+ '%%tag_description%%' => '#taxonomy_description',
69
+ '%%term_title%%' => '#taxonomy_title',
70
+ '%%term_description%%' => '#taxonomy_description',
71
+ '%%search_keywords%%' => '#search_term',
72
+ '%%current_pagination%%' => '#page_number',
73
+ '%%page%%' => '#page_number',
74
+ '%%archive_title%%' => '#archive_title',
75
+ '%%archive_date%%' => '#archive_date',
76
+ '%%wc_single_price%%' => '#woocommerce_price',
77
+ '%%wc_sku%%' => '#woocommerce_sku',
78
+ '%%currentday%%' => '#current_day',
79
+ '%%currentmonth%%' => '#current_month',
80
+ '%%currentmonth_short%%' => '#current_month',
81
+ '%%currentyear%%' => '#current_year',
82
+ '%%currentdate%%' => '#current_date',
83
+ '%%author_first_name%%' => '#author_first_name',
84
+ '%%author_last_name%%' => '#author_last_name',
85
+ '%%author_website%%' => '#author_link',
86
+ '%%author_nickname%%' => '#author_first_name',
87
+ '%%author_bio%%' => '#author_bio',
88
+ '%%currentmonth_num%%' => '#current_month',
89
+ ];
90
+
91
+ if ( $postType ) {
92
+ $postType = get_post_type_object( $postType );
93
+ if ( ! empty( $postType ) ) {
94
+ $macros += [
95
+ '%%cpt_plural%%' => $postType->labels->name,
96
+ ];
97
+ }
98
+ }
99
+
100
+ switch ( $pageType ) {
101
+ case 'archive':
102
+ $macros['%%title%%'] = '#archive_title';
103
+ break;
104
+ case 'term':
105
+ $macros['%%title%%'] = '#taxonomy_title';
106
+ break;
107
+ default:
108
+ $macros['%%title%%'] = '#post_title';
109
+ break;
110
+ }
111
+
112
+ // Strip all other tags.
113
+ $macros['%%[^%]*%%'] = '';
114
+ return $macros;
115
  }
116
  }
app/Common/ImportExport/SeoPress/PostMeta.php ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ use AIOSEO\Plugin\Common\Models;
10
+
11
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
12
+
13
+ /**
14
+ * Imports the post meta from SEOPress.
15
+ *
16
+ * @since 4.1.4
17
+ */
18
+ class PostMeta {
19
+ /**
20
+ * The mapped meta
21
+ *
22
+ * @since 4.1.4
23
+ *
24
+ * @var array
25
+ */
26
+ private $mappedMeta = [
27
+ '_seopress_analysis_target_kw' => '',
28
+ '_seopress_robots_archive' => 'robots_noarchive',
29
+ '_seopress_robots_canonical' => 'canonical_url',
30
+ '_seopress_robots_follow' => 'robots_nofollow',
31
+ '_seopress_robots_imageindex' => 'robots_noimageindex',
32
+ '_seopress_robots_index' => 'robots_noindex',
33
+ '_seopress_robots_odp' => 'robots_noodp',
34
+ '_seopress_robots_snippet' => 'robots_nosnippet',
35
+ '_seopress_social_twitter_desc' => 'twitter_description',
36
+ '_seopress_social_twitter_img' => 'twitter_image_custom_url',
37
+ '_seopress_social_twitter_title' => 'twitter_title',
38
+ '_seopress_social_fb_desc' => 'og_description',
39
+ '_seopress_social_fb_img' => 'og_image_custom_url',
40
+ '_seopress_social_fb_title' => 'og_title',
41
+ '_seopress_titles_desc' => 'description',
42
+ '_seopress_titles_title' => 'title',
43
+ ];
44
+
45
+ /**
46
+ * Class constructor.
47
+ *
48
+ * @since 4.1.4
49
+ */
50
+ public function scheduleImport() {
51
+ if ( aioseo()->helpers->scheduleSingleAction( aioseo()->importExport->seoPress->postActionName, 0 ) ) {
52
+ if ( ! aioseo()->transients->get( 'import_post_meta_seopress' ) ) {
53
+ aioseo()->transients->update( 'import_post_meta_seopress', time(), WEEK_IN_SECONDS );
54
+ }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Imports the post meta.
60
+ *
61
+ * @since 4.1.4
62
+ *
63
+ * @return void
64
+ */
65
+ public function importPostMeta() {
66
+ $postsPerAction = 100;
67
+ $publicPostTypes = implode( "', '", aioseo()->helpers->getPublicPostTypes( true ) );
68
+ $timeStarted = gmdate( 'Y-m-d H:i:s', aioseo()->transients->get( 'import_post_meta_seopress' ) );
69
+
70
+ $posts = aioseo()->db
71
+ ->start( 'posts as p' )
72
+ ->select( 'p.ID, p.post_type' )
73
+ ->join( 'postmeta as pm', '`p`.`ID` = `pm`.`post_id`' )
74
+ ->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
75
+ ->whereRaw( "pm.meta_key LIKE '_seopress_%'" )
76
+ ->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
77
+ ->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
78
+ ->orderBy( 'p.ID DESC' )
79
+ ->limit( $postsPerAction )
80
+ ->run()
81
+ ->result();
82
+
83
+ if ( ! $posts || ! count( $posts ) ) {
84
+ aioseo()->transients->delete( 'import_post_meta_seopress' );
85
+ return;
86
+ }
87
+
88
+ foreach ( $posts as $post ) {
89
+ $postMeta = aioseo()->db
90
+ ->start( 'postmeta' . ' as pm' )
91
+ ->select( 'pm.meta_key, pm.meta_value' )
92
+ ->where( 'pm.post_id', $post->ID )
93
+ ->whereRaw( "`pm`.`meta_key` LIKE '_seopress_%'" )
94
+ ->run()
95
+ ->result();
96
+
97
+ if ( ! $postMeta || ! count( $postMeta ) ) {
98
+ continue;
99
+ }
100
+
101
+ $meta = array_merge( [
102
+ 'post_id' => (int) $post->ID,
103
+ ], $this->getMetaData( $postMeta, $post->ID ) );
104
+
105
+ $aioseoPost = Models\Post::getPost( (int) $post->ID );
106
+ $aioseoPost->set( $meta );
107
+ $aioseoPost->save();
108
+ }
109
+
110
+ if ( count( $posts ) === $postsPerAction ) {
111
+ aioseo()->helpers->scheduleSingleAction( aioseo()->importExport->seoPress->postActionName, 5 );
112
+ } else {
113
+ aioseo()->transients->delete( 'import_post_meta_seopress' );
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Get the meta data by post meta.
119
+ *
120
+ * @since 4.1.4
121
+ *
122
+ * @param object $postMeta The post meta from database.
123
+ * @return array The meta data.
124
+ */
125
+ public function getMetaData( $postMeta, $post_id ) {
126
+ $meta = [];
127
+ foreach ( $postMeta as $record ) {
128
+ $name = $record->meta_key;
129
+ $value = $record->meta_value;
130
+
131
+ if ( ! in_array( $name, array_keys( $this->mappedMeta ), true ) ) {
132
+ continue;
133
+ }
134
+
135
+ switch ( $name ) {
136
+ case '_seopress_analysis_target_kw':
137
+ $keyphrase = [
138
+ 'focus' => [ 'keyphrase' => aioseo()->helpers->sanitizeOption( $value ) ],
139
+ 'additional' => []
140
+ ];
141
+ $meta['keyphrases'] = wp_json_encode( $keyphrase );
142
+ break;
143
+ case '_seopress_robots_snippet':
144
+ case '_seopress_robots_archive':
145
+ case '_seopress_robots_imageindex':
146
+ case '_seopress_robots_odp':
147
+ case '_seopress_robots_follow':
148
+ case '_seopress_robots_index':
149
+ if ( 'yes' === $value ) {
150
+ $meta['robots_default'] = false;
151
+ $meta[ $this->mappedMeta[ $name ] ] = true;
152
+ }
153
+ break;
154
+ case '_seopress_social_twitter_img':
155
+ $meta['twitter_use_og'] = false;
156
+ $meta['twitter_image_type'] = 'custom_image';
157
+ $meta[ $this->mappedMeta[ $name ] ] = esc_url( $value );
158
+ break;
159
+ case '_seopress_social_fb_img':
160
+ $meta['og_image_type'] = 'custom_image';
161
+ $meta[ $this->mappedMeta[ $name ] ] = esc_url( $value );
162
+ break;
163
+ case '_seopress_titles_title':
164
+ case '_seopress_titles_desc':
165
+ $value = aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $value );
166
+ default:
167
+ $meta[ $this->mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
168
+ break;
169
+ }
170
+ }
171
+
172
+ return $meta;
173
+ }
174
+ }
app/Common/ImportExport/SeoPress/RobotsTxt.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the robots.txt settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class RobotsTxt {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_pro_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ $this->migrateRobotsTxt();
29
+
30
+ $settings = [
31
+ 'seopress_robots_enable' => [ 'type' => 'boolean', 'newOption' => [ 'tools', 'robots', 'enable' ] ],
32
+ ];
33
+
34
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
35
+ }
36
+
37
+ /**
38
+ * Migrates the robots.txt.
39
+ *
40
+ * @since 4.1.4
41
+ *
42
+ * @return void
43
+ */
44
+ public function migrateRobotsTxt() {
45
+ $lines = explode( "\n", $this->options['seopress_robots_file'] );
46
+ $allRules = aioseo()->robotsTxt->extractRules( $lines );
47
+
48
+ aioseo()->options->tools->robots->rules = aioseo()->robotsTxt->prepareRobotsTxt( $allRules );
49
+ }
50
+ }
app/Common/ImportExport/SeoPress/Rss.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the RSS settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class Rss {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_pro_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ $this->migrateRss();
29
+ }
30
+
31
+ /**
32
+ * Migrates the RSS settings.
33
+ *
34
+ * @since 4.1.4
35
+ *
36
+ * @return void
37
+ */
38
+ public function migrateRss() {
39
+ if ( ! empty( $this->options['seopress_rss_before_html'] ) ) {
40
+ aioseo()->options->rssContent->before = esc_html( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $this->options['seopress_rss_before_html'] ) );
41
+ }
42
+
43
+ if ( ! empty( $this->options['seopress_rss_after_html'] ) ) {
44
+ aioseo()->options->rssContent->after = esc_html( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $this->options['seopress_rss_after_html'] ) );
45
+ }
46
+ }
47
+ }
app/Common/ImportExport/SeoPress/SearchAppearance.php DELETED
@@ -1,46 +0,0 @@
1
- <?php
2
- namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
-
4
- // Exit if accessed directly.
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- }
8
-
9
- // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
-
11
- /**
12
- * Migrates the Search Appearance settings.
13
- *
14
- * @since 4.0.0
15
- */
16
- class SearchAppearance {
17
- /**
18
- * Class constructor.
19
- *
20
- * @since 4.0.0
21
- */
22
- public function __construct() {
23
- $this->options = get_option( 'seopress_titles_option_name' );
24
- if ( empty( $this->options ) ) {
25
- return;
26
- }
27
-
28
- $this->migrateTitleFormats();
29
-
30
- }
31
-
32
- /**
33
- * Migrates the title format settings.
34
- *
35
- * @since 4.0.0
36
- *
37
- * @return void
38
- */
39
- private function migrateTitleFormats() {
40
- if ( isset( $this->options['seopress_titles_home_site_title'] ) ) {
41
- aioseo()->options->searchAppearance->global->siteTitle =
42
- aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $this->options['seopress_titles_home_site_title'] );
43
- }
44
- }
45
-
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Common/ImportExport/SeoPress/SeoPress.php CHANGED
@@ -6,28 +6,74 @@ if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
9
- class SeoPress {
 
 
10
  /**
11
- * Starts the import.
12
  *
13
- * @since 4.0.0
14
  *
15
- * @return void
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  */
17
- public function doImport() {
18
- // @TODO: [V4+] Write this once SEOPress is going in.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
  /**
22
  * Imports the settings.
23
  *
24
- * @since 4.0.0
25
  *
26
  * @return void
27
  */
28
- public function migrateSettings() {
29
- $this->helpers = new Helpers();
30
-
31
- new SearchAppearance();
 
 
 
 
 
32
  }
33
  }
6
  exit;
7
  }
8
 
9
+ use AIOSEO\Plugin\Common\ImportExport;
10
+
11
+ class SeoPress extends ImportExport\Importer {
12
  /**
13
+ * A list of plugins to look for to import.
14
  *
15
+ * @since 4.1.4
16
  *
17
+ * @var array
18
+ */
19
+ public $plugins = [
20
+ [
21
+ 'name' => 'SEOPress',
22
+ 'version' => '4.0',
23
+ 'basename' => 'wp-seopress/seopress.php',
24
+ 'slug' => 'seopress'
25
+ ],
26
+ [
27
+ 'name' => 'SEOPress PRO',
28
+ 'version' => '4.0',
29
+ 'basename' => 'wp-seopress-pro/seopress-pro.php',
30
+ 'slug' => 'seopress-pro'
31
+ ],
32
+ ];
33
+
34
+ /**
35
+ * The post action name.
36
+ *
37
+ * @since 4.1.4
38
+ *
39
+ * @var string
40
  */
41
+ public $postActionName = 'aioseo_import_post_meta_seopress';
42
+
43
+ /**
44
+ * The post action name.
45
+ *
46
+ * @since 4.1.4
47
+ *
48
+ * @param ImportExport $importer The main importer class.
49
+ */
50
+ public function __construct( $importer ) {
51
+ $this->helpers = new Helpers();
52
+ $this->postMeta = new PostMeta();
53
+ add_action( $this->postActionName, [ $this->postMeta, 'importPostMeta' ] );
54
+
55
+ $plugins = $this->plugins;
56
+ foreach ( $plugins as $key => $plugin ) {
57
+ $plugins[ $key ]['class'] = $this;
58
+ }
59
+ $importer->addPlugins( $plugins );
60
  }
61
 
62
  /**
63
  * Imports the settings.
64
  *
65
+ * @since 4.1.4
66
  *
67
  * @return void
68
  */
69
+ protected function importSettings() {
70
+ new GeneralSettings();
71
+ new Analytics();
72
+ new SocialMeta();
73
+ new Titles();
74
+ new Sitemap();
75
+ new RobotsTxt();
76
+ new Rss();
77
+ new Breadcrumbs();
78
  }
79
  }
app/Common/ImportExport/SeoPress/Sitemap.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the Sitemap Settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class Sitemap {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_xml_sitemap_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ $this->migratePostTypesInclude();
29
+ $this->migrateTaxonomiesInclude();
30
+
31
+ $settings = [
32
+ 'seopress_xml_sitemap_general_enable' => [ 'type' => 'boolean', 'newOption' => [ 'sitemap', 'general', 'enable' ] ],
33
+ 'seopress_xml_sitemap_author_enable' => [ 'type' => 'boolean', 'newOption' => [ 'sitemap', 'general', 'author' ] ],
34
+ ];
35
+
36
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
37
+ }
38
+
39
+ /**
40
+ * Migrates the post types to include in sitemap settings.
41
+ *
42
+ * @since 4.1.4
43
+ *
44
+ * @return void
45
+ */
46
+ public function migratePostTypesInclude() {
47
+ $postTypesMigrate = $this->options['seopress_xml_sitemap_post_types_list'];
48
+ $postTypesInclude = [];
49
+
50
+ foreach ( $postTypesMigrate as $postType => $options ) {
51
+ $postTypesInclude[] = $postType;
52
+ }
53
+
54
+ aioseo()->options->sitemap->general->postTypes->included = $postTypesInclude;
55
+ }
56
+
57
+ /**
58
+ * Migrates the taxonomies to include in sitemap settings.
59
+ *
60
+ * @since 4.1.4
61
+ *
62
+ * @return void
63
+ */
64
+ public function migrateTaxonomiesInclude() {
65
+ $taxonomiesMigrate = $this->options['seopress_xml_sitemap_taxonomies_list'];
66
+ $taxonomiesInclude = [];
67
+
68
+ foreach ( $taxonomiesMigrate as $taxonomy => $options ) {
69
+ $taxonomiesInclude[] = $taxonomy;
70
+ }
71
+
72
+ aioseo()->options->sitemap->general->taxonomies->included = $taxonomiesInclude;
73
+ }
74
+ }
app/Common/ImportExport/SeoPress/SocialMeta.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the Social Meta Settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class SocialMeta {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_social_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ $this->migrateSocialUrls();
29
+ $this->migrateKnowledge();
30
+ $this->migrateFacebookSettings();
31
+ $this->migrateTwitterSettings();
32
+ }
33
+
34
+ /**
35
+ * Migrates Basic Social Profiles URLs.
36
+ *
37
+ * @since 4.1.4
38
+ *
39
+ * @return void
40
+ */
41
+ private function migrateSocialUrls() {
42
+ $settings = [
43
+ 'seopress_social_accounts_facebook' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'facebookPageUrl' ] ],
44
+ 'seopress_social_accounts_twitter' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'twitterUrl' ] ],
45
+ 'seopress_social_accounts_pinterest' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'pinterestUrl' ] ],
46
+ 'seopress_social_accounts_instagram' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'instagramUrl' ] ],
47
+ 'seopress_social_accounts_youtube' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'youtubeUrl' ] ],
48
+ 'seopress_social_accounts_linkedin' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'linkedinUrl' ] ],
49
+ 'seopress_social_accounts_myspace' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'myspaceUrl' ] ],
50
+ 'seopress_social_accounts_soundcloud' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'soundCloudUrl' ] ],
51
+ 'seopress_social_accounts_tumblr' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'tumblrUrl' ] ],
52
+ ];
53
+
54
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
55
+ }
56
+
57
+ /**
58
+ * Migrates Knowledge Graph data.
59
+ *
60
+ * @since 4.1.4
61
+ *
62
+ * @return void
63
+ */
64
+ private function migrateKnowledge() {
65
+ $type = 'organization';
66
+ if ( ! empty( $this->options['seopress_social_knowledge_type'] ) ) {
67
+ $type = strtolower( $this->options['seopress_social_knowledge_type'] );
68
+ if ( 'person' === $type ) {
69
+ aioseo()->options->searchAppearance->global->schema->person = 'manual';
70
+ }
71
+ }
72
+
73
+ aioseo()->options->searchAppearance->global->schema->siteRepresents = $type;
74
+
75
+ if ( ! empty( $this->options['seopress_social_knowledge_contact_type'] ) ) {
76
+ aioseo()->options->searchAppearance->global->schema->contactType = ucwords( $this->options['seopress_social_knowledge_contact_type'] );
77
+ }
78
+
79
+ $settings = [
80
+ 'seopress_social_knowledge_img' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', $type . 'Logo' ] ],
81
+ 'seopress_social_knowledge_name' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', $type . 'Name' ] ],
82
+ 'seopress_social_knowledge_phone' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'schema', 'phone' ] ],
83
+ ];
84
+
85
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
86
+ }
87
+
88
+ /**
89
+ * Migrates the Facebook settings.
90
+ *
91
+ * @since 4.1.4
92
+ *
93
+ * @return void
94
+ */
95
+ private function migrateFacebookSettings() {
96
+ if ( ! empty( $this->options['seopress_social_facebook_admin_id'] ) || ! empty( $this->options['seopress_social_facebook_app_id'] ) ) {
97
+ aioseo()->options->social->facebook->advanced->enable = true;
98
+ }
99
+
100
+ $settings = [
101
+ 'seopress_social_facebook_og' => [ 'type' => 'boolean', 'newOption' => [ 'social', 'facebook', 'general', 'enable' ] ],
102
+ 'seopress_social_facebook_img' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'homePage', 'image' ] ],
103
+ 'seopress_social_facebook_admin_id' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'advanced', 'adminId' ] ],
104
+ 'seopress_social_facebook_app_id' => [ 'type' => 'string', 'newOption' => [ 'social', 'facebook', 'advanced', 'appId' ] ],
105
+ ];
106
+
107
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
108
+ }
109
+
110
+ /**
111
+ * Migrates the Twitter settings.
112
+ *
113
+ * @since 4.1.4
114
+ *
115
+ * @return void
116
+ */
117
+ private function migrateTwitterSettings() {
118
+ if ( ! empty( $this->options['seopress_social_twitter_card_img_size'] ) ) {
119
+ $twitterCard = ( 'large' === $this->options['seopress_social_twitter_card_img_size'] ) ? 'summary-card' : 'summary';
120
+ aioseo()->options->social->twitter->general->defaultCardType = $twitterCard;
121
+ }
122
+
123
+ $settings = [
124
+ 'seopress_social_twitter_card' => [ 'type' => 'boolean', 'newOption' => [ 'social', 'twitter', 'general', 'enable' ] ],
125
+ 'seopress_social_twitter_card_img' => [ 'type' => 'string', 'newOption' => [ 'social', 'twitter', 'homePage', 'image' ] ],
126
+ ];
127
+
128
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
129
+ }
130
+ }
app/Common/ImportExport/SeoPress/Titles.php ADDED
@@ -0,0 +1,288 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\SeoPress;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
+
11
+ /**
12
+ * Migrates the Titles Settings.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class Titles {
17
+ /**
18
+ * Class constructor.
19
+ *
20
+ * @since 4.1.4
21
+ */
22
+ public function __construct() {
23
+ $this->options = get_option( 'seopress_titles_option_name' );
24
+ if ( empty( $this->options ) ) {
25
+ return;
26
+ }
27
+
28
+ if (
29
+ ! empty( $this->options['seopress_titles_archives_author_title'] ) ||
30
+ ! empty( $this->options['seopress_titles_archives_author_desc'] ) ||
31
+ ! empty( $this->options['seopress_titles_archives_author_noindex'] )
32
+ ) {
33
+ aioseo()->options->searchAppearance->archives->author->show = true;
34
+ }
35
+
36
+ if (
37
+ ! empty( $this->options['seopress_titles_archives_date_title'] ) ||
38
+ ! empty( $this->options['seopress_titles_archives_date_desc'] ) ||
39
+ ! empty( $this->options['seopress_titles_archives_date_noindex'] )
40
+ ) {
41
+ aioseo()->options->searchAppearance->archives->date->show = true;
42
+ }
43
+
44
+ if (
45
+ ! empty( $this->options['seopress_titles_archives_search_title'] ) ||
46
+ ! empty( $this->options['seopress_titles_archives_search_desc'] )
47
+ ) {
48
+ aioseo()->options->searchAppearance->archives->search->show = true;
49
+ }
50
+
51
+ $this->migrateTitleFormats();
52
+ $this->migrateDescriptionFormats();
53
+ $this->migrateNoIndexFormats();
54
+ $this->migratePostTypeSettings();
55
+ $this->migrateTaxonomiesSettings();
56
+ $this->migrateArchiveSettings();
57
+ $this->migrateAdvancedSettings();
58
+
59
+ $settings = [
60
+ 'seopress_titles_sep' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'separator' ] ],
61
+ ];
62
+
63
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options, true );
64
+ }
65
+
66
+ /**
67
+ * Migrates the title formats.
68
+ *
69
+ * @since 4.1.4
70
+ *
71
+ * @return void
72
+ */
73
+ private function migrateTitleFormats() {
74
+ $settings = [
75
+ 'seopress_titles_home_site_title' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'siteTitle' ] ],
76
+ 'seopress_titles_archives_author_title' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'title' ] ],
77
+ 'seopress_titles_archives_date_title' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'title' ] ],
78
+ 'seopress_titles_archives_search_title' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'search', 'title' ] ],
79
+ ];
80
+
81
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options, true );
82
+ }
83
+
84
+ /**
85
+ * Migrates the description formats.
86
+ *
87
+ * @since 4.1.4
88
+ *
89
+ * @return void
90
+ */
91
+ private function migrateDescriptionFormats() {
92
+ $settings = [
93
+ 'seopress_titles_home_site_desc' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'global', 'metaDescription' ] ],
94
+ 'seopress_titles_archives_author_desc' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'metaDescription' ] ],
95
+ 'seopress_titles_archives_date_desc' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'metaDescription' ] ],
96
+ 'seopress_titles_archives_search_desc' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'search', 'metaDescription' ] ],
97
+ ];
98
+
99
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options, true );
100
+ }
101
+
102
+ /**
103
+ * Migrates the NoIndex formats.
104
+ *
105
+ * @since 4.1.4
106
+ *
107
+ * @return void
108
+ */
109
+ private function migrateNoIndexFormats() {
110
+ $settings = [
111
+ 'seopress_titles_archives_author_noindex' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'show' ] ],
112
+ 'seopress_titles_archives_date_noindex' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'show' ] ],
113
+ ];
114
+
115
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
116
+ }
117
+
118
+ /**
119
+ * Migrates the post type settings.
120
+ *
121
+ * @since 4.1.4
122
+ *
123
+ * @return void
124
+ */
125
+ private function migratePostTypeSettings() {
126
+ $titles = $this->options['seopress_titles_single_titles'];
127
+ if ( empty( $titles ) ) {
128
+ return;
129
+ }
130
+
131
+ foreach ( $titles as $postType => $options ) {
132
+ if ( ! aioseo()->dynamicOptions->searchAppearance->postTypes->has( $postType ) ) {
133
+ continue;
134
+ }
135
+
136
+ if ( ! empty( $options['title'] ) ) {
137
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->title =
138
+ aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['title'] ) );
139
+ }
140
+
141
+ if ( ! empty( $options['description'] ) ) {
142
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->metaDescription =
143
+ aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['description'] ) );
144
+ }
145
+
146
+ if ( ! empty( $options['enable'] ) ) {
147
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showMetaBox = false;
148
+ }
149
+
150
+ if ( ! empty( $options['noindex'] ) ) {
151
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->show = false;
152
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = false;
153
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = true;
154
+ }
155
+
156
+ if ( ! empty( $options['nofollow'] ) ) {
157
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->show = false;
158
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = false;
159
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->nofollow = true;
160
+ }
161
+
162
+ if ( ! empty( $options['date'] ) ) {
163
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showDateInGooglePreview = false;
164
+ }
165
+
166
+ if ( ! empty( $options['thumb_gcs'] ) ) {
167
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showPostThumbnailInSearch = true;
168
+ }
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Migrates the taxonomies settings.
174
+ *
175
+ * @since 4.1.4
176
+ *
177
+ * @return void
178
+ */
179
+ private function migrateTaxonomiesSettings() {
180
+ $titles = $this->options['seopress_titles_tax_titles'];
181
+ if ( empty( $titles ) ) {
182
+ return;
183
+ }
184
+
185
+ foreach ( $titles as $taxonomy => $options ) {
186
+ if ( ! aioseo()->dynamicOptions->searchAppearance->taxonomies->has( $taxonomy ) ) {
187
+ continue;
188
+ }
189
+
190
+ if ( ! empty( $options['title'] ) ) {
191
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->title =
192
+ aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['title'] ) );
193
+ }
194
+
195
+ if ( ! empty( $options['description'] ) ) {
196
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->metaDescription =
197
+ aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['description'] ) );
198
+ }
199
+
200
+ if ( ! empty( $options['enable'] ) ) {
201
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->showMetaBox = false;
202
+ }
203
+
204
+ if ( ! empty( $options['noindex'] ) ) {
205
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->show = false;
206
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->default = false;
207
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->noindex = true;
208
+ }
209
+
210
+ if ( ! empty( $options['nofollow'] ) ) {
211
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->show = false;
212
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->default = false;
213
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->nofollow = true;
214
+ }
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Migrates the archives settings.
220
+ *
221
+ * @since 4.1.4
222
+ *
223
+ * @return void
224
+ */
225
+ private function migrateArchiveSettings() {
226
+ $titles = $this->options['seopress_titles_archive_titles'];
227
+ if ( empty( $titles ) ) {
228
+ return;
229
+ }
230
+
231
+ foreach ( $titles as $archive => $options ) {
232
+ if ( ! aioseo()->dynamicOptions->searchAppearance->archives->has( $archive ) ) {
233
+ continue;
234
+ }
235
+
236
+ if ( ! empty( $options['title'] ) ) {
237
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->title =
238
+ aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['title'] ) );
239
+ }
240
+
241
+ if ( ! empty( $options['description'] ) ) {
242
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->metaDescription =
243
+ aioseo()->helpers->sanitizeOption( aioseo()->importExport->seoPress->helpers->macrosToSmartTags( $options['description'] ) );
244
+ }
245
+
246
+ if ( ! empty( $options['noindex'] ) ) {
247
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->show = false;
248
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->default = false;
249
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->noindex = true;
250
+ }
251
+
252
+ if ( ! empty( $options['nofollow'] ) ) {
253
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->show = false;
254
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->default = false;
255
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->advanced->robotsMeta->nofollow = true;
256
+ }
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Migrates the advanced settings.
262
+ *
263
+ * @since 4.1.4
264
+ *
265
+ * @return void
266
+ */
267
+ private function migrateAdvancedSettings() {
268
+ if (
269
+ ! empty( $this->options['seopress_titles_noindex'] ) || ! empty( $this->options['seopress_titles_nofollow'] ) || ! empty( $this->options['seopress_titles_noodp'] ) ||
270
+ ! empty( $this->options['seopress_titles_noimageindex'] ) || ! empty( $this->options['seopress_titles_noarchive'] ) ||
271
+ ! empty( $this->options['seopress_titles_nosnippet'] ) || ! empty( $this->options['seopress_titles_paged_noindex'] )
272
+ ) {
273
+ aioseo()->options->searchAppearance->advanced->globalRobotsMeta->default = false;
274
+ }
275
+
276
+ $settings = [
277
+ 'seopress_titles_noindex' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noindex' ] ],
278
+ 'seopress_titles_nofollow' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'nofollow' ] ],
279
+ 'seopress_titles_noodp' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noodp' ] ],
280
+ 'seopress_titles_noimageindex' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noimageindex' ] ],
281
+ 'seopress_titles_noarchive' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noarchive' ] ],
282
+ 'seopress_titles_nosnippet' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'nosnippet' ] ],
283
+ 'seopress_titles_paged_noindex' => [ 'type' => 'boolean', 'newOption' => [ 'searchAppearance', 'advanced', 'globalRobotsMeta', 'noindexPaginated' ] ],
284
+ ];
285
+
286
+ aioseo()->importExport->seoPress->helpers->mapOldToNew( $settings, $this->options );
287
+ }
288
+ }
app/Common/ImportExport/YoastSeo/GeneralSettings.php CHANGED
@@ -25,8 +25,6 @@ class GeneralSettings {
25
  return;
26
  }
27
 
28
- $this->checkIfTrueSeoIsDisabled();
29
-
30
  $settings = [
31
  'googleverify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'google' ] ],
32
  'msverify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'bing' ] ],
@@ -37,21 +35,4 @@ class GeneralSettings {
37
 
38
  aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
39
  }
40
-
41
- /**
42
- * Checks if TrueSEO should be disabled.
43
- *
44
- * @since 4.0.0
45
- *
46
- * @return void
47
- */
48
- private function checkIfTrueSeoIsDisabled() {
49
- if ( ! isset( $this->options['content_analysis_active'] ) || ! isset( $this->options['keyword_analysis_active'] ) ) {
50
- return;
51
- }
52
-
53
- if ( ! $this->options['content_analysis_active'] && ! $this->options['keyword_analysis_active'] ) {
54
- aioseo()->options->advanced->truSeo = false;
55
- }
56
- }
57
  }
25
  return;
26
  }
27
 
 
 
28
  $settings = [
29
  'googleverify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'google' ] ],
30
  'msverify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'bing' ] ],
35
 
36
  aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
app/Common/ImportExport/YoastSeo/PostMeta.php CHANGED
@@ -53,9 +53,7 @@ class PostMeta {
53
  $posts = aioseo()->db
54
  ->start( 'posts' . ' as p' )
55
  ->select( 'p.ID, p.post_type' )
56
- ->join( 'postmeta as pm', '`p`.`ID` = `pm`.`post_id`' )
57
  ->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
58
- ->whereRaw( "pm.meta_key LIKE '_yoast_wpseo_%'" )
59
  ->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
60
  ->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
61
  ->orderBy( 'p.ID DESC' )
@@ -84,7 +82,8 @@ class PostMeta {
84
  '_yoast_wpseo_twitter-description' => 'twitter_description',
85
  '_yoast_wpseo_twitter-image' => 'twitter_image_custom_url',
86
  '_yoast_wpseo_schema_page_type' => '',
87
- '_yoast_wpseo_schema_article_type' => ''
 
88
  ];
89
 
90
  foreach ( $posts as $post ) {
@@ -96,14 +95,25 @@ class PostMeta {
96
  ->run()
97
  ->result();
98
 
 
 
 
 
 
 
 
 
 
99
  if ( ! $postMeta || ! count( $postMeta ) ) {
 
 
 
 
 
100
  continue;
101
  }
102
 
103
- $meta = [
104
- 'post_id' => (int) $post->ID,
105
- ];
106
-
107
  foreach ( $postMeta as $record ) {
108
  $name = $record->meta_key;
109
  $value = $record->meta_value;
@@ -113,6 +123,17 @@ class PostMeta {
113
  }
114
 
115
  switch ( $name ) {
 
 
 
 
 
 
 
 
 
 
 
116
  case '_yoast_wpseo_meta-robots-noindex':
117
  case '_yoast_wpseo_meta-robots-nofollow':
118
  if ( (bool) $value ) {
@@ -205,20 +226,39 @@ class PostMeta {
205
  case '_yoast_wpseo_metadesc':
206
  case '_yoast_wpseo_opengraph-title':
207
  case '_yoast_wpseo_opengraph-description':
 
 
208
  if ( 'page' === $post->post_type ) {
209
  $value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
210
  $value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
211
  }
 
 
 
 
 
212
  $value = aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, 'post', $post->post_type );
 
 
 
 
213
  default:
214
  $meta[ $mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
215
  break;
216
  }
217
  }
218
 
 
 
 
 
 
 
219
  $aioseoPost = Models\Post::getPost( (int) $post->ID );
220
  $aioseoPost->set( $meta );
221
  $aioseoPost->save();
 
 
222
  }
223
 
224
  if ( count( $posts ) === $postsPerAction ) {
53
  $posts = aioseo()->db
54
  ->start( 'posts' . ' as p' )
55
  ->select( 'p.ID, p.post_type' )
 
56
  ->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
 
57
  ->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
58
  ->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
59
  ->orderBy( 'p.ID DESC' )
82
  '_yoast_wpseo_twitter-description' => 'twitter_description',
83
  '_yoast_wpseo_twitter-image' => 'twitter_image_custom_url',
84
  '_yoast_wpseo_schema_page_type' => '',
85
+ '_yoast_wpseo_schema_article_type' => '',
86
+ '_yoast_wpseo_primary_category' => 'og_article_section'
87
  ];
88
 
89
  foreach ( $posts as $post ) {
95
  ->run()
96
  ->result();
97
 
98
+ $categories = aioseo()->helpers->getAllCategories( $post->ID );
99
+ $featuredImage = get_the_post_thumbnail_url( $post->ID );
100
+ $meta = [
101
+ 'post_id' => (int) $post->ID,
102
+ 'twitter_use_og' => true,
103
+ 'og_image_type' => $featuredImage ? 'featured' : 'content',
104
+ 'og_article_section' => ! empty( $categories ) ? $categories[0] : null
105
+ ];
106
+
107
  if ( ! $postMeta || ! count( $postMeta ) ) {
108
+ $aioseoPost = Models\Post::getPost( (int) $post->ID );
109
+ $aioseoPost->set( $meta );
110
+ $aioseoPost->save();
111
+
112
+ aioseo()->migration->meta->migrateAdditionalPostMeta( $post->ID );
113
  continue;
114
  }
115
 
116
+ $title = '';
 
 
 
117
  foreach ( $postMeta as $record ) {
118
  $name = $record->meta_key;
119
  $value = $record->meta_value;
123
  }
124
 
125
  switch ( $name ) {
126
+ case '_yoast_wpseo_primary_category':
127
+ $primaryCategory = get_cat_name( $value );
128
+ foreach ( $categories as $category ) {
129
+ if ( aioseo()->helpers->toLowerCase( $primaryCategory ) === aioseo()->helpers->toLowerCase( $category ) ) {
130
+ $meta[ $mappedMeta[ $name ] ] = $category;
131
+ break 2;
132
+ }
133
+ }
134
+
135
+ $meta[ $mappedMeta[ $name ] ] = ! empty( $categories ) ? $categories[0] : ( ! empty( $primaryCategory ) ? $primaryCategory : '' );
136
+ break;
137
  case '_yoast_wpseo_meta-robots-noindex':
138
  case '_yoast_wpseo_meta-robots-nofollow':
139
  if ( (bool) $value ) {
226
  case '_yoast_wpseo_metadesc':
227
  case '_yoast_wpseo_opengraph-title':
228
  case '_yoast_wpseo_opengraph-description':
229
+ case '_yoast_wpseo_twitter-title':
230
+ case '_yoast_wpseo_twitter-description':
231
  if ( 'page' === $post->post_type ) {
232
  $value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
233
  $value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
234
  }
235
+
236
+ if ( '_yoast_wpseo_twitter-title' === $name || '_yoast_wpseo_twitter-description' === $name ) {
237
+ $meta['twitter_use_og'] = false;
238
+ }
239
+
240
  $value = aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, 'post', $post->post_type );
241
+
242
+ if ( '_yoast_wpseo_title' === $name ) {
243
+ $title = $value;
244
+ }
245
  default:
246
  $meta[ $mappedMeta[ $name ] ] = esc_html( wp_strip_all_tags( strval( $value ) ) );
247
  break;
248
  }
249
  }
250
 
251
+ // Resetting the `twitter_use_og` option if the user has a custom title and no twitter title.
252
+ if ( $meta['twitter_use_og'] && $title && empty( $meta['twitter_title'] ) ) {
253
+ $meta['twitter_use_og'] = false;
254
+ $meta['twitter_title'] = $title;
255
+ }
256
+
257
  $aioseoPost = Models\Post::getPost( (int) $post->ID );
258
  $aioseoPost->set( $meta );
259
  $aioseoPost->save();
260
+
261
+ aioseo()->migration->meta->migrateAdditionalPostMeta( $post->ID );
262
  }
263
 
264
  if ( count( $posts ) === $postsPerAction ) {
app/Common/ImportExport/YoastSeo/SearchAppearance.php CHANGED
@@ -161,7 +161,7 @@ class SearchAppearance {
161
  $value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
162
  $value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
163
  }
164
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->title =
165
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType ) );
166
  break;
167
  case 'metadesc':
@@ -169,17 +169,17 @@ class SearchAppearance {
169
  $value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
170
  $value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
171
  }
172
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->metaDescription =
173
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType ) );
174
  break;
175
  case 'noindex':
176
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->show = empty( $value ) ? true : false;
177
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default = empty( $value ) ? true : false;
178
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->noindex = empty( $value ) ? false : true;
179
  break;
180
  case 'display-metabox-pt':
181
  if ( empty( $value ) ) {
182
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->showMetaBox = false;
183
  }
184
  break;
185
  case 'schema-page-type':
@@ -187,25 +187,25 @@ class SearchAppearance {
187
  if ( in_array( $postType, [ 'post', 'page', 'attachment' ], true ) ) {
188
  break;
189
  }
190
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->schemaType = 'WebPage';
191
  if ( in_array( $value, ImportExport\SearchAppearance::$supportedWebPageGraphs, true ) ) {
192
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->webPageType = $value;
193
  }
194
  break;
195
  case 'schema-article-type':
196
  $value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
197
  if ( 'none' === lcfirst( $value ) ) {
198
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->articleType = 'none';
199
  break;
200
  }
201
 
202
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->articleType = 'Article';
203
  if ( in_array( $value, ImportExport\SearchAppearance::$supportedArticleGraphs, true ) ) {
204
  if ( ! in_array( $postType, [ 'page', 'attachment' ], true ) ) {
205
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->articleType = $value;
206
  }
207
  } else {
208
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->articleType = 'BlogPosting';
209
  }
210
  break;
211
  default:
@@ -237,17 +237,17 @@ class SearchAppearance {
237
 
238
  switch ( $match[1] ) {
239
  case 'title':
240
- aioseo()->options->searchAppearance->dynamic->archives->$postType->title =
241
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType, 'archive' ) );
242
  break;
243
  case 'metadesc':
244
- aioseo()->options->searchAppearance->dynamic->archives->$postType->metaDescription =
245
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType, 'archive' ) );
246
  break;
247
  case 'noindex':
248
- aioseo()->options->searchAppearance->dynamic->archives->$postType->show = empty( $value ) ? true : false;
249
- aioseo()->options->searchAppearance->dynamic->archives->$postType->advanced->robotsMeta->default = empty( $value ) ? true : false;
250
- aioseo()->options->searchAppearance->dynamic->archives->$postType->advanced->robotsMeta->noindex = empty( $value ) ? false : true;
251
  break;
252
  default:
253
  break;
@@ -305,6 +305,6 @@ class SearchAppearance {
305
  * @return void
306
  */
307
  private function migrateRedirectAttachments() {
308
- aioseo()->options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls = empty( $this->options['disable-attachment'] ) ? 'disabled' : 'attachment';
309
  }
310
  }
161
  $value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
162
  $value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
163
  }
164
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->title =
165
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType ) );
166
  break;
167
  case 'metadesc':
169
  $value = aioseo()->helpers->pregReplace( '#%%primary_category%%#', '', $value );
170
  $value = aioseo()->helpers->pregReplace( '#%%excerpt%%#', '', $value );
171
  }
172
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->metaDescription =
173
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType ) );
174
  break;
175
  case 'noindex':
176
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->show = empty( $value ) ? true : false;
177
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = empty( $value ) ? true : false;
178
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = empty( $value ) ? false : true;
179
  break;
180
  case 'display-metabox-pt':
181
  if ( empty( $value ) ) {
182
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->showMetaBox = false;
183
  }
184
  break;
185
  case 'schema-page-type':
187
  if ( in_array( $postType, [ 'post', 'page', 'attachment' ], true ) ) {
188
  break;
189
  }
190
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->schemaType = 'WebPage';
191
  if ( in_array( $value, ImportExport\SearchAppearance::$supportedWebPageGraphs, true ) ) {
192
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->webPageType = $value;
193
  }
194
  break;
195
  case 'schema-article-type':
196
  $value = aioseo()->helpers->pregReplace( '#\s#', '', $value );
197
  if ( 'none' === lcfirst( $value ) ) {
198
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'none';
199
  break;
200
  }
201
 
202
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'Article';
203
  if ( in_array( $value, ImportExport\SearchAppearance::$supportedArticleGraphs, true ) ) {
204
  if ( ! in_array( $postType, [ 'page', 'attachment' ], true ) ) {
205
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = $value;
206
  }
207
  } else {
208
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->articleType = 'BlogPosting';
209
  }
210
  break;
211
  default:
237
 
238
  switch ( $match[1] ) {
239
  case 'title':
240
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->title =
241
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType, 'archive' ) );
242
  break;
243
  case 'metadesc':
244
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->metaDescription =
245
  aioseo()->helpers->sanitizeOption( aioseo()->importExport->yoastSeo->helpers->macrosToSmartTags( $value, $postType, 'archive' ) );
246
  break;
247
  case 'noindex':
248
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->show = empty( $value ) ? true : false;
249
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->default = empty( $value ) ? true : false;
250
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->noindex = empty( $value ) ? false : true;
251
  break;
252
  default:
253
  break;
305
  * @return void
306
  */
307
  private function migrateRedirectAttachments() {
308
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = empty( $this->options['disable-attachment'] ) ? 'disabled' : 'attachment';
309
  }
310
  }
app/Common/ImportExport/YoastSeo/SocialMeta.php CHANGED
@@ -6,6 +6,8 @@ if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
 
 
9
  // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
10
 
11
  /**
@@ -30,6 +32,9 @@ class SocialMeta {
30
  $this->migrateFacebookSettings();
31
  $this->migrateTwitterSettings();
32
  $this->migrateFacebookAdminId();
 
 
 
33
 
34
  $settings = [
35
  'pinterestverify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'pinterest' ] ]
@@ -38,6 +43,13 @@ class SocialMeta {
38
  aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
39
  }
40
 
 
 
 
 
 
 
 
41
  private function migrateSocialUrls() {
42
  $settings = [
43
  'facebook_site' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'facebookPageUrl' ] ],
@@ -82,6 +94,18 @@ class SocialMeta {
82
  ];
83
 
84
  aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options, true );
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  /**
@@ -113,4 +137,41 @@ class SocialMeta {
113
  aioseo()->options->social->facebook->advanced->adminId = aioseo()->helpers->sanitizeOption( $this->options['fbadminapp'] );
114
  }
115
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
6
  exit;
7
  }
8
 
9
+ use AIOSEO\Plugin\Common\Models;
10
+
11
  // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
12
 
13
  /**
32
  $this->migrateFacebookSettings();
33
  $this->migrateTwitterSettings();
34
  $this->migrateFacebookAdminId();
35
+ $this->migrateSiteName();
36
+ $this->migrateArticleTags();
37
+ $this->migrateAdditionalTwitterData();
38
 
39
  $settings = [
40
  'pinterestverify' => [ 'type' => 'string', 'newOption' => [ 'webmasterTools', 'pinterest' ] ]
43
  aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options );
44
  }
45
 
46
+ /**
47
+ * Migrates the Social URLs.
48
+ *
49
+ * @since 4.0.0
50
+ *
51
+ * @return void
52
+ */
53
  private function migrateSocialUrls() {
54
  $settings = [
55
  'facebook_site' => [ 'type' => 'string', 'newOption' => [ 'social', 'profiles', 'urls', 'facebookPageUrl' ] ],
94
  ];
95
 
96
  aioseo()->importExport->yoastSeo->helpers->mapOldToNew( $settings, $this->options, true );
97
+
98
+ // Migrate home page object type.
99
+ aioseo()->options->social->facebook->homePage->objectType = 'website';
100
+ if ( 'page' === get_option( 'show_on_front' ) ) {
101
+ $staticHomePageId = get_option( 'page_on_front' );
102
+
103
+ $aioseoPost = Models\Post::getPost( (int) $staticHomePageId );
104
+ $aioseoPost->set( [
105
+ 'og_object_type' => 'website'
106
+ ] );
107
+ $aioseoPost->save();
108
+ }
109
  }
110
 
111
  /**
137
  aioseo()->options->social->facebook->advanced->adminId = aioseo()->helpers->sanitizeOption( $this->options['fbadminapp'] );
138
  }
139
  }
140
+
141
+ /**
142
+ * Yoast sets the og:site_name to '#site_title';
143
+ *
144
+ * @since 4.1.4
145
+ *
146
+ * @return void
147
+ */
148
+ private function migrateSiteName() {
149
+ aioseo()->options->social->facebook->general->siteName = '#site_title';
150
+ }
151
+
152
+ /**
153
+ * Yoast uses post tags by default, so we need to enable this.
154
+ *
155
+ * @since 4.1.4
156
+ *
157
+ * @return void
158
+ */
159
+ private function migrateArticleTags() {
160
+ aioseo()->options->social->facebook->advanced->enable = true;
161
+ aioseo()->options->social->facebook->advanced->generateArticleTags = true;
162
+ aioseo()->options->social->facebook->advanced->usePostTagsInTags = true;
163
+ aioseo()->options->social->facebook->advanced->useKeywordsInTags = false;
164
+ aioseo()->options->social->facebook->advanced->useCategoriesInTags = false;
165
+ }
166
+
167
+ /**
168
+ * Enable additional Twitter Data.
169
+ *
170
+ * @since 4.1.4
171
+ *
172
+ * @return void
173
+ */
174
+ private function migrateAdditionalTwitterData() {
175
+ aioseo()->options->social->twitter->general->additionalData = true;
176
+ }
177
  }
app/Common/ImportExport/YoastSeo/UserMeta.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\ImportExport\YoastSeo;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ use AIOSEO\Plugin\Common\ImportExport;
10
+ use AIOSEO\Plugin\Common\Models;
11
+
12
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
13
+
14
+ /**
15
+ * Imports the user meta from Yoast SEO.
16
+ *
17
+ * @since 4.0.0
18
+ */
19
+ class UserMeta {
20
+ /**
21
+ * Class constructor.
22
+ *
23
+ * @since 4.0.0
24
+ */
25
+ public function scheduleImport() {
26
+ aioseo()->helpers->scheduleSingleAction( aioseo()->importExport->yoastSeo->userActionName, 30 );
27
+
28
+ if ( ! aioseo()->transients->get( 'import_user_meta_yoast_seo' ) ) {
29
+ aioseo()->transients->update( 'import_user_meta_yoast_seo', 0, WEEK_IN_SECONDS );
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Imports the post meta.
35
+ *
36
+ * @since 4.0.0
37
+ *
38
+ * @return void
39
+ */
40
+ public function importUserMeta() {
41
+ $usersPerAction = 100;
42
+ $offset = aioseo()->transients->get( 'import_user_meta_yoast_seo' );
43
+
44
+ $usersMeta = aioseo()->db
45
+ ->start( 'usermeta' . ' as um' )
46
+ ->whereRaw( "um.meta_key IN ('facebook', 'twitter')" )
47
+ ->whereRaw( "um.meta_value != ''" )
48
+ ->limit( $offset . ',' . $usersPerAction )
49
+ ->run()
50
+ ->result();
51
+
52
+ if ( ! $usersMeta || ! count( $usersMeta ) ) {
53
+ aioseo()->transients->delete( 'import_user_meta_yoast_seo' );
54
+ return;
55
+ }
56
+
57
+ foreach ( $usersMeta as $meta ) {
58
+ update_user_meta( $meta->user_id, 'aioseo_' . $meta->meta_key, $meta->meta_value );
59
+ }
60
+
61
+ if ( count( $usersMeta ) === $usersPerAction ) {
62
+ aioseo()->transients->update( 'import_user_meta_yoast_seo', 100 + $offset, WEEK_IN_SECONDS );
63
+ aioseo()->helpers->scheduleSingleAction( aioseo()->importExport->yoastSeo->userActionName, 5 );
64
+ } else {
65
+ aioseo()->transients->delete( 'import_user_meta_yoast_seo' );
66
+ }
67
+ }
68
+ }
app/Common/ImportExport/YoastSeo/YoastSeo.php CHANGED
@@ -40,6 +40,15 @@ class YoastSeo extends ImportExport\Importer {
40
  */
41
  public $postActionName = 'aioseo_import_post_meta_yoast_seo';
42
 
 
 
 
 
 
 
 
 
 
43
  /**
44
  * The post action name.
45
  *
@@ -50,7 +59,9 @@ class YoastSeo extends ImportExport\Importer {
50
  public function __construct( $importer ) {
51
  $this->helpers = new Helpers();
52
  $this->postMeta = new PostMeta();
 
53
  add_action( $this->postActionName, [ $this->postMeta, 'importPostMeta' ] );
 
54
 
55
  $plugins = $this->plugins;
56
  foreach ( $plugins as $key => $plugin ) {
@@ -70,5 +81,6 @@ class YoastSeo extends ImportExport\Importer {
70
  new GeneralSettings();
71
  new SearchAppearance();
72
  new SocialMeta();
 
73
  }
74
  }
40
  */
41
  public $postActionName = 'aioseo_import_post_meta_yoast_seo';
42
 
43
+ /**
44
+ * The user action name.
45
+ *
46
+ * @since 4.1.4
47
+ *
48
+ * @var string
49
+ */
50
+ public $userActionName = 'aioseo_import_user_meta_yoast_seo';
51
+
52
  /**
53
  * The post action name.
54
  *
59
  public function __construct( $importer ) {
60
  $this->helpers = new Helpers();
61
  $this->postMeta = new PostMeta();
62
+ $this->userMeta = new UserMeta();
63
  add_action( $this->postActionName, [ $this->postMeta, 'importPostMeta' ] );
64
+ add_action( $this->userActionName, [ $this->userMeta, 'importUserMeta' ] );
65
 
66
  $plugins = $this->plugins;
67
  foreach ( $plugins as $key => $plugin ) {
81
  new GeneralSettings();
82
  new SearchAppearance();
83
  new SocialMeta();
84
+ $this->userMeta->scheduleImport();
85
  }
86
  }
app/Common/Main/Activate.php CHANGED
@@ -20,7 +20,17 @@ class Activate {
20
  public function __construct() {
21
  register_activation_hook( AIOSEO_FILE, [ $this, 'activate' ] );
22
  register_deactivation_hook( AIOSEO_FILE, [ $this, 'deactivate' ] );
 
 
23
 
 
 
 
 
 
 
 
 
24
  // If Pro just deactivated the lite version, we need to manually run the activation hook, because it doesn't run here.
25
  $proDeactivatedLite = (bool) aioseo()->transients->get( 'pro_just_deactivated_lite' );
26
  if ( $proDeactivatedLite ) {
20
  public function __construct() {
21
  register_activation_hook( AIOSEO_FILE, [ $this, 'activate' ] );
22
  register_deactivation_hook( AIOSEO_FILE, [ $this, 'deactivate' ] );
23
+ add_action( 'init', [ $this, 'init' ] );
24
+ }
25
 
26
+ /**
27
+ * Initialize activation.
28
+ *
29
+ * @since 4.1.5
30
+ *
31
+ * @return void
32
+ */
33
+ public function init() {
34
  // If Pro just deactivated the lite version, we need to manually run the activation hook, because it doesn't run here.
35
  $proDeactivatedLite = (bool) aioseo()->transients->get( 'pro_just_deactivated_lite' );
36
  if ( $proDeactivatedLite ) {
app/Common/Main/Filters.php CHANGED
@@ -23,6 +23,15 @@ abstract class Filters {
23
  */
24
  private $plugin;
25
 
 
 
 
 
 
 
 
 
 
26
  /**
27
  * Construct method.
28
  *
@@ -44,11 +53,15 @@ abstract class Filters {
44
  add_filter( 'wpaas_cdn_file_ext', [ $this, 'goDaddySitemapXml' ] );
45
 
46
  // Duplicate Post integration.
47
- add_action( 'dp_duplicate_post', [ $this, 'duplicatePostIntegration' ], 10, 3 );
48
- add_action( 'dp_duplicate_page', [ $this, 'duplicatePostIntegration' ], 10, 3 );
 
49
 
50
  // Classic Editor emoji
51
  add_action( 'init', [ $this, 'removeEmojiScript' ] );
 
 
 
52
  }
53
 
54
  /**
@@ -58,11 +71,11 @@ abstract class Filters {
58
  *
59
  * @param integer $newPostId The new post ID.
60
  * @param WP_Post $originalPost The original post object.
61
- * @param string $status The status of the post.
62
  * @return void
63
  */
64
- public function duplicatePostIntegration( $newPostId, $originalPost, $status ) {
65
- $originalAioseoPost = Models\Post::getPost( $originalPost->ID );
 
66
  if ( ! $originalAioseoPost->exists() ) {
67
  return;
68
  }
@@ -89,6 +102,37 @@ abstract class Filters {
89
  $newPost->save();
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  /**
93
  * Disable SEO inside the Genesis theme if it's running.
94
  *
@@ -178,4 +222,18 @@ abstract class Filters {
178
  remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
179
  }
180
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  }
23
  */
24
  private $plugin;
25
 
26
+ /**
27
+ * ID of the WooCommerce product that is being duplicated.
28
+ *
29
+ * @since 4.1.4
30
+ *
31
+ * @var integer
32
+ */
33
+ private static $originalProductId;
34
+
35
  /**
36
  * Construct method.
37
  *
53
  add_filter( 'wpaas_cdn_file_ext', [ $this, 'goDaddySitemapXml' ] );
54
 
55
  // Duplicate Post integration.
56
+ add_action( 'dp_duplicate_post', [ $this, 'duplicatePost' ], 10, 2 );
57
+ add_action( 'dp_duplicate_page', [ $this, 'duplicatePost' ], 10, 2 );
58
+ add_action( 'woocommerce_product_duplicate_before_save', [ $this, 'scheduleDuplicateProduct' ], 10, 2 );
59
 
60
  // Classic Editor emoji
61
  add_action( 'init', [ $this, 'removeEmojiScript' ] );
62
+
63
+ // Bypass the JWT Auth plugin's unnecessary restrictions. https://wordpress.org/plugins/jwt-auth/
64
+ add_filter( 'jwt_auth_default_whitelist', [ $this, 'allowRestRoutes' ] );
65
  }
66
 
67
  /**
71
  *
72
  * @param integer $newPostId The new post ID.
73
  * @param WP_Post $originalPost The original post object.
 
74
  * @return void
75
  */
76
+ public function duplicatePost( $newPostId, $originalPost ) {
77
+ $originalPostId = is_object( $originalPost ) ? $originalPost->ID : $originalPost;
78
+ $originalAioseoPost = Models\Post::getPost( $originalPostId );
79
  if ( ! $originalAioseoPost->exists() ) {
80
  return;
81
  }
102
  $newPost->save();
103
  }
104
 
105
+ /**
106
+ * Schedules an action to duplicate our meta after the duplicated WooCommerce product has been saved.
107
+ *
108
+ * @since 4.1.4
109
+ *
110
+ * @param \WP_Product $newProduct The new, duplicated product.
111
+ * @param \WP_Product $originalProduct The original product.
112
+ * @return void
113
+ */
114
+ public function scheduleDuplicateProduct( $newProduct, $originalProduct ) {
115
+ self::$originalProductId = $originalProduct->get_id();
116
+ add_action( 'wp_insert_post', [ $this, 'duplicateProduct' ], 10, 2 );
117
+ }
118
+
119
+ /**
120
+ * Duplicates our meta for the new WooCommerce product.
121
+ *
122
+ * @since 4.1.4
123
+ *
124
+ * @param integer $postId The new post ID.
125
+ * @param \WP_Post $post The new post object.
126
+ * @return void
127
+ */
128
+ public function duplicateProduct( $postId, $post ) {
129
+ if ( ! self::$originalProductId || 'product' !== $post->post_type ) {
130
+ return;
131
+ }
132
+
133
+ $this->duplicatePost( $postId, self::$originalProductId );
134
+ }
135
+
136
  /**
137
  * Disable SEO inside the Genesis theme if it's running.
138
  *
222
  remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
223
  }
224
  }
225
+
226
+ /**
227
+ * Add our routes to this plugins allow list.
228
+ *
229
+ * @since 4.1.4
230
+ *
231
+ * @param array $allowList The original list.
232
+ * @return array The modified list.
233
+ */
234
+ public function allowRestRoutes( $allowList ) {
235
+ return array_merge( $allowList, [
236
+ '/aioseo/'
237
+ ] );
238
+ }
239
  }
app/Common/Main/Main.php CHANGED
@@ -6,6 +6,8 @@ if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
 
 
9
  /**
10
  * Abstract class that Pro and Lite both extend.
11
  *
@@ -34,10 +36,18 @@ class Main {
34
  */
35
  public function enqueueAssets() {
36
  // Scripts.
37
- aioseo()->helpers->enqueueScript(
38
- 'aioseo-app',
39
- 'js/app.js'
40
- );
 
 
 
 
 
 
 
 
41
  aioseo()->helpers->enqueueScript(
42
  'aioseo-vendors',
43
  'js/chunk-vendors.js'
@@ -47,6 +57,22 @@ class Main {
47
  'js/chunk-common.js'
48
  );
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  // Styles.
51
  $rtl = is_rtl() ? '.rtl' : '';
52
  aioseo()->helpers->enqueueStyle(
@@ -57,10 +83,13 @@ class Main {
57
  'aioseo-vendors',
58
  "css/chunk-vendors$rtl.css"
59
  );
60
- aioseo()->helpers->enqueueStyle(
61
- 'aioseo-app-style',
62
- "css/app$rtl.css"
63
- );
 
 
 
64
  }
65
 
66
  /**
@@ -71,14 +100,19 @@ class Main {
71
  * @return void
72
  */
73
  public function enqueueFrontEndAssets() {
74
- if ( ! is_user_logged_in() || ! current_user_can( 'aioseo_manage_seo' ) ) {
 
 
 
 
75
  return;
76
  }
77
 
78
  // Styles.
79
  aioseo()->helpers->enqueueStyle(
80
  'aioseo-admin-bar',
81
- 'css/aioseo-admin-bar.css'
 
82
  );
83
  }
84
 
6
  exit;
7
  }
8
 
9
+ use AIOSEO\Plugin\Common\Models;
10
+
11
  /**
12
  * Abstract class that Pro and Lite both extend.
13
  *
36
  */
37
  public function enqueueAssets() {
38
  // Scripts.
39
+ $standalone = [
40
+ 'app',
41
+ 'notifications'
42
+ ];
43
+
44
+ foreach ( $standalone as $key ) {
45
+ aioseo()->helpers->enqueueScript(
46
+ 'aioseo-' . $key,
47
+ 'js/' . $key . '.js'
48
+ );
49
+ }
50
+
51
  aioseo()->helpers->enqueueScript(
52
  'aioseo-vendors',
53
  'js/chunk-vendors.js'
57
  'js/chunk-common.js'
58
  );
59
 
60
+ wp_localize_script(
61
+ 'aioseo-app',
62
+ 'aioseoTranslations',
63
+ [
64
+ 'translations' => aioseo()->helpers->getJedLocaleData( 'all-in-one-seo-pack' )
65
+ ]
66
+ );
67
+
68
+ wp_localize_script(
69
+ 'aioseo-notifications',
70
+ 'aioseoNotifications',
71
+ [
72
+ 'newNotifications' => count( Models\Notification::getNewNotifications() )
73
+ ]
74
+ );
75
+
76
  // Styles.
77
  $rtl = is_rtl() ? '.rtl' : '';
78
  aioseo()->helpers->enqueueStyle(
83
  'aioseo-vendors',
84
  "css/chunk-vendors$rtl.css"
85
  );
86
+
87
+ foreach ( $standalone as $key ) {
88
+ aioseo()->helpers->enqueueStyle(
89
+ "aioseo-$key-style",
90
+ "css/$key$rtl.css"
91
+ );
92
+ }
93
  }
94
 
95
  /**
100
  * @return void
101
  */
102
  public function enqueueFrontEndAssets() {
103
+ $canManageSeo = apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' );
104
+ if (
105
+ ! is_user_logged_in() ||
106
+ ! ( current_user_can( $canManageSeo ) || aioseo()->access->canManage() )
107
+ ) {
108
  return;
109
  }
110
 
111
  // Styles.
112
  aioseo()->helpers->enqueueStyle(
113
  'aioseo-admin-bar',
114
+ 'css/aioseo-admin-bar.css',
115
+ false
116
  );
117
  }
118
 
app/Common/Main/Media.php CHANGED
@@ -34,12 +34,12 @@ class Media {
34
  }
35
 
36
  if (
37
- ! aioseo()->options->searchAppearance->dynamic->postTypes->has( 'attachment' )
38
  ) {
39
  return;
40
  }
41
 
42
- $redirect = aioseo()->options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls;
43
  if ( 'disabled' === $redirect ) {
44
  return;
45
  }
34
  }
35
 
36
  if (
37
+ ! aioseo()->dynamicOptions->searchAppearance->postTypes->has( 'attachment' )
38
  ) {
39
  return;
40
  }
41
 
42
+ $redirect = aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls;
43
  if ( 'disabled' === $redirect ) {
44
  return;
45
  }
app/Common/Main/Updates.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  namespace AIOSEO\Plugin\Common\Main;
3
 
 
 
4
  // Exit if accessed directly.
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
@@ -64,6 +66,9 @@ class Updates {
64
  * @return void
65
  */
66
  public function runUpdates() {
 
 
 
67
  $lastActiveVersion = aioseo()->internalOptions->internal->lastActiveVersion;
68
  if ( version_compare( $lastActiveVersion, '4.0.5', '<' ) ) {
69
  $this->addImageScanDateColumn();
@@ -90,9 +95,40 @@ class Updates {
90
  $this->clearProductImages();
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  do_action( 'aioseo_run_updates', $lastActiveVersion );
94
  }
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  /**
97
  * Updates the latest version after all migrations and updates have run.
98
  *
@@ -101,7 +137,9 @@ class Updates {
101
  * @return void
102
  */
103
  public function updateLatestVersion() {
104
- aioseo()->internalOptions->internal->lastActiveVersion = aioseo()->version;
 
 
105
  }
106
 
107
  /**
@@ -357,4 +395,194 @@ class Updates {
357
  )
358
  ->run();
359
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  }
1
  <?php
2
  namespace AIOSEO\Plugin\Common\Main;
3
 
4
+ use \AIOSEO\Plugin\Common\Models;
5
+
6
  // Exit if accessed directly.
7
  if ( ! defined( 'ABSPATH' ) ) {
8
  exit;
66
  * @return void
67
  */
68
  public function runUpdates() {
69
+ // The dynamic options have not yet fully loaded, so let's refresh here to force that to happen.
70
+ aioseo()->dynamicOptions->refresh();
71
+
72
  $lastActiveVersion = aioseo()->internalOptions->internal->lastActiveVersion;
73
  if ( version_compare( $lastActiveVersion, '4.0.5', '<' ) ) {
74
  $this->addImageScanDateColumn();
95
  $this->clearProductImages();
96
  }
97
 
98
+ if ( version_compare( $lastActiveVersion, '4.1.3', '<' ) ) {
99
+ $this->addNotificationsNewColumn();
100
+ $this->noindexWooCommercePages();
101
+ $this->accessControlNewCapabilities();
102
+ }
103
+
104
+ if ( version_compare( $lastActiveVersion, '4.1.3.3', '<' ) ) {
105
+ $this->accessControlNewCapabilities();
106
+ }
107
+
108
+ if ( version_compare( $lastActiveVersion, '4.1.4', '<' ) ) {
109
+ $this->migrateDynamicSettings();
110
+ }
111
+
112
  do_action( 'aioseo_run_updates', $lastActiveVersion );
113
  }
114
 
115
+ /**
116
+ * Retrieve the raw options from the database for migration.
117
+ *
118
+ * @since 4.1.4
119
+ *
120
+ * @return array An array of options.
121
+ */
122
+ private function getRawOptions() {
123
+ // Options from the DB.
124
+ $commonOptions = json_decode( get_option( aioseo()->options->optionsName ), true );
125
+ if ( empty( $commonOptions ) ) {
126
+ $commonOptions = [];
127
+ }
128
+
129
+ return $commonOptions;
130
+ }
131
+
132
  /**
133
  * Updates the latest version after all migrations and updates have run.
134
  *
137
  * @return void
138
  */
139
  public function updateLatestVersion() {
140
+ if ( aioseo()->version !== aioseo()->internalOptions->internal->lastActiveVersion ) {
141
+ aioseo()->internalOptions->internal->lastActiveVersion = aioseo()->version;
142
+ }
143
  }
144
 
145
  /**
395
  )
396
  ->run();
397
  }
398
+
399
+ /**
400
+ * Adds the new flag to the notifications table.
401
+ *
402
+ * @since 4.1.3
403
+ *
404
+ * @return void
405
+ */
406
+ public function addNotificationsNewColumn() {
407
+ if ( ! aioseo()->db->columnExists( 'aioseo_notifications', 'new' ) ) {
408
+ $tableName = aioseo()->db->db->prefix . 'aioseo_notifications';
409
+ aioseo()->db->execute(
410
+ "ALTER TABLE {$tableName}
411
+ ADD new tinyint(1) NOT NULL DEFAULT 1 AFTER dismissed"
412
+ );
413
+
414
+ aioseo()->db
415
+ ->update( 'aioseo_notifications' )
416
+ ->where( 'new', 1 )
417
+ ->set( 'new', 0 )
418
+ ->run();
419
+ }
420
+ }
421
+
422
+ /**
423
+ * Noindexes the WooCommerce cart, checkout and account pages.
424
+ *
425
+ * @since 4.1.3
426
+ *
427
+ * @return void
428
+ */
429
+ public function noindexWooCommercePages() {
430
+ if ( ! aioseo()->helpers->isWooCommerceActive() ) {
431
+ return;
432
+ }
433
+
434
+ $cartId = (int) get_option( 'woocommerce_cart_page_id' );
435
+ $checkoutId = (int) get_option( 'woocommerce_checkout_page_id' );
436
+ $accountId = (int) get_option( 'woocommerce_myaccount_page_id' );
437
+
438
+ $cartPage = Models\Post::getPost( $cartId );
439
+ $checkoutPage = Models\Post::getPost( $checkoutId );
440
+ $accountPage = Models\Post::getPost( $accountId );
441
+
442
+ $newMeta = [
443
+ 'robots_default' => false,
444
+ 'robots_noindex' => true
445
+ ];
446
+
447
+ if ( $cartPage->exists() ) {
448
+ $cartPage->set( $newMeta );
449
+ $cartPage->save();
450
+ }
451
+ if ( $checkoutPage->exists() ) {
452
+ $checkoutPage->set( $newMeta );
453
+ $checkoutPage->save();
454
+ }
455
+ if ( $accountPage->exists() ) {
456
+ $accountPage->set( $newMeta );
457
+ $accountPage->save();
458
+ }
459
+ }
460
+
461
+ /**
462
+ * Adds the new capabilities for all the roles.
463
+ *
464
+ * @since 4.1.3
465
+ *
466
+ * @return void
467
+ */
468
+ public function accessControlNewCapabilities() {
469
+ aioseo()->access->addCapabilities();
470
+ }
471
+
472
+ /**
473
+ * Migrate dynamic settings to a separate options structure.
474
+ *
475
+ * @since 4.1.4
476
+ *
477
+ * @return void
478
+ */
479
+ public function migrateDynamicSettings() {
480
+ $rawOptions = $this->getRawOptions();
481
+ $options = aioseo()->dynamicOptions->noConflict();
482
+
483
+ // Sitemap post type priorities/frequencies.
484
+ if (
485
+ ! empty( $rawOptions['sitemap']['dynamic']['priority']['postTypes'] )
486
+ ) {
487
+ foreach ( $rawOptions['sitemap']['dynamic']['priority']['postTypes'] as $postTypeName => $data ) {
488
+ if ( $options->sitemap->priority->postTypes->has( $postTypeName ) ) {
489
+ $options->sitemap->priority->postTypes->$postTypeName->priority = $data['priority'];
490
+ $options->sitemap->priority->postTypes->$postTypeName->frequency = $data['frequency'];
491
+ }
492
+ }
493
+ }
494
+
495
+ // Sitemap taxonomy priorities/frequencies.
496
+ if (
497
+ ! empty( $rawOptions['sitemap']['dynamic']['priority']['taxonomies'] )
498
+ ) {
499
+ foreach ( $rawOptions['sitemap']['dynamic']['priority']['taxonomies'] as $taxonomyName => $data ) {
500
+ if ( $options->sitemap->priority->taxonomies->has( $taxonomyName ) ) {
501
+ $options->sitemap->priority->taxonomies->$taxonomyName->priority = $data['priority'];
502
+ $options->sitemap->priority->taxonomies->$taxonomyName->frequency = $data['frequency'];
503
+ }
504
+ }
505
+ }
506
+
507
+ // Facebook post type object types.
508
+ if (
509
+ ! empty( $rawOptions['social']['facebook']['general']['dynamic']['postTypes'] )
510
+ ) {
511
+ foreach ( $rawOptions['social']['facebook']['general']['dynamic']['postTypes'] as $postTypeName => $data ) {
512
+ if ( $options->social->facebook->general->postTypes->has( $postTypeName ) ) {
513
+ $options->social->facebook->general->postTypes->$postTypeName->objectType = $data['objectType'];
514
+ }
515
+ }
516
+ }
517
+
518
+ // Search appearance post type data.
519
+ if (
520
+ ! empty( $rawOptions['searchAppearance']['dynamic']['postTypes'] )
521
+ ) {
522
+ foreach ( $rawOptions['searchAppearance']['dynamic']['postTypes'] as $postTypeName => $data ) {
523
+ if ( $options->searchAppearance->postTypes->has( $postTypeName ) ) {
524
+ $options->searchAppearance->postTypes->$postTypeName->show = $data['show'];
525
+ $options->searchAppearance->postTypes->$postTypeName->title = $data['title'];
526
+ $options->searchAppearance->postTypes->$postTypeName->metaDescription = $data['metaDescription'];
527
+ $options->searchAppearance->postTypes->$postTypeName->schemaType = $data['schemaType'];
528
+ $options->searchAppearance->postTypes->$postTypeName->webPageType = $data['webPageType'];
529
+ $options->searchAppearance->postTypes->$postTypeName->articleType = $data['articleType'];
530
+ $options->searchAppearance->postTypes->$postTypeName->customFields = $data['customFields'];
531
+
532
+ // Advanced settings.
533
+ $advanced = ! empty( $data['advanced']['robotsMeta'] ) ? $data['advanced']['robotsMeta'] : null;
534
+ if ( ! empty( $advanced ) ) {
535
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->default = $data['advanced']['robotsMeta']['default'];
536
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->noindex = $data['advanced']['robotsMeta']['noindex'];
537
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->nofollow = $data['advanced']['robotsMeta']['nofollow'];
538
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->noarchive = $data['advanced']['robotsMeta']['noarchive'];
539
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->noimageindex = $data['advanced']['robotsMeta']['noimageindex'];
540
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->notranslate = $data['advanced']['robotsMeta']['notranslate'];
541
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->nosnippet = $data['advanced']['robotsMeta']['nosnippet'];
542
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->noodp = $data['advanced']['robotsMeta']['noodp'];
543
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->maxSnippet = $data['advanced']['robotsMeta']['maxSnippet'];
544
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->maxVideoPreview = $data['advanced']['robotsMeta']['maxVideoPreview'];
545
+ $options->searchAppearance->postTypes->$postTypeName->advanced->robotsMeta->maxImagePreview = $data['advanced']['robotsMeta']['maxImagePreview'];
546
+ $options->searchAppearance->postTypes->$postTypeName->advanced->showDateInGooglePreview = $data['advanced']['showDateInGooglePreview'];
547
+ $options->searchAppearance->postTypes->$postTypeName->advanced->showPostThumbnailInSearch = $data['advanced']['showPostThumbnailInSearch'];
548
+ $options->searchAppearance->postTypes->$postTypeName->advanced->showMetaBox = $data['advanced']['showMetaBox'];
549
+ $options->searchAppearance->postTypes->$postTypeName->advanced->bulkEditing = $data['advanced']['bulkEditing'];
550
+ }
551
+ }
552
+ }
553
+ }
554
+
555
+ // Search appearance taxonomy data.
556
+ if (
557
+ ! empty( $rawOptions['searchAppearance']['dynamic']['taxonomy'] )
558
+ ) {
559
+ foreach ( $rawOptions['searchAppearance']['dynamic']['taxonomy'] as $taxonomyName => $data ) {
560
+ if ( $options->searchAppearance->taxonomy->has( $taxonomyName ) ) {
561
+ $options->searchAppearance->taxonomy->$taxonomyName->show = $data['show'];
562
+ $options->searchAppearance->taxonomy->$taxonomyName->title = $data['title'];
563
+ $options->searchAppearance->taxonomy->$taxonomyName->metaDescription = $data['metaDescription'];
564
+
565
+ // Advanced settings.
566
+ $advanced = ! empty( $data['advanced']['robotsMeta'] ) ? $data['advanced']['robotsMeta'] : null;
567
+ if ( ! empty( $advanced ) ) {
568
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->default = $data['advanced']['robotsMeta']['default'];
569
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->noindex = $data['advanced']['robotsMeta']['noindex'];
570
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->nofollow = $data['advanced']['robotsMeta']['nofollow'];
571
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->noarchive = $data['advanced']['robotsMeta']['noarchive'];
572
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->noimageindex = $data['advanced']['robotsMeta']['noimageindex'];
573
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->notranslate = $data['advanced']['robotsMeta']['notranslate'];
574
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->nosnippet = $data['advanced']['robotsMeta']['nosnippet'];
575
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->noodp = $data['advanced']['robotsMeta']['noodp'];
576
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->maxSnippet = $data['advanced']['robotsMeta']['maxSnippet'];
577
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->maxVideoPreview = $data['advanced']['robotsMeta']['maxVideoPreview'];
578
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->robotsMeta->maxImagePreview = $data['advanced']['robotsMeta']['maxImagePreview'];
579
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->showDateInGooglePreview = $data['advanced']['showDateInGooglePreview'];
580
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->showPostThumbnailInSearch = $data['advanced']['showPostThumbnailInSearch'];
581
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->showMetaBox = $data['advanced']['showMetaBox'];
582
+ $options->searchAppearance->taxonomy->$taxonomyName->advanced->bulkEditing = $data['advanced']['bulkEditing'];
583
+ }
584
+ }
585
+ }
586
+ }
587
+ }
588
  }
app/Common/Meta/Description.php CHANGED
@@ -89,10 +89,10 @@ class Description {
89
  }
90
 
91
  if ( is_archive() ) {
92
- $postType = get_queried_object();
93
- $options = aioseo()->options->noConflict();
94
- if ( $options->searchAppearance->dynamic->archives->has( $postType->name ) ) {
95
- return $this->helpers->prepare( aioseo()->options->searchAppearance->dynamic->archives->{ $postType->name }->metaDescription );
96
  }
97
  }
98
  }
@@ -177,8 +177,8 @@ class Description {
177
  return $postTypeDescription[ $postType ];
178
  }
179
 
180
- if ( aioseo()->options->searchAppearance->dynamic->postTypes->has( $postType ) ) {
181
- $description = aioseo()->options->searchAppearance->dynamic->postTypes->{$postType}->metaDescription;
182
  }
183
 
184
  $postTypeDescription[ $postType ] = empty( $description ) ? '' : $description;
@@ -210,9 +210,9 @@ class Description {
210
  return $description;
211
  }
212
 
213
- $options = aioseo()->options->noConflict();
214
- if ( ! $description && $options->searchAppearance->dynamic->taxonomies->has( $term->taxonomy ) ) {
215
- $description = $this->helpers->prepare( aioseo()->options->searchAppearance->dynamic->taxonomies->{$term->taxonomy}->metaDescription, false, $default );
216
  }
217
 
218
  $terms[ $term->term_id ] = $description ? $description : $this->helpers->prepare( term_description( $term->term_id ), false, $default );
89
  }
90
 
91
  if ( is_archive() ) {
92
+ $postType = get_queried_object();
93
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
94
+ if ( $dynamicOptions->searchAppearance->archives->has( $postType->name ) ) {
95
+ return $this->helpers->prepare( aioseo()->dynamicOptions->searchAppearance->archives->{ $postType->name }->metaDescription );
96
  }
97
  }
98
  }
177
  return $postTypeDescription[ $postType ];
178
  }
179
 
180
+ if ( aioseo()->dynamicOptions->searchAppearance->postTypes->has( $postType ) ) {
181
+ $description = aioseo()->dynamicOptions->searchAppearance->postTypes->{$postType}->metaDescription;
182
  }
183
 
184
  $postTypeDescription[ $postType ] = empty( $description ) ? '' : $description;
210
  return $description;
211
  }
212
 
213
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
214
+ if ( ! $description && $dynamicOptions->searchAppearance->taxonomies->has( $term->taxonomy ) ) {
215
+ $description = $this->helpers->prepare( aioseo()->dynamicOptions->searchAppearance->taxonomies->{$term->taxonomy}->metaDescription, false, $default );
216
  }
217
 
218
  $terms[ $term->term_id ] = $description ? $description : $this->helpers->prepare( term_description( $term->term_id ), false, $default );
app/Common/Meta/Helpers.php CHANGED
@@ -61,7 +61,7 @@ class Helpers {
61
  }
62
 
63
  $value = aioseo()->helpers->decodeHtmlEntities( $value );
64
- $value = aioseo()->helpers->encodeExceptions( $value );
65
  $value = wp_strip_all_tags( strip_shortcodes( $value ) );
66
  // Because we encoded the exceptions, we need to decode them again first to prevent double encoding later down the line.
67
  $value = aioseo()->helpers->decodeHtmlEntities( $value );
@@ -91,4 +91,21 @@ class Helpers {
91
 
92
  return $this->sanitize( $value, $objectId, $replaceTags );
93
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
61
  }
62
 
63
  $value = aioseo()->helpers->decodeHtmlEntities( $value );
64
+ $value = $this->encodeExceptions( $value );
65
  $value = wp_strip_all_tags( strip_shortcodes( $value ) );
66
  // Because we encoded the exceptions, we need to decode them again first to prevent double encoding later down the line.
67
  $value = aioseo()->helpers->decodeHtmlEntities( $value );
91
 
92
  return $this->sanitize( $value, $objectId, $replaceTags );
93
  }
94
+
95
+ /**
96
+ * Encodes a number of exceptions before we strip tags.
97
+ * We need this function to allow certain character (combinations) in the title/description.
98
+ *
99
+ * @since 4.1.1
100
+ *
101
+ * @param string $string The string.
102
+ * @return string $string The string with exceptions encoded.
103
+ */
104
+ public function encodeExceptions( $string ) {
105
+ $exceptions = [ '<3' ];
106
+ foreach ( $exceptions as $exception ) {
107
+ $string = preg_replace( "/$exception/", aioseo()->helpers->encodeOutputHtml( $exception ), $string );
108
+ }
109
+ return $string;
110
+ }
111
  }
app/Common/Meta/Keywords.php CHANGED
@@ -52,10 +52,10 @@ class Keywords {
52
  return $this->prepareKeywords( $keywords );
53
  }
54
 
55
- $postType = get_queried_object();
56
- $options = aioseo()->options->noConflict();
57
- if ( $postType && $options->searchAppearance->dynamic->archives->has( $postType->name ) ) {
58
- $keywords = $this->extractMetaKeywords( aioseo()->options->searchAppearance->dynamic->archives->{ $postType->name }->advanced->keywords );
59
  return $this->prepareKeywords( $keywords );
60
  }
61
 
@@ -136,11 +136,11 @@ class Keywords {
136
 
137
  if ( $post ) {
138
  if ( aioseo()->options->searchAppearance->advanced->useTagsForMetaKeywords ) {
139
- $keywords = array_merge( $keywords, aioseo()->social->helpers->getAllTags( $post->ID ) );
140
  }
141
 
142
  if ( aioseo()->options->searchAppearance->advanced->useCategoriesForMetaKeywords && ! is_page() ) {
143
- $keywords = array_merge( $keywords, aioseo()->social->helpers->getAllCategories( $post->ID ) );
144
  }
145
  }
146
 
52
  return $this->prepareKeywords( $keywords );
53
  }
54
 
55
+ $postType = get_queried_object();
56
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
57
+ if ( $postType && $dynamicOptions->searchAppearance->archives->has( $postType->name ) ) {
58
+ $keywords = $this->extractMetaKeywords( aioseo()->dynamicOptions->searchAppearance->archives->{ $postType->name }->advanced->keywords );
59
  return $this->prepareKeywords( $keywords );
60
  }
61
 
136
 
137
  if ( $post ) {
138
  if ( aioseo()->options->searchAppearance->advanced->useTagsForMetaKeywords ) {
139
+ $keywords = array_merge( $keywords, aioseo()->helpers->getAllTags( $post->ID ) );
140
  }
141
 
142
  if ( aioseo()->options->searchAppearance->advanced->useCategoriesForMetaKeywords && ! is_page() ) {
143
+ $keywords = array_merge( $keywords, aioseo()->helpers->getAllCategories( $post->ID ) );
144
  }
145
  }
146
 
app/Common/Meta/Robots.php CHANGED
@@ -40,10 +40,24 @@ class Robots {
40
  * @since 4.0.16
41
  */
42
  public function __construct() {
 
43
  add_action( 'template_redirect', [ $this, 'noindexFeed' ] );
44
  add_action( 'wp_head', [ $this, 'disableWpRobotsCore' ], -1 );
45
  }
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  /**
48
  * Prevents WP Core from outputting its own robots meta tag.
49
  *
@@ -85,10 +99,6 @@ class Robots {
85
  return $this->term();
86
  }
87
 
88
- if ( ! get_option( 'blog_public' ) || $this->isNoindexedWooCommercePage() ) {
89
- return false;
90
- }
91
-
92
  if ( is_home() && 'posts' === get_option( 'show_on_front' ) ) {
93
  $this->globalValues();
94
  return $this->metaHelper();
@@ -157,6 +167,12 @@ class Robots {
157
  $this->attributes['noindex'] = '';
158
  }
159
 
 
 
 
 
 
 
160
  $this->attributes = apply_filters( 'aioseo_robots_meta', $this->attributes );
161
  return implode( ', ', array_filter( $this->attributes ) );
162
  }
@@ -169,17 +185,17 @@ class Robots {
169
  * @return void
170
  */
171
  private function post() {
172
- $options = aioseo()->options->noConflict();
173
- $post = aioseo()->helpers->getPost();
174
- $metaData = aioseo()->meta->metaData->getMetaData( $post );
175
 
176
  if ( ! empty( $metaData ) && ! $metaData->robots_default ) {
177
  $this->metaValues( $metaData );
178
  return;
179
  }
180
 
181
- if ( $options->searchAppearance->dynamic->postTypes->has( $post->post_type ) ) {
182
- $this->globalValues( [ 'dynamic', 'postTypes', $post->post_type ] );
183
  }
184
  }
185
 
@@ -191,11 +207,11 @@ class Robots {
191
  * @return string The robots meta tag value.
192
  */
193
  private function term() {
194
- $options = aioseo()->options->noConflict();
195
- $term = get_queried_object();
196
 
197
- if ( $options->searchAppearance->dynamic->taxonomies->has( $term->taxonomy ) ) {
198
- $this->globalValues( [ 'dynamic', 'taxonomies', $term->taxonomy ] );
199
  return$this->metaHelper();
200
  }
201
 
@@ -211,11 +227,11 @@ class Robots {
211
  * @return void
212
  */
213
  private function archives() {
214
- $options = aioseo()->options->noConflict();
215
- $postType = get_queried_object();
216
 
217
- if ( $options->searchAppearance->dynamic->archives->has( $postType->name ) ) {
218
- $this->globalValues( [ 'dynamic', 'archives', $postType->name ] );
219
  }
220
  }
221
 
@@ -224,13 +240,14 @@ class Robots {
224
  *
225
  * @since 4.0.0
226
  *
227
- * @param array $optionOrder The order in which the options need to be called to get the relevant robots meta settings.
 
228
  * @return void
229
  */
230
- protected function globalValues( $optionOrder = [] ) {
231
  $robotsMeta = [];
232
  if ( count( $optionOrder ) ) {
233
- $options = aioseo()->options->noConflict()->searchAppearance;
234
  foreach ( $optionOrder as $option ) {
235
  if ( ! $options->has( $option, false ) ) {
236
  return;
@@ -251,6 +268,8 @@ class Robots {
251
  $robotsMeta = aioseo()->options->searchAppearance->advanced->globalRobotsMeta->all();
252
  }
253
 
 
 
254
  if ( $robotsMeta['default'] ) {
255
  return;
256
  }
@@ -268,10 +287,6 @@ class Robots {
268
  if ( $noSnippet ) {
269
  $this->attributes['nosnippet'] = 'nosnippet';
270
  }
271
- $noImageIndex = $robotsMeta['noimageindex'];
272
- if ( $noImageIndex ) {
273
- $this->attributes['noimageindex'] = 'noimageindex';
274
- }
275
  if ( $robotsMeta['noodp'] ) {
276
  $this->attributes['noodp'] = 'noodp';
277
  }
@@ -283,6 +298,7 @@ class Robots {
283
  $this->attributes['max-snippet'] = "max-snippet:$maxSnippet";
284
  }
285
  $maxImagePreview = $robotsMeta['maxImagePreview'];
 
286
  if ( ! $noImageIndex && $maxImagePreview && in_array( $maxImagePreview, [ 'none', 'standard', 'large' ], true ) ) {
287
  $this->attributes['max-image-preview'] = "max-image-preview:$maxImagePreview";
288
  }
@@ -290,6 +306,12 @@ class Robots {
290
  if ( $maxVideoPreview && intval( $maxVideoPreview ) ) {
291
  $this->attributes['max-video-preview'] = "max-video-preview:$maxVideoPreview";
292
  }
 
 
 
 
 
 
293
  }
294
 
295
  /**
@@ -313,9 +335,6 @@ class Robots {
313
  if ( $metaData->robots_nosnippet ) {
314
  $this->attributes['nosnippet'] = 'nosnippet';
315
  }
316
- if ( $metaData->robots_noimageindex ) {
317
- $this->attributes['noimageindex'] = 'noimageindex';
318
- }
319
  if ( $metaData->robots_noodp ) {
320
  $this->attributes['noodp'] = 'noodp';
321
  }
@@ -331,6 +350,12 @@ class Robots {
331
  if ( $metaData->robots_max_videopreview && intval( $metaData->robots_max_videopreview ) ) {
332
  $this->attributes['max-video-preview'] = "max-video-preview:$metaData->robots_max_videopreview";
333
  }
 
 
 
 
 
 
334
  }
335
 
336
  /**
@@ -344,27 +369,4 @@ class Robots {
344
  $post = aioseo()->helpers->getPost();
345
  return is_object( $post ) && $post->post_password;
346
  }
347
-
348
- /**
349
- * Checks whether the current page is a noindexed WooCommerce page.
350
- *
351
- * WooCommerce noindexes the Cart, Checkout and My Account pages by default. In this case, we don't need to output another robots meta tag.
352
- *
353
- * @since 4.0.0
354
- *
355
- * @return boolean Whether the current page is an noindexed WooCommerce page.
356
- */
357
- private function isNoindexedWooCommercePage() {
358
- $post = aioseo()->helpers->getPost();
359
- if (
360
- ! aioseo()->helpers->isWooCommerceActive() ||
361
- ! is_object( $post ) ||
362
- 'page' !== $post->post_type ||
363
- ! has_action( 'wp_head', 'wc_page_noindex' )
364
- ) {
365
- return false;
366
- }
367
-
368
- return in_array( get_permalink(), aioseo()->helpers->getNoindexedWooCommercePages(), true );
369
- }
370
  }
40
  * @since 4.0.16
41
  */
42
  public function __construct() {
43
+ add_action( 'wp_loaded', [ $this, 'unregisterWooCommerceNoindex' ] );
44
  add_action( 'template_redirect', [ $this, 'noindexFeed' ] );
45
  add_action( 'wp_head', [ $this, 'disableWpRobotsCore' ], -1 );
46
  }
47
 
48
+ /**
49
+ * Prevents WooCommerce from noindexing the Cart/Checkout pages.
50
+ *
51
+ * @since 4.1.3
52
+ *
53
+ * @return void
54
+ */
55
+ public function unregisterWooCommerceNoindex() {
56
+ if ( has_action( 'wp_head', 'wc_page_noindex' ) ) {
57
+ remove_action( 'wp_head', 'wc_page_noindex' );
58
+ }
59
+ }
60
+
61
  /**
62
  * Prevents WP Core from outputting its own robots meta tag.
63
  *
99
  return $this->term();
100
  }
101
 
 
 
 
 
102
  if ( is_home() && 'posts' === get_option( 'show_on_front' ) ) {
103
  $this->globalValues();
104
  return $this->metaHelper();
167
  $this->attributes['noindex'] = '';
168
  }
169
 
170
+ // Because we prevent WordPress Core from outputting a robots tag in disableWpRobotsCore(), we need to noindex/nofollow non-public sites ourselves.
171
+ if ( ! get_option( 'blog_public' ) ) {
172
+ $this->attributes['noindex'] = 'noindex';
173
+ $this->attributes['nofollow'] = 'nofollow';
174
+ }
175
+
176
  $this->attributes = apply_filters( 'aioseo_robots_meta', $this->attributes );
177
  return implode( ', ', array_filter( $this->attributes ) );
178
  }
185
  * @return void
186
  */
187
  private function post() {
188
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
189
+ $post = aioseo()->helpers->getPost();
190
+ $metaData = aioseo()->meta->metaData->getMetaData( $post );
191
 
192
  if ( ! empty( $metaData ) && ! $metaData->robots_default ) {
193
  $this->metaValues( $metaData );
194
  return;
195
  }
196
 
197
+ if ( $dynamicOptions->searchAppearance->postTypes->has( $post->post_type ) ) {
198
+ $this->globalValues( [ 'postTypes', $post->post_type ], true );
199
  }
200
  }
201
 
207
  * @return string The robots meta tag value.
208
  */
209
  private function term() {
210
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
211
+ $term = get_queried_object();
212
 
213
+ if ( $dynamicOptions->searchAppearance->taxonomies->has( $term->taxonomy ) ) {
214
+ $this->globalValues( [ 'taxonomies', $term->taxonomy ], true );
215
  return$this->metaHelper();
216
  }
217
 
227
  * @return void
228
  */
229
  private function archives() {
230
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
231
+ $postType = get_queried_object();
232
 
233
+ if ( $dynamicOptions->searchAppearance->archives->has( $postType->name ) ) {
234
+ $this->globalValues( [ 'archives', $postType->name ], true );
235
  }
236
  }
237
 
240
  *
241
  * @since 4.0.0
242
  *
243
+ * @param array $optionOrder The order in which the options need to be called to get the relevant robots meta settings.
244
+ * @param boolean $isDynamicOption Whether this is for a dynamic option.
245
  * @return void
246
  */
247
+ protected function globalValues( $optionOrder = [], $isDynamicOption = false ) {
248
  $robotsMeta = [];
249
  if ( count( $optionOrder ) ) {
250
+ $options = $isDynamicOption ? aioseo()->dynamicOptions->noConflict()->searchAppearance : aioseo()->options->noConflict()->searchAppearance;
251
  foreach ( $optionOrder as $option ) {
252
  if ( ! $options->has( $option, false ) ) {
253
  return;
268
  $robotsMeta = aioseo()->options->searchAppearance->advanced->globalRobotsMeta->all();
269
  }
270
 
271
+ $this->attributes['max-image-preview'] = 'max-image-preview:large';
272
+
273
  if ( $robotsMeta['default'] ) {
274
  return;
275
  }
287
  if ( $noSnippet ) {
288
  $this->attributes['nosnippet'] = 'nosnippet';
289
  }
 
 
 
 
290
  if ( $robotsMeta['noodp'] ) {
291
  $this->attributes['noodp'] = 'noodp';
292
  }
298
  $this->attributes['max-snippet'] = "max-snippet:$maxSnippet";
299
  }
300
  $maxImagePreview = $robotsMeta['maxImagePreview'];
301
+ $noImageIndex = $robotsMeta['noimageindex'];
302
  if ( ! $noImageIndex && $maxImagePreview && in_array( $maxImagePreview, [ 'none', 'standard', 'large' ], true ) ) {
303
  $this->attributes['max-image-preview'] = "max-image-preview:$maxImagePreview";
304
  }
306
  if ( $maxVideoPreview && intval( $maxVideoPreview ) ) {
307
  $this->attributes['max-video-preview'] = "max-video-preview:$maxVideoPreview";
308
  }
309
+
310
+ // Check this last so that we can prevent max-image-preview from being output if noimageindex is enabled.
311
+ if ( $noImageIndex ) {
312
+ $this->attributes['max-image-preview'] = '';
313
+ $this->attributes['noimageindex'] = 'noimageindex';
314
+ }
315
  }
316
 
317
  /**
335
  if ( $metaData->robots_nosnippet ) {
336
  $this->attributes['nosnippet'] = 'nosnippet';
337
  }
 
 
 
338
  if ( $metaData->robots_noodp ) {
339
  $this->attributes['noodp'] = 'noodp';
340
  }
350
  if ( $metaData->robots_max_videopreview && intval( $metaData->robots_max_videopreview ) ) {
351
  $this->attributes['max-video-preview'] = "max-video-preview:$metaData->robots_max_videopreview";
352
  }
353
+
354
+ // Check this last so that we can prevent max-image-preview from being output if noimageindex is enabled.
355
+ if ( $metaData->robots_noimageindex ) {
356
+ $this->attributes['max-image-preview'] = '';
357
+ $this->attributes['noimageindex'] = 'noimageindex';
358
+ }
359
  }
360
 
361
  /**
369
  $post = aioseo()->helpers->getPost();
370
  return is_object( $post ) && $post->post_password;
371
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  }
app/Common/Meta/Title.php CHANGED
@@ -88,10 +88,10 @@ class Title {
88
  }
89
 
90
  if ( is_archive() ) {
91
- $postType = get_queried_object();
92
- $options = aioseo()->options->noConflict();
93
- if ( $options->searchAppearance->dynamic->archives->has( $postType->name ) ) {
94
- return $this->helpers->prepare( aioseo()->options->searchAppearance->dynamic->archives->{ $postType->name }->title );
95
  }
96
  }
97
  }
@@ -119,15 +119,15 @@ class Title {
119
  $title = $this->helpers->prepare( $metaData->title, $post->ID );
120
  }
121
 
 
 
 
 
122
  // If this post is the static home page and we have no title, let's reset to the site name.
123
  if ( empty( $title ) && 'page' === get_option( 'show_on_front' ) && (int) get_option( 'page_on_front' ) === $post->ID ) {
124
  $title = aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) );
125
  }
126
 
127
- if ( ! $title ) {
128
- $title = $this->helpers->prepare( $this->getPostTypeTitle( $post->post_type ), $post->ID, $default );
129
- }
130
-
131
  $posts[ $post->ID ] = $title;
132
  return $posts[ $post->ID ];
133
  }
@@ -146,8 +146,8 @@ class Title {
146
  return $postTypeTitle[ $postType ];
147
  }
148
 
149
- if ( aioseo()->options->searchAppearance->dynamic->postTypes->has( $postType ) ) {
150
- $title = aioseo()->options->searchAppearance->dynamic->postTypes->{$postType}->title;
151
  }
152
 
153
  $postTypeTitle[ $postType ] = empty( $title ) ? '' : $title;
@@ -170,10 +170,10 @@ class Title {
170
  return $terms[ $term->term_id ];
171
  }
172
 
173
- $title = '';
174
- $options = aioseo()->options->noConflict();
175
- if ( ! $title && $options->searchAppearance->dynamic->taxonomies->has( $term->taxonomy ) ) {
176
- $newTitle = aioseo()->options->searchAppearance->dynamic->taxonomies->{$term->taxonomy}->title;
177
  $newTitle = preg_replace( '/#taxonomy_title/', aioseo()->helpers->escapeRegexReplacement( $term->name ), $newTitle );
178
  $title = $this->helpers->prepare( $newTitle, false, $default );
179
  }
88
  }
89
 
90
  if ( is_archive() ) {
91
+ $postType = get_queried_object();
92
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
93
+ if ( $dynamicOptions->searchAppearance->archives->has( $postType->name ) ) {
94
+ return $this->helpers->prepare( aioseo()->dynamicOptions->searchAppearance->archives->{ $postType->name }->title );
95
  }
96
  }
97
  }
119
  $title = $this->helpers->prepare( $metaData->title, $post->ID );
120
  }
121
 
122
+ if ( ! $title ) {
123
+ $title = $this->helpers->prepare( $this->getPostTypeTitle( $post->post_type ), $post->ID, $default );
124
+ }
125
+
126
  // If this post is the static home page and we have no title, let's reset to the site name.
127
  if ( empty( $title ) && 'page' === get_option( 'show_on_front' ) && (int) get_option( 'page_on_front' ) === $post->ID ) {
128
  $title = aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) );
129
  }
130
 
 
 
 
 
131
  $posts[ $post->ID ] = $title;
132
  return $posts[ $post->ID ];
133
  }
146
  return $postTypeTitle[ $postType ];
147
  }
148
 
149
+ if ( aioseo()->dynamicOptions->searchAppearance->postTypes->has( $postType ) ) {
150
+ $title = aioseo()->dynamicOptions->searchAppearance->postTypes->{$postType}->title;
151
  }
152
 
153
  $postTypeTitle[ $postType ] = empty( $title ) ? '' : $title;
170
  return $terms[ $term->term_id ];
171
  }
172
 
173
+ $title = '';
174
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
175
+ if ( ! $title && $dynamicOptions->searchAppearance->taxonomies->has( $term->taxonomy ) ) {
176
+ $newTitle = aioseo()->dynamicOptions->searchAppearance->taxonomies->{$term->taxonomy}->title;
177
  $newTitle = preg_replace( '/#taxonomy_title/', aioseo()->helpers->escapeRegexReplacement( $term->name ), $newTitle );
178
  $title = $this->helpers->prepare( $newTitle, false, $default );
179
  }
app/Common/Migration/GeneralSettings.php CHANGED
@@ -104,8 +104,8 @@ class GeneralSettings {
104
  * @return void
105
  */
106
  private function setDefaultArticleType() {
107
- if ( aioseo()->options->searchAppearance->dynamic->postTypes->has( 'post' ) ) {
108
- aioseo()->options->searchAppearance->dynamic->postTypes->post->articleType = 'Article';
109
  }
110
  }
111
 
@@ -385,19 +385,19 @@ class GeneralSettings {
385
  */
386
  private function migrateTitleFormats() {
387
  if ( ! empty( $this->oldOptions['aiosp_archive_title_format'] ) ) {
388
- $archives = array_keys( aioseo()->options->searchAppearance->dynamic->archives->all() );
389
  $format = aioseo()->helpers->sanitizeOption( aioseo()->migration->helpers->macrosToSmartTags( $this->oldOptions['aiosp_archive_title_format'] ) );
390
  foreach ( $archives as $archive ) {
391
- aioseo()->options->searchAppearance->dynamic->archives->$archive->title = $format;
392
  }
393
  }
394
 
395
  $settings = [
396
- 'aiosp_post_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'dynamic', 'postTypes', 'post', 'title' ] ],
397
- 'aiosp_page_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'dynamic', 'postTypes', 'page', 'title' ] ],
398
- 'aiosp_attachment_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'dynamic', 'postTypes', 'attachment', 'title' ] ],
399
- 'aiosp_category_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'dynamic', 'taxonomies', 'category', 'title' ] ],
400
- 'aiosp_tag_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'dynamic', 'taxonomies', 'post_tag', 'title' ] ],
401
  'aiosp_date_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'title' ] ],
402
  'aiosp_author_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'title' ] ],
403
  'aiosp_search_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'search', 'title' ] ],
@@ -415,11 +415,11 @@ class GeneralSettings {
415
 
416
  $objectSlug = aioseo()->helpers->pregReplace( '#_tax#', '', $slug[1] );
417
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicPostTypes( true ), true ) ) {
418
- $settings[ $name ] = [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'dynamic', 'postTypes', $objectSlug, 'title' ] ];
419
  continue;
420
  }
421
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicTaxonomies( true ), true ) ) {
422
- $settings[ $name ] = [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'dynamic', 'taxonomies', $objectSlug, 'title' ] ];
423
  }
424
  }
425
  }
@@ -488,8 +488,8 @@ class GeneralSettings {
488
  continue;
489
  }
490
 
491
- if ( aioseo()->options->searchAppearance->dynamic->postTypes->has( $postType['name'] ) ) {
492
- aioseo()->options->searchAppearance->dynamic->postTypes->{$postType['name']}->metaDescription = '#post_excerpt';
493
  }
494
  }
495
  }
@@ -523,10 +523,10 @@ class GeneralSettings {
523
 
524
  $noindexedPostTypes = is_array( $this->oldOptions['aiosp_cpostnoindex'] ) ? $this->oldOptions['aiosp_cpostnoindex'] : explode( ', ', $this->oldOptions['aiosp_cpostnoindex'] );
525
  foreach ( array_intersect( aioseo()->helpers->getPublicPostTypes( true ), $noindexedPostTypes ) as $postType ) {
526
- if ( aioseo()->options->noConflict()->searchAppearance->dynamic->postTypes->has( $postType ) ) {
527
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->show = false;
528
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default = false;
529
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->noindex = true;
530
  }
531
  }
532
 
@@ -541,10 +541,10 @@ class GeneralSettings {
541
 
542
  if ( ! empty( $noindexedTaxonomies ) ) {
543
  foreach ( array_intersect( aioseo()->helpers->getPublicTaxonomies( true ), $noindexedTaxonomies ) as $taxonomy ) {
544
- if ( aioseo()->options->noConflict()->searchAppearance->dynamic->taxonomies->has( $taxonomy ) ) {
545
- aioseo()->options->searchAppearance->dynamic->taxonomies->$taxonomy->show = false;
546
- aioseo()->options->searchAppearance->dynamic->taxonomies->$taxonomy->advanced->robotsMeta->default = false;
547
- aioseo()->options->searchAppearance->dynamic->taxonomies->$taxonomy->advanced->robotsMeta->noindex = true;
548
  }
549
  }
550
  }
@@ -588,9 +588,9 @@ class GeneralSettings {
588
  private function migrateNofollowSettings() {
589
  if ( ! empty( $this->oldOptions['aiosp_cpostnofollow'] ) ) {
590
  foreach ( array_intersect( aioseo()->helpers->getPublicPostTypes( true ), $this->oldOptions['aiosp_cpostnofollow'] ) as $postType ) {
591
- if ( aioseo()->options->noConflict()->searchAppearance->dynamic->postTypes->has( $postType ) ) {
592
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default = false;
593
- aioseo()->options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->nofollow = true;
594
  }
595
  }
596
  }
@@ -818,9 +818,9 @@ class GeneralSettings {
818
  private function migrateRedirectToParent() {
819
  if ( isset( $this->oldOptions['aiosp_redirect_attachement_parent'] ) ) {
820
  if ( ! empty( $this->oldOptions['aiosp_redirect_attachement_parent'] ) ) {
821
- aioseo()->options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls = 'attachment_parent';
822
  } else {
823
- aioseo()->options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls = 'disabled';
824
  }
825
  }
826
  }
104
  * @return void
105
  */
106
  private function setDefaultArticleType() {
107
+ if ( aioseo()->dynamicOptions->searchAppearance->postTypes->has( 'post' ) ) {
108
+ aioseo()->dynamicOptions->searchAppearance->postTypes->post->articleType = 'Article';
109
  }
110
  }
111
 
385
  */
386
  private function migrateTitleFormats() {
387
  if ( ! empty( $this->oldOptions['aiosp_archive_title_format'] ) ) {
388
+ $archives = array_keys( aioseo()->dynamicOptions->searchAppearance->archives->all() );
389
  $format = aioseo()->helpers->sanitizeOption( aioseo()->migration->helpers->macrosToSmartTags( $this->oldOptions['aiosp_archive_title_format'] ) );
390
  foreach ( $archives as $archive ) {
391
+ aioseo()->dynamicOptions->searchAppearance->archives->$archive->title = $format;
392
  }
393
  }
394
 
395
  $settings = [
396
+ 'aiosp_post_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'postTypes', 'post', 'title' ], 'dynamic' => true ],
397
+ 'aiosp_page_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'postTypes', 'page', 'title' ], 'dynamic' => true ],
398
+ 'aiosp_attachment_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'postTypes', 'attachment', 'title' ], 'dynamic' => true ],
399
+ 'aiosp_category_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'taxonomies', 'category', 'title' ], 'dynamic' => true ],
400
+ 'aiosp_tag_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'taxonomies', 'post_tag', 'title' ], 'dynamic' => true ],
401
  'aiosp_date_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'date', 'title' ] ],
402
  'aiosp_author_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'author', 'title' ] ],
403
  'aiosp_search_title_format' => [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'archives', 'search', 'title' ] ],
415
 
416
  $objectSlug = aioseo()->helpers->pregReplace( '#_tax#', '', $slug[1] );
417
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicPostTypes( true ), true ) ) {
418
+ $settings[ $name ] = [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'postTypes', $objectSlug, 'title' ], 'dynamic' => true ];
419
  continue;
420
  }
421
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicTaxonomies( true ), true ) ) {
422
+ $settings[ $name ] = [ 'type' => 'string', 'newOption' => [ 'searchAppearance', 'taxonomies', $objectSlug, 'title' ], 'dynamic' => true ];
423
  }
424
  }
425
  }
488
  continue;
489
  }
490
 
491
+ if ( aioseo()->dynamicOptions->searchAppearance->postTypes->has( $postType['name'] ) ) {
492
+ aioseo()->dynamicOptions->searchAppearance->postTypes->{$postType['name']}->metaDescription = '#post_excerpt';
493
  }
494
  }
495
  }
523
 
524
  $noindexedPostTypes = is_array( $this->oldOptions['aiosp_cpostnoindex'] ) ? $this->oldOptions['aiosp_cpostnoindex'] : explode( ', ', $this->oldOptions['aiosp_cpostnoindex'] );
525
  foreach ( array_intersect( aioseo()->helpers->getPublicPostTypes( true ), $noindexedPostTypes ) as $postType ) {
526
+ if ( aioseo()->dynamicOptions->noConflict()->searchAppearance->postTypes->has( $postType ) ) {
527
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->show = false;
528
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = false;
529
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->noindex = true;
530
  }
531
  }
532
 
541
 
542
  if ( ! empty( $noindexedTaxonomies ) ) {
543
  foreach ( array_intersect( aioseo()->helpers->getPublicTaxonomies( true ), $noindexedTaxonomies ) as $taxonomy ) {
544
+ if ( aioseo()->dynamicOptions->noConflict()->searchAppearance->taxonomies->has( $taxonomy ) ) {
545
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->show = false;
546
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->default = false;
547
+ aioseo()->dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->noindex = true;
548
  }
549
  }
550
  }
588
  private function migrateNofollowSettings() {
589
  if ( ! empty( $this->oldOptions['aiosp_cpostnofollow'] ) ) {
590
  foreach ( array_intersect( aioseo()->helpers->getPublicPostTypes( true ), $this->oldOptions['aiosp_cpostnofollow'] ) as $postType ) {
591
+ if ( aioseo()->dynamicOptions->noConflict()->searchAppearance->postTypes->has( $postType ) ) {
592
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default = false;
593
+ aioseo()->dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->nofollow = true;
594
  }
595
  }
596
  }
818
  private function migrateRedirectToParent() {
819
  if ( isset( $this->oldOptions['aiosp_redirect_attachement_parent'] ) ) {
820
  if ( ! empty( $this->oldOptions['aiosp_redirect_attachement_parent'] ) ) {
821
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'attachment_parent';
822
  } else {
823
+ aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls = 'disabled';
824
  }
825
  }
826
  }
app/Common/Migration/Helpers.php CHANGED
@@ -34,13 +34,15 @@ class Helpers {
34
  return;
35
  }
36
 
 
 
37
  foreach ( $mappings as $name => $values ) {
38
  if ( ! isset( $group[ $name ] ) ) {
39
  continue;
40
  }
41
 
42
  $error = false;
43
- $options = aioseo()->options->noConflict();
44
  $lastOption = '';
45
  for ( $i = 0; $i < count( $values['newOption'] ); $i++ ) {
46
  $lastOption = $values['newOption'][ $i ];
@@ -81,8 +83,6 @@ class Helpers {
81
  break;
82
  }
83
  }
84
-
85
- aioseo()->options->refresh();
86
  }
87
 
88
  /**
34
  return;
35
  }
36
 
37
+ $mainOptions = aioseo()->options->noConflict();
38
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
39
  foreach ( $mappings as $name => $values ) {
40
  if ( ! isset( $group[ $name ] ) ) {
41
  continue;
42
  }
43
 
44
  $error = false;
45
+ $options = ! empty( $values['dynamic'] ) ? $dynamicOptions : $mainOptions;
46
  $lastOption = '';
47
  for ( $i = 0; $i < count( $values['newOption'] ); $i++ ) {
48
  $lastOption = $values['newOption'][ $i ];
83
  break;
84
  }
85
  }
 
 
86
  }
87
 
88
  /**
app/Common/Migration/Meta.php CHANGED
@@ -67,6 +67,7 @@ class Meta {
67
  ->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
68
  ->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
69
  ->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
 
70
  ->orderBy( 'p.ID DESC' )
71
  ->limit( $postsPerAction )
72
  ->run()
@@ -327,8 +328,23 @@ class Meta {
327
  * @param int $postId The post ID.
328
  * @return void
329
  */
330
- protected function migrateAdditionalPostMeta( $postId ) {
331
- return $postId;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  }
333
 
334
  /**
67
  ->leftJoin( 'aioseo_posts as ap', '`p`.`ID` = `ap`.`post_id`' )
68
  ->whereRaw( "( ap.post_id IS NULL OR ap.updated < '$timeStarted' )" )
69
  ->whereRaw( "( p.post_type IN ( '$publicPostTypes' ) )" )
70
+ ->whereRaw( 'p.post_status NOT IN( \'auto-draft\' )' )
71
  ->orderBy( 'p.ID DESC' )
72
  ->limit( $postsPerAction )
73
  ->run()
328
  * @param int $postId The post ID.
329
  * @return void
330
  */
331
+ public function migrateAdditionalPostMeta( $postId ) {
332
+ static $disabled = null;
333
+
334
+ if ( null === $disabled ) {
335
+ $disabled = (
336
+ ! aioseo()->options->sitemap->general->enable ||
337
+ (
338
+ aioseo()->options->sitemap->general->advancedSettings->enable &&
339
+ aioseo()->options->sitemap->general->advancedSettings->excludeImages
340
+ )
341
+ );
342
+ }
343
+ if ( $disabled ) {
344
+ return;
345
+ }
346
+
347
+ aioseo()->sitemap->image->scanPost( $postId );
348
  }
349
 
350
  /**
app/Common/Migration/Sitemap.php CHANGED
@@ -275,8 +275,8 @@ class Sitemap {
275
  'aiosp_sitemap_freq_homepage' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'homePage', 'frequency' ] ],
276
  'aiosp_sitemap_prio_post' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'postTypes', 'priority' ] ],
277
  'aiosp_sitemap_freq_post' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'postTypes', 'frequency' ] ],
278
- 'aiosp_sitemap_prio_post_post' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'dynamic', 'priority', 'postTypes', 'post', 'priority' ] ],
279
- 'aiosp_sitemap_freq_post_post' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'dynamic', 'priority', 'postTypes', 'post', 'frequency' ] ],
280
  'aiosp_sitemap_prio_taxonomies' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'taxonomies', 'priority' ] ],
281
  'aiosp_sitemap_freq_taxonomies' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'taxonomies', 'frequency' ] ],
282
  'aiosp_sitemap_prio_archive' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'archive', 'priority' ] ],
@@ -308,7 +308,8 @@ class Sitemap {
308
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicPostTypes( true ), true ) ) {
309
  $settings[ $name ] = [
310
  'type' => 'priority' === $type ? 'float' : 'string',
311
- 'newOption' => [ 'sitemap', 'dynamic', 'priority', 'postTypes', $objectSlug, $type ]
 
312
  ];
313
  continue;
314
  }
@@ -316,11 +317,14 @@ class Sitemap {
316
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicTaxonomies( true ), true ) ) {
317
  $settings[ $name ] = [
318
  'type' => 'priority' === $type ? 'float' : 'string',
319
- 'newOption' => [ 'sitemap', 'dynamic', 'priority', 'taxonomies', $objectSlug, $type ]
 
320
  ];
321
  }
322
  }
323
 
 
 
324
  foreach ( $settings as $name => $values ) {
325
  // If setting is set to default, do nothing.
326
  if (
@@ -347,7 +351,7 @@ class Sitemap {
347
  $object->value = $value;
348
 
349
  $error = false;
350
- $options = aioseo()->options->noConflict();
351
  $lastOption = '';
352
  for ( $i = 0; $i < count( $values['newOption'] ); $i++ ) {
353
  $lastOption = $values['newOption'][ $i ];
@@ -365,11 +369,10 @@ class Sitemap {
365
  }
366
 
367
  $options->$lastOption = wp_json_encode( $object );
368
- aioseo()->options->refresh();
369
  }
370
 
371
  if ( count( $settings ) ) {
372
- aioseo()->options->sitemap->general->advancedSettings->enable = true;
373
  }
374
  }
375
 
275
  'aiosp_sitemap_freq_homepage' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'homePage', 'frequency' ] ],
276
  'aiosp_sitemap_prio_post' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'postTypes', 'priority' ] ],
277
  'aiosp_sitemap_freq_post' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'postTypes', 'frequency' ] ],
278
+ 'aiosp_sitemap_prio_post_post' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'priority', 'postTypes', 'post', 'priority' ], 'dynamic' => true ],
279
+ 'aiosp_sitemap_freq_post_post' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'priority', 'postTypes', 'post', 'frequency' ], 'dynamic' => true ],
280
  'aiosp_sitemap_prio_taxonomies' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'taxonomies', 'priority' ] ],
281
  'aiosp_sitemap_freq_taxonomies' => [ 'type' => 'string', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'taxonomies', 'frequency' ] ],
282
  'aiosp_sitemap_prio_archive' => [ 'type' => 'float', 'newOption' => [ 'sitemap', 'general', 'advancedSettings', 'priority', 'archive', 'priority' ] ],
308
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicPostTypes( true ), true ) ) {
309
  $settings[ $name ] = [
310
  'type' => 'priority' === $type ? 'float' : 'string',
311
+ 'newOption' => [ 'sitemap', 'priority', 'postTypes', $objectSlug, $type ],
312
+ 'dynamic' => true
313
  ];
314
  continue;
315
  }
317
  if ( in_array( $objectSlug, aioseo()->helpers->getPublicTaxonomies( true ), true ) ) {
318
  $settings[ $name ] = [
319
  'type' => 'priority' === $type ? 'float' : 'string',
320
+ 'newOption' => [ 'sitemap', 'priority', 'taxonomies', $objectSlug, $type ],
321
+ 'dynamic' => true
322
  ];
323
  }
324
  }
325
 
326
+ $mainOptions = aioseo()->options->noConflict();
327
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
328
  foreach ( $settings as $name => $values ) {
329
  // If setting is set to default, do nothing.
330
  if (
351
  $object->value = $value;
352
 
353
  $error = false;
354
+ $options = ! empty( $values['dynamic'] ) ? $dynamicOptions : $mainOptions;
355
  $lastOption = '';
356
  for ( $i = 0; $i < count( $values['newOption'] ); $i++ ) {
357
  $lastOption = $values['newOption'][ $i ];
369
  }
370
 
371
  $options->$lastOption = wp_json_encode( $object );
 
372
  }
373
 
374
  if ( count( $settings ) ) {
375
+ $mainOptions->sitemap->general->advancedSettings->enable = true;
376
  }
377
  }
378
 
app/Common/Migration/SocialMeta.php CHANGED
@@ -376,9 +376,9 @@ class SocialMeta {
376
  continue;
377
  }
378
 
379
- $options = aioseo()->options->noConflict();
380
- if ( $options->social->facebook->general->dynamic->postTypes->has( $postType ) ) {
381
- aioseo()->options->social->facebook->general->dynamic->postTypes->$postType->objectType =
382
  aioseo()->helpers->sanitizeOption( $this->oldOptions['modules']['aiosp_opengraph_options'][ $settingName ] );
383
  }
384
 
376
  continue;
377
  }
378
 
379
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
380
+ if ( $dynamicOptions->social->facebook->general->postTypes->has( $postType ) ) {
381
+ aioseo()->dynamicOptions->social->facebook->general->postTypes->$postType->objectType =
382
  aioseo()->helpers->sanitizeOption( $this->oldOptions['modules']['aiosp_opengraph_options'][ $settingName ] );
383
  }
384
 
app/Common/Models/Model.php CHANGED
@@ -236,6 +236,9 @@ class Model implements \JsonSerializable {
236
 
237
  foreach ( $this->jsonFields as $field ) {
238
  if ( isset( $data[ $field ] ) && ! aioseo()->helpers->isJsonString( $data[ $field ] ) ) {
 
 
 
239
  $data[ $field ] = wp_json_encode( $data[ $field ] );
240
  }
241
  }
@@ -495,119 +498,4 @@ class Model implements \JsonSerializable {
495
 
496
  return wp_json_encode( $existingOptions );
497
  }
498
-
499
- /**
500
- * Returns a JSON object with default local seo options.
501
- *
502
- * @since 4.0.0
503
- *
504
- * @param string $existingOptions The existing options in JSON.
505
- * @return string The existing options with defaults added in JSON.
506
- */
507
- public static function getDefaultLocalSeoOptions( $existingOptions = '' ) {
508
- $defaults = [
509
- 'locations' => [
510
- 'business' => [
511
- 'name' => '',
512
- 'businessType' => '',
513
- 'image' => '',
514
- 'areaServed' => '',
515
- 'urls' => [
516
- 'website' => '',
517
- 'aboutPage' => '',
518
- 'contactPage' => ''
519
- ],
520
- 'address' => [
521
- 'streetLine1' => '',
522
- 'streetLine2' => '',
523
- 'zipCode' => '',
524
- 'city' => '',
525
- 'state' => '',
526
- 'country' => '',
527
- 'addressFormat' => '#streetLineOne\n#streetLineTwo\n#city, #state #zipCode'
528
- ],
529
- 'contact' => [
530
- 'email' => '',
531
- 'phone' => '',
532
- 'phoneFormatted' => '',
533
- 'fax' => '',
534
- 'faxFormatted' => ''
535
- ],
536
- 'ids' => [
537
- 'vat' => '',
538
- 'tax' => '',
539
- 'chamberOfCommerce' => ''
540
- ],
541
- 'payment' => [
542
- 'priceRange' => '',
543
- 'currenciesAccepted' => '',
544
- 'methods' => ''
545
- ],
546
- ],
547
- ],
548
- 'openingHours' => [
549
- 'useDefaults' => true,
550
- 'show' => true,
551
- 'alwaysOpen' => false,
552
- 'use24hFormat' => false,
553
- 'timezone' => '',
554
- 'labels' => [
555
- 'closed' => '',
556
- 'alwaysOpen' => ''
557
- ],
558
- 'days' => [
559
- 'monday' => [
560
- 'open24h' => false,
561
- 'closed' => false,
562
- 'openTime' => '09:00',
563
- 'closeTime' => '17:00'
564
- ],
565
- 'tuesday' => [
566
- 'open24h' => false,
567
- 'closed' => false,
568
- 'openTime' => '09:00',
569
- 'closeTime' => '17:00'
570
- ],
571
- 'wednesday' => [
572
- 'open24h' => false,
573
- 'closed' => false,
574
- 'openTime' => '09:00',
575
- 'closeTime' => '17:00'
576
- ],
577
- 'thursday' => [
578
- 'open24h' => false,
579
- 'closed' => false,
580
- 'openTime' => '09:00',
581
- 'closeTime' => '17:00'
582
- ],
583
- 'friday' => [
584
- 'open24h' => false,
585
- 'closed' => false,
586
- 'openTime' => '09:00',
587
- 'closeTime' => '17:00'
588
- ],
589
- 'saturday' => [
590
- 'open24h' => false,
591
- 'closed' => false,
592
- 'openTime' => '09:00',
593
- 'closeTime' => '17:00'
594
- ],
595
- 'sunday' => [
596
- 'open24h' => false,
597
- 'closed' => false,
598
- 'openTime' => '09:00',
599
- 'closeTime' => '17:00'
600
- ]
601
- ]
602
- ]
603
- ];
604
-
605
- if ( empty( $existingOptions ) ) {
606
- $defaults = wp_json_encode( $defaults );
607
- return str_replace( '\\\n', '\n', $defaults );
608
- }
609
-
610
- $existingOptions = json_decode( $existingOptions, true );
611
- return array_replace_recursive( $defaults, $existingOptions );
612
- }
613
  }
236
 
237
  foreach ( $this->jsonFields as $field ) {
238
  if ( isset( $data[ $field ] ) && ! aioseo()->helpers->isJsonString( $data[ $field ] ) ) {
239
+ if ( is_array( $data[ $field ] ) && aioseo()->helpers->isArrayNumeric( $data[ $field ] ) ) {
240
+ $data[ $field ] = array_values( $data[ $field ] );
241
+ }
242
  $data[ $field ] = wp_json_encode( $data[ $field ] );
243
  }
244
  }
498
 
499
  return wp_json_encode( $existingOptions );
500
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
  }
app/Common/Models/Notification.php CHANGED
@@ -91,6 +91,22 @@ class Notification extends Model {
91
  'updated'
92
  ];
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  /**
95
  * Get an array of active notifications.
96
  *
@@ -104,6 +120,51 @@ class Notification extends Model {
104
  return ! empty( $staticNotifications ) ? array_merge( $staticNotifications, $notifications ) : $notifications;
105
  }
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  /**
108
  * Returns all static notifications.
109
  *
@@ -114,12 +175,13 @@ class Notification extends Model {
114
  public static function getStaticNotifications() {
115
  $staticNotifications = [];
116
  $notifications = [
117
- 'notification-review'
 
118
  ];
119
 
120
  foreach ( $notifications as $notification ) {
121
  switch ( $notification ) {
122
- case 'notification-review':
123
  // If they intentionally dismissed the main notification, we don't show the repeat one.
124
  $originalDismissed = get_user_meta( get_current_user_id(), '_aioseo_plugin_review_dismissed', true );
125
  if ( '2' !== $originalDismissed ) {
@@ -141,8 +203,21 @@ class Notification extends Model {
141
  }
142
 
143
  $staticNotifications[] = [
144
- 'slug' => 'notification-review',
145
- 'component' => 'core-notification-review'
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  ];
147
  break;
148
  }
@@ -165,7 +240,7 @@ class Notification extends Model {
165
  ->where( 'dismissed', 0 )
166
  ->whereRaw( "(start <= '" . gmdate( 'Y-m-d H:i:s' ) . "' OR start IS NULL)" )
167
  ->whereRaw( "(end >= '" . gmdate( 'Y-m-d H:i:s' ) . "' OR end IS NULL)" )
168
- ->orderBy( 'start DESC' )
169
  ->run()
170
  ->models( 'AIOSEO\\Plugin\\Common\\Models\\Notification' )
171
  );
91
  'updated'
92
  ];
93
 
94
+ /**
95
+ * Get the list of notifications.
96
+ *
97
+ * @since 4.1.3
98
+ *
99
+ * @param boolean $reset Whether or not to reset the new notifications.
100
+ * @return array An array of notifications.
101
+ */
102
+ public static function getNotifications( $reset = true ) {
103
+ return [
104
+ 'active' => self::getAllActiveNotifications(),
105
+ 'new' => self::getNewNotifications( $reset ),
106
+ 'dismissed' => self::getAllDismissedNotifications()
107
+ ];
108
+ }
109
+
110
  /**
111
  * Get an array of active notifications.
112
  *
120
  return ! empty( $staticNotifications ) ? array_merge( $staticNotifications, $notifications ) : $notifications;
121
  }
122
 
123
+ /**
124
+ * Get all new notifications. After retrieving them, this will reset them.
125
+ * This means that calling this method twice will result in no results
126
+ * the second time. The only exception is to pass false as a reset variable to prevent it.
127
+ *
128
+ * @since 4.1.3
129
+ *
130
+ * @param boolean $reset Whether or not to reset the new notifications.
131
+ * @return array An array of new notifications if any exist.
132
+ */
133
+ public static function getNewNotifications( $reset = true ) {
134
+ $notifications = self::filterNotifications(
135
+ aioseo()->db
136
+ ->start( 'aioseo_notifications' )
137
+ ->where( 'dismissed', 0 )
138
+ ->where( 'new', 1 )
139
+ ->whereRaw( "(start <= '" . gmdate( 'Y-m-d H:i:s' ) . "' OR start IS NULL)" )
140
+ ->whereRaw( "(end >= '" . gmdate( 'Y-m-d H:i:s' ) . "' OR end IS NULL)" )
141
+ ->orderBy( 'start DESC, created DESC' )
142
+ ->run()
143
+ ->models( 'AIOSEO\\Plugin\\Common\\Models\\Notification' )
144
+ );
145
+
146
+ if ( $reset ) {
147
+ self::resetNewNotifications();
148
+ }
149
+
150
+ return $notifications;
151
+ }
152
+
153
+ /**
154
+ * Resets all new notifications.
155
+ *
156
+ * @since 4.1.3
157
+ *
158
+ * @return void
159
+ */
160
+ public static function resetNewNotifications() {
161
+ aioseo()->db
162
+ ->update( 'aioseo_notifications' )
163
+ ->where( 'new', 1 )
164
+ ->set( 'new', 0 )
165
+ ->run();
166
+ }
167
+
168
  /**
169
  * Returns all static notifications.
170
  *
175
  public static function getStaticNotifications() {
176
  $staticNotifications = [];
177
  $notifications = [
178
+ 'unlicensed-addons',
179
+ 'review'
180
  ];
181
 
182
  foreach ( $notifications as $notification ) {
183
  switch ( $notification ) {
184
+ case 'review':
185
  // If they intentionally dismissed the main notification, we don't show the repeat one.
186
  $originalDismissed = get_user_meta( get_current_user_id(), '_aioseo_plugin_review_dismissed', true );
187
  if ( '2' !== $originalDismissed ) {
203
  }
204
 
205
  $staticNotifications[] = [
206
+ 'slug' => 'notification-' . $notification,
207
+ 'component' => 'notifications-' . $notification
208
+ ];
209
+ break;
210
+ case 'unlicensed-addons':
211
+ $unlicensedAddons = aioseo()->addons->unlicensedAddons();
212
+ if ( empty( $unlicensedAddons['addons'] ) ) {
213
+ break;
214
+ }
215
+
216
+ $staticNotifications[] = [
217
+ 'slug' => 'notification-' . $notification,
218
+ 'component' => 'notifications-' . $notification,
219
+ 'addons' => $unlicensedAddons['addons'],
220
+ 'message' => $unlicensedAddons['message']
221
  ];
222
  break;
223
  }
240
  ->where( 'dismissed', 0 )
241
  ->whereRaw( "(start <= '" . gmdate( 'Y-m-d H:i:s' ) . "' OR start IS NULL)" )
242
  ->whereRaw( "(end >= '" . gmdate( 'Y-m-d H:i:s' ) . "' OR end IS NULL)" )
243
+ ->orderBy( 'start DESC, created DESC' )
244
  ->run()
245
  ->models( 'AIOSEO\\Plugin\\Common\\Models\\Notification' )
246
  );
app/Common/Models/Post.php CHANGED
@@ -68,11 +68,46 @@ class Post extends Model {
68
  * @return Post The Post object.
69
  */
70
  public static function getPost( $postId ) {
71
- return aioseo()->db
72
  ->start( 'aioseo_posts' )
73
  ->where( 'post_id', $postId )
74
  ->run()
75
  ->model( 'AIOSEO\\Plugin\\Common\\Models\\Post' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
 
78
  /**
@@ -80,16 +115,12 @@ class Post extends Model {
80
  *
81
  * @since 4.0.3
82
  *
83
- * @param int $postId The Post ID.
84
- * @param array $data The post data to save.
85
- * @return bool|WP_REST_Response True if post saved or Response Error.
86
  */
87
  public static function savePost( $postId, $data ) {
88
- $thePost = aioseo()->db
89
- ->start( 'aioseo_posts' )
90
- ->where( 'post_id', $postId )
91
- ->run()
92
- ->model( 'AIOSEO\\Plugin\\Common\\Models\\Post' );
93
 
94
  $post = aioseo()->helpers->getPost( $postId );
95
 
@@ -155,6 +186,7 @@ class Post extends Model {
155
  if ( ! $thePost->exists() ) {
156
  $thePost->created = gmdate( 'Y-m-d H:i:s' );
157
  }
 
158
  $thePost->save();
159
  $thePost->reset();
160
 
@@ -178,8 +210,6 @@ class Post extends Model {
178
  if ( ! empty( $lastError ) ) {
179
  return $lastError;
180
  }
181
-
182
- return null;
183
  }
184
 
185
  /**
68
  * @return Post The Post object.
69
  */
70
  public static function getPost( $postId ) {
71
+ $post = aioseo()->db
72
  ->start( 'aioseo_posts' )
73
  ->where( 'post_id', $postId )
74
  ->run()
75
  ->model( 'AIOSEO\\Plugin\\Common\\Models\\Post' );
76
+
77
+ if ( ! $post->exists() ) {
78
+ $post = self::setDynamicDefaults( $post, $postId );
79
+ }
80
+
81
+ return $post;
82
+ }
83
+
84
+ /**
85
+ * Sets the dynamic defaults on the post object if it doesn't exist in the DB yet.
86
+ *
87
+ * @since 4.1.4
88
+ *
89
+ * @param Post $post The post object.
90
+ * @param int $postId The post ID.
91
+ * @return Post The modified post object.
92
+ */
93
+ private static function setDynamicDefaults( $post, $postId ) {
94
+ if (
95
+ 'page' === get_post_type( $postId ) && // This check cannot be deleted and is required to prevent errors after WordPress cleans up the attachment it creates when a plugin is updated.
96
+ (
97
+ aioseo()->helpers->isWooCommerceCheckoutPage( $postId ) ||
98
+ aioseo()->helpers->isWooCommerceCartPage( $postId ) ||
99
+ aioseo()->helpers->isWooCommerceAccountPage( $postId )
100
+ )
101
+ ) {
102
+ $post->robots_default = false;
103
+ $post->robots_noindex = true;
104
+ }
105
+
106
+ if ( aioseo()->helpers->isStaticHomePage( $postId ) ) {
107
+ $post->og_object_type = 'website';
108
+ }
109
+
110
+ return $post;
111
  }
112
 
113
  /**
115
  *
116
  * @since 4.0.3
117
  *
118
+ * @param int $postId The Post ID.
119
+ * @param array $data The post data to save.
120
+ * @return void|string True if post data was saved or error response.
121
  */
122
  public static function savePost( $postId, $data ) {
123
+ $thePost = self::getPost( $postId );
 
 
 
 
124
 
125
  $post = aioseo()->helpers->getPost( $postId );
126
 
186
  if ( ! $thePost->exists() ) {
187
  $thePost->created = gmdate( 'Y-m-d H:i:s' );
188
  }
189
+
190
  $thePost->save();
191
  $thePost->reset();
192
 
210
  if ( ! empty( $lastError ) ) {
211
  return $lastError;
212
  }
 
 
213
  }
214
 
215
  /**
app/Common/Options/Cache.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Options;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Class that holds all the cache for the AIOSEO options.
11
+ *
12
+ * @since 4.1.4
13
+ */
14
+ class Cache {
15
+ /**
16
+ * The DB options cache.
17
+ *
18
+ * @since 4.1.4
19
+ *
20
+ * @var array
21
+ */
22
+ private static $db = [];
23
+
24
+ /**
25
+ * The options cache.
26
+ *
27
+ * @since 4.1.4
28
+ *
29
+ * @var array
30
+ */
31
+ private static $options = [];
32
+
33
+ /**
34
+ * Sets the cache for the DB option.
35
+ *
36
+ * @since 4.1.4
37
+ *
38
+ * @param string $name The cache name.
39
+ * @param array $value The value.
40
+ * @return void
41
+ */
42
+ public function setDb( $name, $value ) {
43
+ self::$db[ $name ] = $value;
44
+ }
45
+
46
+ /**
47
+ * Gets the cache for the DB option.
48
+ *
49
+ * @since 4.1.4
50
+ *
51
+ * @param string $name The cache name.
52
+ * @return array The data from the cache.
53
+ */
54
+ public function getDb( $name ) {
55
+ return ! empty( self::$db[ $name ] ) ? self::$db[ $name ] : [];
56
+ }
57
+
58
+ /**
59
+ * Sets the cache for the options.
60
+ *
61
+ * @since 4.1.4
62
+ *
63
+ * @param string $name The cache name.
64
+ * @param array $value The value.
65
+ * @return void
66
+ */
67
+ public function setOptions( $name, $value ) {
68
+ self::$options[ $name ] = $value;
69
+ }
70
+
71
+ /**
72
+ * Gets the cache for the options.
73
+ *
74
+ * @since 4.1.4
75
+ *
76
+ * @param string $name The cache name.
77
+ * @return array The data from the cache.
78
+ */
79
+ public function getOptions( $name ) {
80
+ return ! empty( self::$options[ $name ] ) ? self::$options[ $name ] : [];
81
+ }
82
+
83
+ /**
84
+ * Resets the DB cache.
85
+ *
86
+ * @since 4.1.4
87
+ *
88
+ * @return void
89
+ */
90
+ public function resetDb() {
91
+ self::$db = [];
92
+ }
93
+ }
app/Common/Options/DynamicBackup.php ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Options;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Handles the dynamic backup.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class DynamicBackup {
15
+ /**
16
+ * A the name of the option to save dynamic backups to.
17
+ *
18
+ * @since 4.1.3
19
+ *
20
+ * @var string
21
+ */
22
+ protected $optionsName = 'aioseo_dynamic_settings_backup';
23
+
24
+ /**
25
+ * The dynamic backup.
26
+ *
27
+ * @since 4.1.3
28
+ *
29
+ * @var array
30
+ */
31
+ protected $backup = [];
32
+
33
+ /**
34
+ * Whether the backup should be updated.
35
+ *
36
+ * @since 4.1.3
37
+ *
38
+ * @var boolean
39
+ */
40
+ protected $shouldBackup = false;
41
+
42
+ /**
43
+ * The options from the DB.
44
+ *
45
+ * @since 4.1.3
46
+ *
47
+ * @var array
48
+ */
49
+ protected $options = [];
50
+
51
+ /**
52
+ * Class constructor.
53
+ *
54
+ * @since 4.1.3
55
+ */
56
+ public function __construct() {
57
+ add_action( 'wp_loaded', [ $this, 'init' ], 5000 );
58
+ add_action( 'shutdown', [ $this, 'updateBackup' ] );
59
+ }
60
+
61
+ /**
62
+ * Updates the backup after restoring options.
63
+ *
64
+ * @since 4.1.3
65
+ *
66
+ * @return void
67
+ */
68
+ public function updateBackup() {
69
+ if ( $this->shouldBackup ) {
70
+ $this->shouldBackup = false;
71
+ $backup = aioseo()->dynamicOptions->convertOptionsToValues( $this->backup, 'value' );
72
+ update_option( $this->optionsName, wp_json_encode( $backup ) );
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Checks whether data from the backup has to be restored.
78
+ *
79
+ * @since 4.1.3
80
+ *
81
+ * @return void
82
+ */
83
+ public function init() {
84
+ $backup = json_decode( get_option( $this->optionsName ), true );
85
+ if ( empty( $backup ) ) {
86
+ update_option( $this->optionsName, '{}' );
87
+ return;
88
+ }
89
+
90
+ aioseo()->dynamicOptions->refresh();
91
+
92
+ $this->backup = $backup;
93
+ $this->options = aioseo()->dynamicOptions->getDefaults();
94
+
95
+ $this->restorePostTypes();
96
+ $this->restoreTaxonomies();
97
+ $this->restoreArchives();
98
+ }
99
+
100
+ /**
101
+ * Restores the dynamic Post Types options.
102
+ *
103
+ * @since 4.1.3
104
+ *
105
+ * @return void
106
+ */
107
+ private function restorePostTypes() {
108
+ $postTypes = aioseo()->helpers->getPublicPostTypes();
109
+ foreach ( $postTypes as $postType ) {
110
+ $name = $postType['name'];
111
+ if ( 'type' === $name ) {
112
+ $name = '_aioseo_type';
113
+ }
114
+
115
+ if ( ! empty( $this->backup['postTypes'][ $name ]['searchAppearance'] ) ) {
116
+ $this->restoreOptions( $this->backup['postTypes'][ $name ]['searchAppearance'], [ 'searchAppearance', 'postTypes', $name ] );
117
+ unset( $this->backup['postTypes'][ $name ]['searchAppearance'] );
118
+ $this->shouldBackup = true;
119
+ }
120
+
121
+ if ( ! empty( $this->backup['postTypes'][ $name ]['social']['facebook'] ) ) {
122
+ $this->restoreOptions( $this->backup['postTypes'][ $name ]['social']['facebook'], [ 'social', 'facebook', 'general', 'postTypes', $name ] );
123
+ unset( $this->backup['postTypes'][ $name ]['social']['facebook'] );
124
+ $this->shouldBackup = true;
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Restores the dynamic Taxonomies options.
131
+ *
132
+ * @since 4.1.3
133
+ *
134
+ * @return void
135
+ */
136
+ private function restoreTaxonomies() {
137
+ $taxonomies = aioseo()->helpers->getPublicTaxonomies();
138
+ foreach ( $taxonomies as $taxonomy ) {
139
+ $name = $taxonomy['name'];
140
+ if ( 'type' === $name ) {
141
+ $name = '_aioseo_type';
142
+ }
143
+
144
+ if ( ! empty( $this->backup['taxonomies'][ $name ]['searchAppearance'] ) ) {
145
+ $this->restoreOptions( $this->backup['taxonomies'][ $name ]['searchAppearance'], [ 'searchAppearance', 'taxonomies', $name ] );
146
+ unset( $this->backup['taxonomies'][ $name ]['searchAppearance'] );
147
+ $this->shouldBackup = true;
148
+ }
149
+
150
+ if ( ! empty( $this->backup['taxonomies'][ $name ]['social']['facebook'] ) ) {
151
+ $this->restoreOptions( $this->backup['taxonomies'][ $name ]['social']['facebook'], [ 'social', 'facebook', 'general', 'taxonomies', $name ] );
152
+ unset( $this->backup['taxonomies'][ $name ]['social']['facebook'] );
153
+ $this->shouldBackup = true;
154
+ }
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Restores the dynamic Archives options.
160
+ *
161
+ * @since 4.1.3
162
+ *
163
+ * @return void
164
+ */
165
+ private function restoreArchives() {
166
+ $postTypes = aioseo()->helpers->getPublicPostTypes();
167
+ foreach ( $postTypes as $postType ) {
168
+ $name = $postType['name'];
169
+ if ( 'type' === $name ) {
170
+ $name = '_aioseo_type';
171
+ }
172
+
173
+ if ( ! empty( $this->backup['archives'][ $name ]['searchAppearance'] ) ) {
174
+ $this->restoreOptions( $this->backup['archives'][ $name ]['searchAppearance'], [ 'searchAppearance', 'archives', $name ] );
175
+ unset( $this->backup['archives'][ $name ]['searchAppearance'] );
176
+ $this->shouldBackup = true;
177
+ }
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Restores the backuped options.
183
+ *
184
+ * @since 4.1.3
185
+ *
186
+ * @return void
187
+ * @param array $backupOptions The options to be restored.
188
+ * @param array $groups The group that the option should be restored.
189
+ */
190
+ protected function restoreOptions( $backupOptions, $groups ) {
191
+ $groupPath = $this->options;
192
+ foreach ( $groups as $group ) {
193
+ if ( ! isset( $groupPath[ $group ] ) ) {
194
+ return false;
195
+ }
196
+ $groupPath = $groupPath[ $group ];
197
+ }
198
+
199
+ $options = aioseo()->dynamicOptions->noConflict();
200
+ foreach ( $backupOptions as $setting => $value ) {
201
+ // Check if the option exists by checking if the type is defined.
202
+ $type = ! empty( $groupPath[ $setting ]['type'] ) ? $groupPath[ $setting ]['type'] : '';
203
+ if ( ! $type ) {
204
+ continue;
205
+ }
206
+
207
+ foreach ( $groups as $group ) {
208
+ $options = $options->$group;
209
+ }
210
+
211
+ $options->$setting = $value;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Maybe backup the options if it has disappeared.
217
+ *
218
+ * @since 4.1.3
219
+ *
220
+ * @param array $newOptions An array of options to check.
221
+ * @return void
222
+ */
223
+ public function maybeBackup( $newOptions ) {
224
+ $this->maybeBackupPostType( $newOptions['searchAppearance']['postTypes'], $newOptions['social']['facebook']['general']['postTypes'] );
225
+ $this->maybeBackupTaxonomy( $newOptions['searchAppearance']['taxonomies'] );
226
+ $this->maybeBackupArchives( $newOptions['searchAppearance']['archives'] );
227
+ }
228
+
229
+ /**
230
+ * Maybe backup the Post Types.
231
+ *
232
+ * @since 4.1.3
233
+ *
234
+ * @param array $dynamicPostTypes An array of dynamic post types from Search Appearance to check.
235
+ * @param array $dynamicPostTypeOG An array of dynamic post types from Social Facebook to check.
236
+ * @return void
237
+ */
238
+ private function maybeBackupPostType( $dynamicPostTypes, $dynamicPostTypesOG ) {
239
+ $postTypes = aioseo()->helpers->getPublicPostTypes();
240
+ $postTypes = $this->normalizeObjectName( $postTypes );
241
+
242
+ foreach ( $dynamicPostTypes as $dynamicPostTypeName => $dynamicPostTypeSettings ) {
243
+ $found = wp_list_filter( $postTypes, [ 'name' => $dynamicPostTypeName ] );
244
+ if ( count( $found ) === 0 ) {
245
+ $this->backup['postTypes'][ $dynamicPostTypeName ]['searchAppearance'] = $dynamicPostTypeSettings;
246
+ $this->shouldBackup = true;
247
+ }
248
+ }
249
+
250
+ foreach ( $dynamicPostTypesOG as $dynamicPostTypeNameOG => $dynamicPostTypeSettingsOG ) {
251
+ $found = wp_list_filter( $postTypes, [ 'name' => $dynamicPostTypeNameOG ] );
252
+ if ( count( $found ) === 0 ) {
253
+ $this->backup['postTypes'][ $dynamicPostTypeNameOG ]['social']['facebook'] = $dynamicPostTypeSettingsOG;
254
+ $this->shouldBackup = true;
255
+ }
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Maybe backup the Taxonomies.
261
+ *
262
+ * @since 4.1.3
263
+ *
264
+ * @param array $dynamicTaxonomies An array of dynamic taxonomy from Search Appearance to check.
265
+ * @param array $dynamicTaxonomiesOG An array of dynamic taxonomy from Social Facebook to check.
266
+ * @return void
267
+ */
268
+ protected function maybeBackupTaxonomy( $dynamicTaxonomies, $dynamicTaxonomiesOG = [] ) {
269
+ $taxonomies = aioseo()->helpers->getPublicTaxonomies();
270
+ $taxonomies = $this->normalizeObjectName( $taxonomies );
271
+
272
+ foreach ( $dynamicTaxonomies as $dynamicTaxonomyName => $dynamicTaxonomySettings ) {
273
+ $found = wp_list_filter( $taxonomies, [ 'name' => $dynamicTaxonomyName ] );
274
+ if ( count( $found ) === 0 ) {
275
+ $this->backup['taxonomies'][ $dynamicTaxonomyName ]['searchAppearance'] = $dynamicTaxonomySettings;
276
+ $this->shouldBackup = true;
277
+ }
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Maybe backup the Archives.
283
+ *
284
+ * @since 4.1.3
285
+ *
286
+ * @param array $dynamicArchives An array of dynamic archives to check.
287
+ * @return void
288
+ */
289
+ private function maybeBackupArchives( $dynamicArchives ) {
290
+ $postTypes = aioseo()->helpers->getPublicPostTypes( false, true );
291
+ $postTypes = $this->normalizeObjectName( $postTypes );
292
+
293
+ foreach ( $dynamicArchives as $archiveName => $archiveSettings ) {
294
+ $found = wp_list_filter( $postTypes, [ 'name' => $archiveName ] );
295
+ if ( count( $found ) === 0 ) {
296
+ $this->backup['archives'][ $archiveName ]['searchAppearance'] = $archiveSettings;
297
+ $this->shouldBackup = true;
298
+ }
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Normalize object name to work properly with AIOSEO.
304
+ *
305
+ * @since 4.1.3
306
+ *
307
+ * @param array $items The items.
308
+ * @return array The normalized items.
309
+ */
310
+ public function normalizeObjectName( $items ) {
311
+ foreach ( $items as &$item ) {
312
+ if ( 'type' === $item['name'] ) {
313
+ $item['name'] = '_aioseo_type';
314
+ }
315
+ }
316
+
317
+ return $items;
318
+ }
319
+ }
app/Common/Options/DynamicOptions.php ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Options;
3
+
4
+ use AIOSEO\Plugin\Common\Traits;
5
+
6
+ // Exit if accessed directly.
7
+ if ( ! defined( 'ABSPATH' ) ) {
8
+ exit;
9
+ }
10
+
11
+ /**
12
+ * Handles the dynamic options.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ class DynamicOptions {
17
+ use Traits\Options;
18
+
19
+ /**
20
+ * The default options.
21
+ *
22
+ * @since 4.1.4
23
+ *
24
+ * @var array
25
+ */
26
+ protected $defaults = [
27
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
28
+ 'sitemap' => [
29
+ 'priority' => [
30
+ 'postTypes' => [],
31
+ 'taxonomies' => []
32
+ ]
33
+ ],
34
+ 'social' => [
35
+ 'facebook' => [
36
+ 'general' => [
37
+ 'postTypes' => []
38
+ ]
39
+ ]
40
+ ],
41
+ 'searchAppearance' => [
42
+ 'postTypes' => [],
43
+ 'taxonomies' => [],
44
+ 'archives' => []
45
+ ]
46
+ // phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
47
+ ];
48
+
49
+ /**
50
+ * Class constructor.
51
+ *
52
+ * @since 4.1.4
53
+ *
54
+ * @param string $optionsName The options name.
55
+ */
56
+ public function __construct( $optionsName = 'aioseo_options_dynamic' ) {
57
+ $this->optionsName = is_network_admin() ? $optionsName . '_network' : $optionsName;
58
+
59
+ // Load defaults in case this is a complete fresh install.
60
+ $this->init();
61
+
62
+ add_action( 'shutdown', [ $this, 'save' ] );
63
+ }
64
+
65
+ /**
66
+ * Initializes the options.
67
+ *
68
+ * @since 4.1.4
69
+ *
70
+ * @return void
71
+ */
72
+ protected function init() {
73
+ $this->addDynamicDefaults();
74
+ $this->setDbOptions();
75
+ }
76
+
77
+ /**
78
+ * Sets the DB options.
79
+ *
80
+ * @since 4.1.4
81
+ *
82
+ * @return void
83
+ */
84
+ protected function setDbOptions() {
85
+ $dbOptions = $this->getDbOptions( $this->optionsName );
86
+
87
+ // Refactor options.
88
+ $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->defaultsMerged );
89
+
90
+ $dbOptions = array_replace_recursive(
91
+ $this->defaultsMerged,
92
+ $this->addValueToValuesArray( $this->defaultsMerged, $dbOptions )
93
+ );
94
+
95
+ aioseo()->optionsCache->setOptions( $this->optionsName, $dbOptions );
96
+
97
+ // Get the localized options.
98
+ $dbOptionsLocalized = get_option( $this->optionsName . '_localized' );
99
+ if ( empty( $dbOptionsLocalized ) ) {
100
+ $dbOptionsLocalized = [];
101
+ }
102
+ $this->localized = $dbOptionsLocalized;
103
+ }
104
+
105
+ /**
106
+ * Sanitizes, then saves the options to the database.
107
+ *
108
+ * @since 4.1.4
109
+ *
110
+ * @param array $options An array of options to sanitize, then save.
111
+ * @return void
112
+ */
113
+ public function sanitizeAndSave( $options ) {
114
+ if ( ! is_array( $options ) ) {
115
+ return;
116
+ }
117
+
118
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
119
+
120
+ aioseo()->dynamicBackup->maybeBackup( $cachedOptions );
121
+
122
+ // Refactor options.
123
+ $dbOptions = array_replace_recursive(
124
+ $cachedOptions,
125
+ $this->addValueToValuesArray( $cachedOptions, $options, [], true )
126
+ );
127
+
128
+ aioseo()->optionsCache->setOptions( $this->optionsName, $dbOptions );
129
+
130
+ // Update localized options.
131
+ update_option( $this->optionsName . '_localized', $this->localized );
132
+
133
+ // Update values.
134
+ $this->save( true );
135
+ }
136
+
137
+ /**
138
+ * Adds some defaults that are dynamically generated.
139
+ *
140
+ * @since 4.1.4
141
+ *
142
+ * @return void
143
+ */
144
+ public function addDynamicDefaults() {
145
+ $this->addDynamicPostTypeDefaults();
146
+ $this->addDynamicTaxonomyDefaults();
147
+ $this->addDynamicArchiveDefaults();
148
+ }
149
+
150
+ /**
151
+ * Adds the dynamic defaults for the public post types.
152
+ *
153
+ * @since 4.1.4
154
+ *
155
+ * @return void
156
+ */
157
+ protected function addDynamicPostTypeDefaults() {
158
+ $postTypes = aioseo()->helpers->getPublicPostTypes();
159
+ foreach ( $postTypes as $postType ) {
160
+ if ( 'type' === $postType['name'] ) {
161
+ $postType['name'] = '_aioseo_type';
162
+ }
163
+
164
+ $defaultTitle = '#post_title #separator_sa #site_title';
165
+ $defaultDescription = $postType['hasExcerpt'] ? '#post_excerpt' : '#post_content';
166
+ $defaultSchemaType = 'WebPage';
167
+ $defaultWebPageType = 'WebPage';
168
+ $defaultArticleType = 'BlogPosting';
169
+
170
+ switch ( $postType['name'] ) {
171
+ case 'post':
172
+ $defaultSchemaType = 'Article';
173
+ break;
174
+ case 'attachment':
175
+ $defaultDescription = '#attachment_caption';
176
+ $defaultSchemaType = 'ItemPage';
177
+ $defaultWebPageType = 'ItemPage';
178
+ break;
179
+ case 'product':
180
+ $defaultSchemaType = 'WebPage';
181
+ $defaultWebPageType = 'ItemPage';
182
+ break;
183
+ case 'news':
184
+ $defaultArticleType = 'NewsArticle';
185
+ break;
186
+ default:
187
+ break;
188
+ }
189
+
190
+ $defaultOptions = array_replace_recursive(
191
+ $this->getDefaultSearchAppearanceOptions(),
192
+ [
193
+ 'title' => [
194
+ 'type' => 'string',
195
+ 'localized' => true,
196
+ 'default' => $defaultTitle
197
+ ],
198
+ 'metaDescription' => [
199
+ 'type' => 'string',
200
+ 'localized' => true,
201
+ 'default' => $defaultDescription
202
+ ],
203
+ 'schemaType' => [
204
+ 'type' => 'string',
205
+ 'default' => $defaultSchemaType
206
+ ],
207
+ 'webPageType' => [
208
+ 'type' => 'string',
209
+ 'default' => $defaultWebPageType
210
+ ],
211
+ 'articleType' => [
212
+ 'type' => 'string',
213
+ 'default' => $defaultArticleType
214
+ ],
215
+ 'customFields' => [ 'type' => 'html' ],
216
+ 'advanced' => [
217
+ 'bulkEditing' => [
218
+ 'type' => 'string',
219
+ 'default' => 'enabled'
220
+ ]
221
+ ]
222
+ ]
223
+ );
224
+
225
+ if ( 'attachment' === $postType['name'] ) {
226
+ $defaultOptions['redirectAttachmentUrls'] = [
227
+ 'type' => 'string',
228
+ 'default' => 'attachment'
229
+ ];
230
+ }
231
+
232
+ $this->defaults['searchAppearance']['postTypes'][ $postType['name'] ] = $defaultOptions;
233
+ $this->setDynamicSocialOptions( 'postTypes', $postType['name'] );
234
+ $this->setDynamicSitemapOptions( 'postTypes', $postType['name'] );
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Adds the dynamic defaults for the public taxonomies.
240
+ *
241
+ * @since 4.1.4
242
+ *
243
+ * @return void
244
+ */
245
+ protected function addDynamicTaxonomyDefaults() {
246
+ $taxonomies = aioseo()->helpers->getPublicTaxonomies();
247
+ foreach ( $taxonomies as $taxonomy ) {
248
+ if ( 'type' === $taxonomy['name'] ) {
249
+ $taxonomy['name'] = '_aioseo_type';
250
+ }
251
+
252
+ $defaultOptions = array_replace_recursive(
253
+ $this->getDefaultSearchAppearanceOptions(),
254
+ [
255
+ 'title' => [
256
+ 'type' => 'string',
257
+ 'localized' => true,
258
+ 'default' => '#taxonomy_title #separator_sa #site_title'
259
+ ],
260
+ 'metaDescription' => [
261
+ 'type' => 'string',
262
+ 'localized' => true,
263
+ 'default' => '#taxonomy_description'
264
+ ],
265
+ ]
266
+ );
267
+
268
+ $this->defaults['searchAppearance']['taxonomies'][ $taxonomy['name'] ] = $defaultOptions;
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Adds the dynamic defaults for the archive pages.
274
+ *
275
+ * @since 4.1.4
276
+ *
277
+ * @return void
278
+ */
279
+ protected function addDynamicArchiveDefaults() {
280
+ $postTypes = aioseo()->helpers->getPublicPostTypes( false, true );
281
+ foreach ( $postTypes as $postType ) {
282
+ if ( 'type' === $postType['name'] ) {
283
+ $postType['name'] = '_aioseo_type';
284
+ }
285
+
286
+ $defaultOptions = array_replace_recursive(
287
+ $this->getDefaultSearchAppearanceOptions(),
288
+ [
289
+ 'title' => [
290
+ 'type' => 'string',
291
+ 'localized' => true,
292
+ 'default' => '#archive_title #separator_sa #site_title'
293
+ ],
294
+ 'metaDescription' => [
295
+ 'type' => 'string',
296
+ 'localized' => true,
297
+ 'default' => ''
298
+ ],
299
+ 'customFields' => [ 'type' => 'html' ],
300
+ 'advanced' => [
301
+ 'keywords' => [
302
+ 'type' => 'string',
303
+ 'localized' => true
304
+ ]
305
+ ]
306
+ ]
307
+ );
308
+
309
+ $this->defaults['searchAppearance']['archives'][ $postType['name'] ] = $defaultOptions;
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Returns the search appearance options for dynamic objects.
315
+ *
316
+ * @since 4.1.4
317
+ *
318
+ * @return array The default options.
319
+ */
320
+ protected function getDefaultSearchAppearanceOptions() {
321
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
322
+ return [
323
+ 'show' => [ 'type' => 'boolean', 'default' => true ],
324
+ 'advanced' => [
325
+ 'robotsMeta' => [
326
+ 'default' => [ 'type' => 'boolean', 'default' => true ],
327
+ 'noindex' => [ 'type' => 'boolean', 'default' => false ],
328
+ 'nofollow' => [ 'type' => 'boolean', 'default' => false ],
329
+ 'noarchive' => [ 'type' => 'boolean', 'default' => false ],
330
+ 'noimageindex' => [ 'type' => 'boolean', 'default' => false ],
331
+ 'notranslate' => [ 'type' => 'boolean', 'default' => false ],
332
+ 'nosnippet' => [ 'type' => 'boolean', 'default' => false ],
333
+ 'noodp' => [ 'type' => 'boolean', 'default' => false ],
334
+ 'maxSnippet' => [ 'type' => 'number', 'default' => -1 ],
335
+ 'maxVideoPreview' => [ 'type' => 'number', 'default' => -1 ],
336
+ 'maxImagePreview' => [ 'type' => 'string', 'default' => 'large' ]
337
+ ],
338
+ 'showDateInGooglePreview' => [ 'type' => 'boolean', 'default' => true ],
339
+ 'showPostThumbnailInSearch' => [ 'type' => 'boolean', 'default' => true ],
340
+ 'showMetaBox' => [ 'type' => 'boolean', 'default' => true ]
341
+ ]
342
+ ];
343
+ // phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
344
+ }
345
+
346
+ /**
347
+ * Sets the dynamic social settings for a given post type or taxonomy.
348
+ *
349
+ * @since 4.1.4
350
+ *
351
+ * @param string $objectType Whether the object belongs to the dynamic "postTypes" or "taxonomies".
352
+ * @param string $objectName The object name.
353
+ * @return void
354
+ */
355
+ protected function setDynamicSocialOptions( $objectType, $objectName ) {
356
+ $defaultOptions = [
357
+ 'objectType' => [
358
+ 'type' => 'string',
359
+ 'default' => 'article'
360
+ ]
361
+ ];
362
+
363
+ $this->defaults['social']['facebook']['general'][ $objectType ][ $objectName ] = $defaultOptions;
364
+ }
365
+
366
+ /**
367
+ * Sets the dynamic sitemap settings for a given post type or taxonomy.
368
+ *
369
+ * @since 4.1.4
370
+ *
371
+ * @param string $objectType Whether the object belongs to the dynamic "postTypes" or "taxonomies".
372
+ * @param string $objectName The object name.
373
+ * @return void
374
+ */
375
+ protected function setDynamicSitemapOptions( $objectType, $objectName ) {
376
+ $this->defaults['sitemap']['priority'][ $objectType ][ $objectName ] = [
377
+ 'priority' => [
378
+ 'type' => 'string',
379
+ 'default' => '{"label":"default","value":"default"}'
380
+ ],
381
+ 'frequency' => [
382
+ 'type' => 'string',
383
+ 'default' => '{"label":"default","value":"default"}'
384
+ ]
385
+ ];
386
+ }
387
+ }
app/Common/{Utils → Options}/InternalOptions.php RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace AIOSEO\Plugin\Common\Utils;
3
 
4
  // Exit if accessed directly.
5
  if ( ! defined( 'ABSPATH' ) ) {
@@ -77,12 +77,14 @@ class InternalOptions {
77
  *
78
  * @since 4.0.0
79
  *
80
- * @param string $optionsName An array of options.
81
  */
82
  public function __construct( $optionsName = 'aioseo_options_internal' ) {
83
  $this->optionsName = is_network_admin() ? $optionsName . '_network' : $optionsName;
84
 
85
  $this->init();
 
 
86
  }
87
 
88
  /**
@@ -94,10 +96,7 @@ class InternalOptions {
94
  */
95
  protected function init() {
96
  // Options from the DB.
97
- $dbOptions = json_decode( get_option( $this->optionsName ), true );
98
- if ( empty( $dbOptions ) ) {
99
- $dbOptions = [];
100
- }
101
 
102
  // Refactor options.
103
  $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->defaultsMerged );
@@ -107,7 +106,7 @@ class InternalOptions {
107
  $this->addValueToValuesArray( $this->defaultsMerged, $dbOptions )
108
  );
109
 
110
- $this->options = apply_filters( 'aioseo_get_options_internal', $options );
111
 
112
  // Get the localized options.
113
  $dbOptionsLocalized = get_option( $this->optionsName . '_localized' );
@@ -142,17 +141,20 @@ class InternalOptions {
142
  }
143
 
144
  // Refactor options.
145
- $this->options = array_replace_recursive(
146
- $this->options,
147
- $this->addValueToValuesArray( $this->options, $options, [], true )
 
148
  );
149
 
150
- $this->options['internal']['siteAnalysis']['competitors']['value'] = $this->sanitizeField( $options['internal']['siteAnalysis']['competitors'], 'array', true );
 
 
151
 
152
  // Update localized options.
153
  update_option( $this->optionsName . '_localized', $this->localized );
154
 
155
  // Update values.
156
- $this->update();
157
  }
158
  }
1
  <?php
2
+ namespace AIOSEO\Plugin\Common\Options;
3
 
4
  // Exit if accessed directly.
5
  if ( ! defined( 'ABSPATH' ) ) {
77
  *
78
  * @since 4.0.0
79
  *
80
+ * @param string $optionsName The options name.
81
  */
82
  public function __construct( $optionsName = 'aioseo_options_internal' ) {
83
  $this->optionsName = is_network_admin() ? $optionsName . '_network' : $optionsName;
84
 
85
  $this->init();
86
+
87
+ add_action( 'shutdown', [ $this, 'save' ] );
88
  }
89
 
90
  /**
96
  */
97
  protected function init() {
98
  // Options from the DB.
99
+ $dbOptions = $this->getDbOptions( $this->optionsName );
 
 
 
100
 
101
  // Refactor options.
102
  $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->defaultsMerged );
106
  $this->addValueToValuesArray( $this->defaultsMerged, $dbOptions )
107
  );
108
 
109
+ aioseo()->optionsCache->setOptions( $this->optionsName, apply_filters( 'aioseo_get_options_internal', $options ) );
110
 
111
  // Get the localized options.
112
  $dbOptionsLocalized = get_option( $this->optionsName . '_localized' );
141
  }
142
 
143
  // Refactor options.
144
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
145
+ $dbOptions = array_replace_recursive(
146
+ $cachedOptions,
147
+ $this->addValueToValuesArray( $cachedOptions, $options, [], true )
148
  );
149
 
150
+ $dbOptions['internal']['siteAnalysis']['competitors']['value'] = $this->sanitizeField( $options['internal']['siteAnalysis']['competitors'], 'array', true );
151
+
152
+ aioseo()->optionsCache->setOptions( $this->optionsName, $dbOptions );
153
 
154
  // Update localized options.
155
  update_option( $this->optionsName . '_localized', $this->localized );
156
 
157
  // Update values.
158
+ $this->save( true );
159
  }
160
  }
app/Common/{Utils → Options}/Options.php RENAMED
@@ -1,5 +1,5 @@
1
  <?php
2
- namespace AIOSEO\Plugin\Common\Utils;
3
 
4
  // Exit if accessed directly.
5
  if ( ! defined( 'ABSPATH' ) ) {
@@ -17,15 +17,6 @@ use AIOSEO\Plugin\Common\Traits;
17
  class Options {
18
  use Traits\Options;
19
 
20
- /**
21
- * Whether the options need to be updated.
22
- *
23
- * @since 4.1.1
24
- *
25
- * @var bool
26
- */
27
- protected $needsUpdate = false;
28
-
29
  /**
30
  * All the default options.
31
  *
@@ -35,16 +26,7 @@ class Options {
35
  */
36
  protected $defaults = [
37
  // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
38
- 'internal' => [
39
- 'searchAppearanceDynamicBackup' => [
40
- 'postTypes' => [ 'type' => 'array', 'default' => [] ],
41
- 'taxonomies' => [ 'type' => 'array', 'default' => [] ]
42
- ],
43
- 'socialFacebookDynamicBackup' => [
44
- 'postTypes' => [ 'type' => 'array', 'default' => [] ],
45
- 'taxonomies' => [ 'type' => 'array', 'default' => [] ]
46
- ],
47
- ],
48
  'webmasterTools' => [
49
  'google' => [ 'type' => 'string' ],
50
  'bing' => [ 'type' => 'string' ],
@@ -61,9 +43,9 @@ class Options {
61
  'homepageLink' => [ 'type' => 'boolean', 'default' => true ],
62
  'homepageLabel' => [ 'type' => 'string', 'default' => 'Home' ],
63
  'breadcrumbPrefix' => [ 'type' => 'string' ],
64
- 'archiveFormat' => [ 'type' => 'string', 'default' => 'Archives for #breadcrumb_archive_post_type_name' ],
65
- 'searchResultFormat' => [ 'type' => 'string', 'default' => 'Search for \'#breadcrumb_search_string\'' ],
66
- 'errorFormat404' => [ 'type' => 'string', 'default' => '404 Error: page not found' ],
67
  'showCurrentItem' => [ 'type' => 'boolean', 'default' => true ],
68
  'linkCurrentItem' => [ 'type' => 'boolean', 'default' => false ],
69
  'categoryFullHierarchy' => [ 'type' => 'boolean', 'default' => false ],
@@ -156,12 +138,28 @@ TEMPLATE
156
  'included' => [ 'type' => 'array', 'default' => [ 'post', 'page', 'product' ] ],
157
  ]
158
  ],
159
- 'dynamic' => [
160
- 'priority' => [
161
- 'postTypes' => [],
162
- 'taxonomies' => []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  ]
164
- ]
165
  ],
166
  'social' => [
167
  'profiles' => [
@@ -195,12 +193,7 @@ TEMPLATE
195
  'defaultImagePostsWidth' => [ 'type' => 'number', 'default' => '' ],
196
  'defaultImagePostsHeight' => [ 'type' => 'number', 'default' => '' ],
197
  'showAuthor' => [ 'type' => 'boolean', 'default' => true ],
198
- 'siteName' => [ 'type' => 'string', 'localized' => true, 'default' => '#site_title #separator_sa #tagline' ],
199
- 'dynamic' => [
200
- 'postTypes' => [],
201
- 'taxonomies' => [],
202
- 'archives' => []
203
- ]
204
  ],
205
  'homePage' => [
206
  'image' => [ 'type' => 'string', 'default' => '' ],
@@ -283,7 +276,7 @@ TEMPLATE
283
  'useCategoriesForMetaKeywords' => [ 'type' => 'boolean', 'default' => false ],
284
  'useTagsForMetaKeywords' => [ 'type' => 'boolean', 'default' => false ],
285
  'dynamicallyGenerateKeywords' => [ 'type' => 'boolean', 'default' => false ],
286
- 'pagedFormat' => [ 'type' => 'string', 'default' => '- Page #page_number' ]
287
  ],
288
  'archives' => [
289
  'author' => [
@@ -358,11 +351,6 @@ TEMPLATE
358
  'keywords' => [ 'type' => 'string', 'localized' => true ]
359
  ]
360
  ]
361
- ],
362
- 'dynamic' => [
363
- 'postTypes' => [],
364
- 'taxonomies' => [],
365
- 'archives' => []
366
  ]
367
  ],
368
  'tools' => [
@@ -443,6 +431,8 @@ TEMPLATE
443
  $this->optionsName = is_network_admin() ? $optionsName . '_network' : $optionsName;
444
 
445
  $this->init();
 
 
446
  }
447
 
448
  /**
@@ -450,368 +440,63 @@ TEMPLATE
450
  *
451
  * @since 4.0.0
452
  *
453
- * @param boolean $resetKeys Whether or not to reset keys after init.
454
  * @return void
455
  */
456
- protected function init( $resetKeys = false ) {
457
- if ( $resetKeys ) {
458
- $originalGroupKey = $this->groupKey;
459
- $originalSubGroups = $this->subGroups;
460
- }
461
-
462
- $this->addDynamicDefaults();
463
  $this->translateDefaults();
464
 
465
- $options = $this->getDbOptions();
466
-
467
- $this->options = apply_filters( 'aioseo_get_options', $options );
468
-
469
- // Get the localized options.
470
- $dbOptionsLocalized = get_option( $this->optionsName . '_localized' );
471
- if ( empty( $dbOptionsLocalized ) ) {
472
- $dbOptionsLocalized = [];
473
- }
474
- $this->localized = $dbOptionsLocalized;
475
-
476
- if ( $resetKeys ) {
477
- $this->groupKey = $originalGroupKey;
478
- $this->subGroups = $originalSubGroups;
479
- }
480
 
481
  add_action( 'wp_loaded', [ $this, 'maybeFlushRewriteRules' ] );
482
  }
483
 
484
  /**
485
- * Get the DB options.
486
  *
487
- * @since 4.0.12
488
  *
489
- * @return array An array of options.
490
  */
491
- public function getDbOptions() {
492
- // Options from the DB.
493
- $dbOptions = json_decode( get_option( $this->optionsName ), true );
494
- if ( empty( $dbOptions ) ) {
495
- $dbOptions = [];
496
- }
497
-
498
  // Refactor options.
499
  $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->defaultsMerged );
500
 
501
- return array_replace_recursive(
 
 
502
  $this->defaultsMerged,
503
  $this->addValueToValuesArray( $this->defaultsMerged, $dbOptions )
504
  );
505
- }
506
 
507
- /**
508
- * Adds some defaults that are dynamically generated.
509
- *
510
- * @since 4.0.0
511
- *
512
- * @return void
513
- */
514
- public function addDynamicDefaults() {
515
- $this->addDynamicPostTypeDefaults();
516
- $this->addDynamicTaxonomyDefaults();
517
- $this->addDynamicArchiveDefaults();
518
-
519
- $this->defaults['searchAppearance']['global']['schema']['organizationName']['default'] = aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) );
520
- $this->defaults['deprecated']['tools']['blocker']['custom']['bots']['default'] = implode( "\n", aioseo()->badBotBlocker->getBotList() );
521
- $this->defaults['deprecated']['tools']['blocker']['custom']['referer']['default'] = implode( "\n", aioseo()->badBotBlocker->getRefererList() );
522
-
523
- if ( $this->needsUpdate ) {
524
- $this->needsUpdate = false;
525
- $this->update( $this->getDbOptions() );
526
- }
527
- }
528
-
529
- /**
530
- * Adds the dynamic defaults for the public post types.
531
- *
532
- * @since 4.1.1
533
- *
534
- * @return void
535
- */
536
- protected function addDynamicPostTypeDefaults() {
537
- $postTypes = aioseo()->helpers->getPublicPostTypes();
538
- foreach ( $postTypes as $postType ) {
539
- if ( 'type' === $postType['name'] ) {
540
- $postType['name'] = '_aioseo_type';
541
- }
542
-
543
- $defaultTitle = '#post_title #separator_sa #site_title';
544
- $defaultDescription = $postType['hasExcerpt'] ? '#post_excerpt' : '#post_content';
545
- $defaultSchemaType = 'WebPage';
546
- $defaultWebPageType = 'WebPage';
547
- $defaultArticleType = 'BlogPosting';
548
-
549
- switch ( $postType['name'] ) {
550
- case 'post':
551
- $defaultSchemaType = 'Article';
552
- break;
553
- case 'attachment':
554
- $defaultDescription = '#attachment_caption';
555
- $defaultSchemaType = 'ItemPage';
556
- $defaultWebPageType = 'ItemPage';
557
- break;
558
- case 'product':
559
- $defaultSchemaType = 'WebPage';
560
- $defaultWebPageType = 'ItemPage';
561
- break;
562
- case 'news':
563
- $defaultArticleType = 'NewsArticle';
564
- break;
565
- default:
566
- break;
567
- }
568
-
569
- $defaultOptions = array_replace_recursive(
570
- $this->getDefaultSearchAppearanceOptions(),
571
- [
572
- 'title' => [
573
- 'type' => 'string',
574
- 'localized' => true,
575
- 'default' => $defaultTitle
576
- ],
577
- 'metaDescription' => [
578
- 'type' => 'string',
579
- 'localized' => true,
580
- 'default' => $defaultDescription
581
- ],
582
- 'schemaType' => [
583
- 'type' => 'string',
584
- 'default' => $defaultSchemaType
585
- ],
586
- 'webPageType' => [
587
- 'type' => 'string',
588
- 'default' => $defaultWebPageType
589
- ],
590
- 'articleType' => [
591
- 'type' => 'string',
592
- 'default' => $defaultArticleType
593
- ],
594
- 'customFields' => [ 'type' => 'html' ],
595
- 'advanced' => [
596
- 'bulkEditing' => [
597
- 'type' => 'string',
598
- 'default' => 'enabled'
599
- ]
600
- ]
601
- ]
602
- );
603
-
604
- if ( 'attachment' === $postType['name'] ) {
605
- $defaultOptions['redirectAttachmentUrls'] = [
606
- 'type' => 'string',
607
- 'default' => 'attachment'
608
- ];
609
- }
610
-
611
- $this->setDynamicSearchAppearanceOptions( 'postTypes', $postType['name'], $defaultOptions );
612
- $this->setDynamicSocialOptions( 'postTypes', $postType['name'] );
613
- $this->setDynamicSitemapOptions( 'postTypes', $postType['name'] );
614
- }
615
- }
616
-
617
- /**
618
- * Adds the dynamic defaults for the public taxonomies.
619
- *
620
- * @since 4.1.1
621
- *
622
- * @return void
623
- */
624
- protected function addDynamicTaxonomyDefaults() {
625
- $taxonomies = aioseo()->helpers->getPublicTaxonomies();
626
- foreach ( $taxonomies as $taxonomy ) {
627
- if ( 'type' === $taxonomy['name'] ) {
628
- $taxonomy['name'] = '_aioseo_type';
629
- }
630
-
631
- $defaultOptions = array_replace_recursive(
632
- $this->getDefaultSearchAppearanceOptions(),
633
- [
634
- 'title' => [
635
- 'type' => 'string',
636
- 'localized' => true,
637
- 'default' => '#taxonomy_title #separator_sa #site_title'
638
- ],
639
- 'metaDescription' => [
640
- 'type' => 'string',
641
- 'localized' => true,
642
- 'default' => '#taxonomy_description'
643
- ],
644
- ]
645
- );
646
-
647
- $this->setDynamicSearchAppearanceOptions( 'taxonomies', $taxonomy['name'], $defaultOptions );
648
- $this->setDynamicSocialOptions( 'taxonomies', $taxonomy['name'] );
649
- $this->setDynamicSitemapOptions( 'taxonomies', $taxonomy['name'] );
650
- }
651
-
652
- }
653
-
654
- /**
655
- * Adds the dynamic defaults for the archive pages.
656
- *
657
- * @since 4.1.1
658
- *
659
- * @return void
660
- */
661
- protected function addDynamicArchiveDefaults() {
662
- $postTypes = aioseo()->helpers->getPublicPostTypes( false, true );
663
- foreach ( $postTypes as $postType ) {
664
- if ( 'type' === $postType['name'] ) {
665
- $postType['name'] = '_aioseo_type';
666
- }
667
 
668
- $defaultOptions = array_replace_recursive(
669
- $this->getDefaultSearchAppearanceOptions(),
670
- [
671
- 'title' => [
672
- 'type' => 'string',
673
- 'localized' => true,
674
- 'default' => '#archive_title #separator_sa #site_title'
675
- ],
676
- 'metaDescription' => [
677
- 'type' => 'string',
678
- 'localized' => true,
679
- 'default' => ''
680
- ],
681
- 'customFields' => [ 'type' => 'html' ],
682
- 'advanced' => [
683
- 'keywords' => [
684
- 'type' => 'string',
685
- 'localized' => true
686
- ]
687
- ]
688
- ]
689
- );
690
-
691
- $this->setDynamicSearchAppearanceOptions( 'archives', $postType['name'], $defaultOptions );
692
- $this->setDynamicSocialOptions( 'archives', $postType['name'] );
693
- }
694
- }
695
-
696
- /**
697
- * Returns the search appearance options for dynamic objects.
698
- *
699
- * @since 4.1.1
700
- *
701
- * @return array The default options.
702
- */
703
- protected function getDefaultSearchAppearanceOptions() {
704
- // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
705
- return [
706
- 'show' => [ 'type' => 'boolean', 'default' => true ],
707
- 'advanced' => [
708
- 'robotsMeta' => [
709
- 'default' => [ 'type' => 'boolean', 'default' => true ],
710
- 'noindex' => [ 'type' => 'boolean', 'default' => false ],
711
- 'nofollow' => [ 'type' => 'boolean', 'default' => false ],
712
- 'noarchive' => [ 'type' => 'boolean', 'default' => false ],
713
- 'noimageindex' => [ 'type' => 'boolean', 'default' => false ],
714
- 'notranslate' => [ 'type' => 'boolean', 'default' => false ],
715
- 'nosnippet' => [ 'type' => 'boolean', 'default' => false ],
716
- 'noodp' => [ 'type' => 'boolean', 'default' => false ],
717
- 'maxSnippet' => [ 'type' => 'number', 'default' => -1 ],
718
- 'maxVideoPreview' => [ 'type' => 'number', 'default' => -1 ],
719
- 'maxImagePreview' => [ 'type' => 'string', 'default' => 'large' ]
720
- ],
721
- 'showDateInGooglePreview' => [ 'type' => 'boolean', 'default' => true ],
722
- 'showPostThumbnailInSearch' => [ 'type' => 'boolean', 'default' => true ],
723
- 'showMetaBox' => [ 'type' => 'boolean', 'default' => true ]
724
- ]
725
- ];
726
- // phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
727
- }
728
-
729
- /**
730
- * Sets the dynamic search appearance settings for a given post type or taxonomy.
731
- *
732
- * @since 4.1.1
733
- *
734
- * @param string $objectType Whether the object belongs to the dynamic "postTypes" or "taxonomies".
735
- * @param string $objectName The object name.
736
- * @param array $defaultOptions The default options for the object.
737
- * @return void
738
- */
739
- protected function setDynamicSearchAppearanceOptions( $objectType, $objectName, $defaultOptions ) {
740
- // Check if dynamic backup needs to be reset.
741
- if ( ! empty( $this->options['internal']['searchAppearanceDynamicBackup'][ $objectType ]['value'][ $objectName ] ) ) {
742
- $this->needsUpdate = true;
743
-
744
- // If the backup is double-encoded, decode it again first. This code is to support versions before 4.1.2 and can be removed at some point in the future.
745
- $value = $this->options['internal']['searchAppearanceDynamicBackup'][ $objectType ]['value'][ $objectName ];
746
- if ( is_string( $value ) ) {
747
- $value = json_decode( $value, true ) ? json_decode( $value, true ) : $value;
748
- }
749
-
750
- unset( $this->options['internal']['searchAppearanceDynamicBackup'][ $objectType ]['value'][ $objectName ] );
751
- if ( is_array( $value ) && ! empty( $value ) ) {
752
- $defaultOptions = array_replace_recursive( $defaultOptions, $value );
753
- }
754
  }
755
-
756
- $this->defaults['searchAppearance']['dynamic'][ $objectType ][ $objectName ] = $defaultOptions;
757
  }
758
 
759
  /**
760
- * Sets the dynamic social settings for a given post type or taxonomy.
761
  *
762
- * @since 4.1.1
763
  *
764
- * @param string $objectType Whether the object belongs to the dynamic "postTypes" or "taxonomies".
765
- * @param string $objectName The object name.
766
  * @return void
767
  */
768
- protected function setDynamicSocialOptions( $objectType, $objectName ) {
769
- $defaultOptions = [
770
- 'objectType' => [
771
- 'type' => 'string',
772
- 'default' => 'article'
773
- ]
774
- ];
775
-
776
- // Check if dynamic backup needs to be reset.
777
- if ( ! empty( $this->options['internal']['socialFacebookDynamicBackup'][ $objectType ]['value'][ $objectName ] ) ) {
778
- $this->needsUpdate = true;
779
-
780
- // If the backup is double-encoded, decode it again first. This code is to support versions before 4.1.2 and can be removed at some point in the future.
781
- $value = $this->options['internal']['socialFacebookDynamicBackup'][ $objectType ]['value'][ $objectName ];
782
- if ( is_string( $value ) ) {
783
- $value = json_decode( $value, true ) ? json_decode( $value, true ) : $value;
784
- }
785
-
786
- unset( $this->options['internal']['socialFacebookDynamicBackup'][ $objectType ]['value'][ $objectName ] );
787
- if ( is_array( $value ) && ! empty( $value ) ) {
788
- $defaultOptions = array_replace_recursive( $defaultOptions, $value );
789
- }
790
  }
791
 
792
- $this->defaults['social']['facebook']['general']['dynamic'][ $objectType ][ $objectName ] = $defaultOptions;
793
- }
794
 
795
- /**
796
- * Sets the dynamic sitemap settings for a given post type or taxonomy.
797
- *
798
- * @since 4.1.1
799
- *
800
- * @param string $objectType Whether the object belongs to the dynamic "postTypes" or "taxonomies".
801
- * @param string $objectName The object name.
802
- * @return void
803
- */
804
- protected function setDynamicSitemapOptions( $objectType, $objectName ) {
805
- $this->defaults['sitemap']['dynamic']['priority'][ $objectType ][ $objectName ] = [
806
- 'priority' => [
807
- 'type' => 'string',
808
- 'default' => '{"label":"default","value":"default"}'
809
- ],
810
- 'frequency' => [
811
- 'type' => 'string',
812
- 'default' => '{"label":"default","value":"default"}'
813
- ]
814
- ];
815
  }
816
 
817
  /**
@@ -822,6 +507,13 @@ TEMPLATE
822
  * @return void
823
  */
824
  public function translateDefaults() {
 
 
 
 
 
 
 
825
  $default = sprintf( '{"label":"%1$s","value":"default"}', __( 'default', 'all-in-one-seo-pack' ) );
826
  $this->defaults['sitemap']['general']['advancedSettings']['priority']['homePage']['priority']['default'] = $default;
827
  $this->defaults['sitemap']['general']['advancedSettings']['priority']['homePage']['frequency']['default'] = $default;
@@ -848,7 +540,7 @@ TEMPLATE
848
  * @return void
849
  */
850
  public function sanitizeAndSave( $options ) {
851
- $sitemapOptions = ! empty( $options['sitemap'] ) && ! empty( $options['sitemap']['general'] ) ? $options['sitemap']['general'] : null;
852
  $oldSitemapOptions = aioseo()->options->sitemap->general->all();
853
  $deprecatedSitemapOptions = ! empty( $options['deprecated']['sitemap']['general'] )
854
  ? $options['deprecated']['sitemap']['general']
@@ -858,6 +550,7 @@ TEMPLATE
858
  $phoneNumberOptions = isset( $options['searchAppearance']['global']['schema']['phone'] )
859
  ? $options['searchAppearance']['global']['schema']['phone']
860
  : null;
 
861
 
862
  $options = $this->maybeRemoveUnfilteredHtmlFields( $options );
863
 
@@ -867,119 +560,43 @@ TEMPLATE
867
  return;
868
  }
869
 
870
- // Get the settings from the options being passed in.
871
- $dynamicPostTypeSettings = $this->options['searchAppearance']['dynamic']['postTypes'];
872
- $dynamicPostTypeSettingsOG = $this->options['social']['facebook']['general']['dynamic']['postTypes'];
873
- $dynamicTaxonomiesSettings = $this->options['searchAppearance']['dynamic']['taxonomies'];
874
- $dynamicTaxonomiesSettingsOG = $this->options['social']['facebook']['general']['dynamic']['taxonomies'];
875
- $dynamicArchiveSettings = $this->options['searchAppearance']['dynamic']['archives'];
876
-
877
  // Refactor options.
878
- $this->options = array_replace_recursive(
879
- $this->options,
880
- $this->addValueToValuesArray( $this->options, $options, [], true )
 
881
  );
882
 
883
- // Post Types.
884
- $postTypes = aioseo()->helpers->getPublicPostTypes();
885
- foreach ( $dynamicPostTypeSettings as $postTypeName => $postTypeData ) {
886
- foreach ( $postTypes as $postType ) {
887
- if ( 'type' === $postType['name'] ) {
888
- $postType['name'] = '_aioseo_type';
889
- }
890
-
891
- // If the option has disappeared, we want to save the settings manually.
892
- if ( $postTypeName === $postType['name'] ) {
893
- continue 2;
894
- }
895
- }
896
-
897
- $this->options['internal']['searchAppearanceDynamicBackup']['postTypes']['value'][ $postTypeName ] = $postTypeData;
898
- }
899
- foreach ( $dynamicPostTypeSettingsOG as $postTypeName => $postTypeData ) {
900
- foreach ( $postTypes as $postType ) {
901
- if ( 'type' === $postType['name'] ) {
902
- $postType['name'] = '_aioseo_type';
903
- }
904
-
905
- // If the option has disappeared, we want to save the settings manually.
906
- if ( $postTypeName === $postType['name'] ) {
907
- continue 2;
908
- }
909
- }
910
-
911
- $this->options['internal']['socialFacebookDynamicBackup']['postTypes']['value'][ $postTypeName ] = $postTypeData;
912
- }
913
-
914
- // Taxonomies.
915
- $taxonomies = aioseo()->helpers->getPublicTaxonomies();
916
- foreach ( $dynamicTaxonomiesSettings as $taxonomyName => $taxonomyData ) {
917
- foreach ( $taxonomies as $taxonomy ) {
918
- if ( 'type' === $taxonomy['name'] ) {
919
- $taxonomy['name'] = '_aioseo_type';
920
- }
921
-
922
- // If the option has disappeared, we want to save the settings manually.
923
- if ( $taxonomyName === $taxonomy['name'] ) {
924
- continue 2;
925
- }
926
- }
927
-
928
- $this->options['internal']['searchAppearanceDynamicBackup']['taxonomies']['value'][ $taxonomyName ] = $taxonomyData;
929
- }
930
- foreach ( $dynamicTaxonomiesSettingsOG as $taxonomyName => $taxonomyData ) {
931
- foreach ( $taxonomies as $taxonomy ) {
932
- // If the option has disappeared, we want to save the settings manually.
933
- if ( $taxonomyName === $taxonomy['name'] ) {
934
- continue 2;
935
- }
936
- }
937
-
938
- $this->options['internal']['socialFacebookDynamicBackup']['taxonomies']['value'][ $taxonomyName ] = $taxonomyData;
939
- }
940
-
941
- // Archives.
942
- $postTypes = aioseo()->helpers->getPublicPostTypes( false, true );
943
- foreach ( $dynamicArchiveSettings as $archiveName => $archiveData ) {
944
- foreach ( $postTypes as $postType ) {
945
- if ( 'type' === $postType['name'] ) {
946
- $postType['name'] = '_aioseo_type';
947
- }
948
-
949
- // If the option has disappeared, we want to save the settings manually.
950
- if ( $archiveName === $postType['name'] ) {
951
- continue 2;
952
- }
953
- }
954
-
955
- $this->options['internal']['searchAppearanceDynamicBackup']['archives']['value'][ $postTypeName ] = $postTypeData;
956
- }
957
-
958
  // The above works for most options, but there are a few that need to be forcibly updated.
959
  if ( $sitemapOptions ) {
960
- $this->options['sitemap']['general']['postTypes']['included']['value'] = $this->sanitizeField( $options['sitemap']['general']['postTypes']['included'], 'array' );
961
- $this->options['sitemap']['general']['taxonomies']['included']['value'] = $this->sanitizeField( $options['sitemap']['general']['taxonomies']['included'], 'array' );
962
- $this->options['sitemap']['general']['additionalPages']['pages']['value'] = $this->sanitizeField( $options['sitemap']['general']['additionalPages']['pages'], 'array' );
963
- $this->options['sitemap']['general']['advancedSettings']['excludePosts']['value'] = $this->sanitizeField( $options['sitemap']['general']['advancedSettings']['excludePosts'], 'array' );
964
- $this->options['sitemap']['general']['advancedSettings']['excludeTerms']['value'] = $this->sanitizeField( $options['sitemap']['general']['advancedSettings']['excludeTerms'], 'array' );
965
- $this->options['sitemap']['rss']['postTypes']['included']['value'] = $this->sanitizeField( $options['sitemap']['rss']['postTypes']['included'], 'array' );
 
 
 
 
966
  }
967
 
968
  // Advanced options.
969
  if ( ! empty( $options['advanced'] ) ) {
970
  if ( isset( $options['advanced']['postTypes']['included'] ) ) {
971
- $this->options['advanced']['postTypes']['included']['value'] = $this->sanitizeField( $options['advanced']['postTypes']['included'], 'array' );
972
  }
973
 
974
  if ( isset( $options['advanced']['taxonomies']['included'] ) ) {
975
- $this->options['advanced']['taxonomies']['included']['value'] = $this->sanitizeField( $options['advanced']['taxonomies']['included'], 'array' );
976
  }
977
  }
978
 
979
  // Tools.
980
  if ( ! empty( $options['tools'] ) ) {
981
  if ( isset( $options['tools']['robots']['rules'] ) ) {
982
- $this->options['tools']['robots']['rules']['value'] = $this->sanitizeField( $options['tools']['robots']['rules'], 'array' );
983
  }
984
  }
985
 
@@ -987,27 +604,44 @@ TEMPLATE
987
  if ( ! empty( $options['deprecated'] ) ) {
988
 
989
  if ( isset( $options['deprecated']['webmasterTools']['googleAnalytics']['excludeUsers'] ) ) {
990
- $this->options['deprecated']['webmasterTools']['googleAnalytics']['excludeUsers']['value'] = $this->sanitizeField( $options['deprecated']['webmasterTools']['googleAnalytics']['excludeUsers'], 'array' ); // phpcs:ignore Generic.Files.LineLength.MaxExceeded
991
  }
992
  if ( isset( $options['deprecated']['searchAppearance']['advanced']['excludePosts'] ) ) {
993
- $this->options['deprecated']['searchAppearance']['advanced']['excludePosts']['value'] = $this->sanitizeField( $options['deprecated']['searchAppearance']['advanced']['excludePosts'], 'array' ); // phpcs:ignore Generic.Files.LineLength.MaxExceeded
994
  }
995
 
996
  if ( isset( $options['deprecated']['searchAppearance']['advanced']['excludeTerms'] ) ) {
997
- $this->options['deprecated']['searchAppearance']['advanced']['excludeTerms']['value'] = $this->sanitizeField( $options['deprecated']['searchAppearance']['advanced']['excludeTerms'], 'array' ); // phpcs:ignore Generic.Files.LineLength.MaxExceeded
998
  }
999
  }
1000
 
1001
  // Social networks.
1002
  if ( isset( $options['social']['profiles']['sameUsername']['included'] ) ) {
1003
- $this->options['social']['profiles']['sameUsername']['included']['value'] = $this->sanitizeField( $options['social']['profiles']['sameUsername']['included'], 'array' );
1004
  }
1005
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1006
  // Update localized options.
1007
  update_option( $this->optionsName . '_localized', $this->localized );
1008
 
1009
  // Update values.
1010
- $this->update();
1011
 
1012
  // If phone settings have changed, let's see if we need to dump the phone number notice.
1013
  if (
@@ -1036,6 +670,9 @@ TEMPLATE
1036
  aioseo()->sitemap->scheduleRegeneration();
1037
  }
1038
  }
 
 
 
1039
  }
1040
 
1041
  /**
1
  <?php
2
+ namespace AIOSEO\Plugin\Common\Options;
3
 
4
  // Exit if accessed directly.
5
  if ( ! defined( 'ABSPATH' ) ) {
17
  class Options {
18
  use Traits\Options;
19
 
 
 
 
 
 
 
 
 
 
20
  /**
21
  * All the default options.
22
  *
26
  */
27
  protected $defaults = [
28
  // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
29
+ 'internal' => [],
 
 
 
 
 
 
 
 
 
30
  'webmasterTools' => [
31
  'google' => [ 'type' => 'string' ],
32
  'bing' => [ 'type' => 'string' ],
43
  'homepageLink' => [ 'type' => 'boolean', 'default' => true ],
44
  'homepageLabel' => [ 'type' => 'string', 'default' => 'Home' ],
45
  'breadcrumbPrefix' => [ 'type' => 'string' ],
46
+ 'archiveFormat' => [ 'type' => 'string', 'default' => 'Archives for #breadcrumb_archive_post_type_name', 'localized' => true ],
47
+ 'searchResultFormat' => [ 'type' => 'string', 'default' => 'Search for \'#breadcrumb_search_string\'', 'localized' => true ],
48
+ 'errorFormat404' => [ 'type' => 'string', 'default' => '404 Error: page not found', 'localized' => true ],
49
  'showCurrentItem' => [ 'type' => 'boolean', 'default' => true ],
50
  'linkCurrentItem' => [ 'type' => 'boolean', 'default' => false ],
51
  'categoryFullHierarchy' => [ 'type' => 'boolean', 'default' => false ],
138
  'included' => [ 'type' => 'array', 'default' => [ 'post', 'page', 'product' ] ],
139
  ]
140
  ],
141
+ 'html' => [
142
+ 'enable' => [ 'type' => 'boolean', 'default' => true ],
143
+ 'pageUrl' => [ 'type' => 'string', 'default' => '' ],
144
+ 'postTypes' => [
145
+ 'all' => [ 'type' => 'boolean', 'default' => true ],
146
+ 'included' => [ 'type' => 'array', 'default' => [ 'post', 'page', 'product' ] ],
147
+ ],
148
+ 'taxonomies' => [
149
+ 'all' => [ 'type' => 'boolean', 'default' => true ],
150
+ 'included' => [ 'type' => 'array', 'default' => [ 'category', 'post_tag', 'product_cat', 'product_tag' ] ],
151
+ ],
152
+ 'sortOrder' => [ 'type' => 'string', 'default' => 'publish_date' ],
153
+ 'sortDirection' => [ 'type' => 'string', 'default' => 'asc' ],
154
+ 'publicationDate' => [ 'type' => 'boolean', 'default' => true ],
155
+ 'compactArchives' => [ 'type' => 'boolean', 'default' => false ],
156
+ 'advancedSettings' => [
157
+ 'enable' => [ 'type' => 'boolean', 'default' => false ],
158
+ 'nofollowLinks' => [ 'type' => 'boolean', 'default' => false ],
159
+ 'excludePosts' => [ 'type' => 'array', 'default' => [] ],
160
+ 'excludeTerms' => [ 'type' => 'array', 'default' => [] ]
161
  ]
162
+ ],
163
  ],
164
  'social' => [
165
  'profiles' => [
193
  'defaultImagePostsWidth' => [ 'type' => 'number', 'default' => '' ],
194
  'defaultImagePostsHeight' => [ 'type' => 'number', 'default' => '' ],
195
  'showAuthor' => [ 'type' => 'boolean', 'default' => true ],
196
+ 'siteName' => [ 'type' => 'string', 'localized' => true, 'default' => '#site_title #separator_sa #tagline' ]
 
 
 
 
 
197
  ],
198
  'homePage' => [
199
  'image' => [ 'type' => 'string', 'default' => '' ],
276
  'useCategoriesForMetaKeywords' => [ 'type' => 'boolean', 'default' => false ],
277
  'useTagsForMetaKeywords' => [ 'type' => 'boolean', 'default' => false ],
278
  'dynamicallyGenerateKeywords' => [ 'type' => 'boolean', 'default' => false ],
279
+ 'pagedFormat' => [ 'type' => 'string', 'default' => '- Page #page_number', 'localized' => true ]
280
  ],
281
  'archives' => [
282
  'author' => [
351
  'keywords' => [ 'type' => 'string', 'localized' => true ]
352
  ]
353
  ]
 
 
 
 
 
354
  ]
355
  ],
356
  'tools' => [
431
  $this->optionsName = is_network_admin() ? $optionsName . '_network' : $optionsName;
432
 
433
  $this->init();
434
+
435
+ add_action( 'shutdown', [ $this, 'save' ] );
436
  }
437
 
438
  /**
440
  *
441
  * @since 4.0.0
442
  *
 
443
  * @return void
444
  */
445
+ protected function init() {
446
+ $this->setInitialDefaults();
 
 
 
 
 
447
  $this->translateDefaults();
448
 
449
+ $this->setDbOptions();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
 
451
  add_action( 'wp_loaded', [ $this, 'maybeFlushRewriteRules' ] );
452
  }
453
 
454
  /**
455
+ * Sets the DB options to the class after merging in new defaults and dropping unknown values.
456
  *
457
+ * @since 4.0.14
458
  *
459
+ * @return void
460
  */
461
+ public function setDbOptions() {
 
 
 
 
 
 
462
  // Refactor options.
463
  $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->defaultsMerged );
464
 
465
+ $dbOptions = $this->getDbOptions( $this->optionsName );
466
+
467
+ $options = array_replace_recursive(
468
  $this->defaultsMerged,
469
  $this->addValueToValuesArray( $this->defaultsMerged, $dbOptions )
470
  );
 
471
 
472
+ aioseo()->optionsCache->setOptions( $this->optionsName, apply_filters( 'aioseo_get_options', $options ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
 
474
+ // Get the localized options.
475
+ $dbOptionsLocalized = get_option( $this->optionsName . '_localized' );
476
+ if ( empty( $dbOptionsLocalized ) ) {
477
+ $dbOptionsLocalized = [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  }
479
+ $this->localized = $dbOptionsLocalized;
 
480
  }
481
 
482
  /**
483
+ * Sets the initial defaults that can't be defined in the property because of PHP 5.4.
484
  *
485
+ * @since 4.1.4
486
  *
 
 
487
  * @return void
488
  */
489
+ protected function setInitialDefaults() {
490
+ static $hasInitialized = false;
491
+ if ( $hasInitialized ) {
492
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
  }
494
 
495
+ $hasInitialized = true;
 
496
 
497
+ $this->defaults['searchAppearance']['global']['schema']['organizationName']['default'] = aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) );
498
+ $this->defaults['deprecated']['tools']['blocker']['custom']['bots']['default'] = implode( "\n", aioseo()->badBotBlocker->getBotList() );
499
+ $this->defaults['deprecated']['tools']['blocker']['custom']['referer']['default'] = implode( "\n", aioseo()->badBotBlocker->getRefererList() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  }
501
 
502
  /**
507
  * @return void
508
  */
509
  public function translateDefaults() {
510
+ static $hasInitialized = false;
511
+ if ( $hasInitialized ) {
512
+ return;
513
+ }
514
+
515
+ $hasInitialized = true;
516
+
517
  $default = sprintf( '{"label":"%1$s","value":"default"}', __( 'default', 'all-in-one-seo-pack' ) );
518
  $this->defaults['sitemap']['general']['advancedSettings']['priority']['homePage']['priority']['default'] = $default;
519
  $this->defaults['sitemap']['general']['advancedSettings']['priority']['homePage']['frequency']['default'] = $default;
540
  * @return void
541
  */
542
  public function sanitizeAndSave( $options ) {
543
+ $sitemapOptions = ! empty( $options['sitemap']['general'] ) ? $options['sitemap']['general'] : null;
544
  $oldSitemapOptions = aioseo()->options->sitemap->general->all();
545
  $deprecatedSitemapOptions = ! empty( $options['deprecated']['sitemap']['general'] )
546
  ? $options['deprecated']['sitemap']['general']
550
  $phoneNumberOptions = isset( $options['searchAppearance']['global']['schema']['phone'] )
551
  ? $options['searchAppearance']['global']['schema']['phone']
552
  : null;
553
+ $oldHtmlSitemapUrl = $this->sitemap->html->pageUrl;
554
 
555
  $options = $this->maybeRemoveUnfilteredHtmlFields( $options );
556
 
560
  return;
561
  }
562
 
 
 
 
 
 
 
 
563
  // Refactor options.
564
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
565
+ $dbOptions = array_replace_recursive(
566
+ $cachedOptions,
567
+ $this->addValueToValuesArray( $cachedOptions, $options, [], true )
568
  );
569
 
570
+ // TODO: Refactor this into an array since importing old settings imports fail because new settings might not exist in the $options being passed in here. (i.e. 'html' below).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
  // The above works for most options, but there are a few that need to be forcibly updated.
572
  if ( $sitemapOptions ) {
573
+ $dbOptions['sitemap']['general']['postTypes']['included']['value'] = $this->sanitizeField( $options['sitemap']['general']['postTypes']['included'], 'array' );
574
+ $dbOptions['sitemap']['general']['taxonomies']['included']['value'] = $this->sanitizeField( $options['sitemap']['general']['taxonomies']['included'], 'array' );
575
+ $dbOptions['sitemap']['general']['additionalPages']['pages']['value'] = $this->sanitizeField( $options['sitemap']['general']['additionalPages']['pages'], 'array' );
576
+ $dbOptions['sitemap']['general']['advancedSettings']['excludePosts']['value'] = $this->sanitizeField( $options['sitemap']['general']['advancedSettings']['excludePosts'], 'array' );
577
+ $dbOptions['sitemap']['general']['advancedSettings']['excludeTerms']['value'] = $this->sanitizeField( $options['sitemap']['general']['advancedSettings']['excludeTerms'], 'array' );
578
+ $dbOptions['sitemap']['rss']['postTypes']['included']['value'] = $this->sanitizeField( $options['sitemap']['rss']['postTypes']['included'], 'array' );
579
+ $dbOptions['sitemap']['html']['postTypes']['included']['value'] = $this->sanitizeField( $options['sitemap']['html']['postTypes']['included'], 'array' );
580
+ $dbOptions['sitemap']['html']['taxonomies']['included']['value'] = $this->sanitizeField( $options['sitemap']['html']['taxonomies']['included'], 'array' );
581
+ $dbOptions['sitemap']['html']['advancedSettings']['excludePosts']['value'] = $this->sanitizeField( $options['sitemap']['html']['advancedSettings']['excludePosts'], 'array' );
582
+ $dbOptions['sitemap']['html']['advancedSettings']['excludeTerms']['value'] = $this->sanitizeField( $options['sitemap']['html']['advancedSettings']['excludeTerms'], 'array' );
583
  }
584
 
585
  // Advanced options.
586
  if ( ! empty( $options['advanced'] ) ) {
587
  if ( isset( $options['advanced']['postTypes']['included'] ) ) {
588
+ $dbOptions['advanced']['postTypes']['included']['value'] = $this->sanitizeField( $options['advanced']['postTypes']['included'], 'array' );
589
  }
590
 
591
  if ( isset( $options['advanced']['taxonomies']['included'] ) ) {
592
+ $dbOptions['advanced']['taxonomies']['included']['value'] = $this->sanitizeField( $options['advanced']['taxonomies']['included'], 'array' );
593
  }
594
  }
595
 
596
  // Tools.
597
  if ( ! empty( $options['tools'] ) ) {
598
  if ( isset( $options['tools']['robots']['rules'] ) ) {
599
+ $dbOptions['tools']['robots']['rules']['value'] = $this->sanitizeField( $options['tools']['robots']['rules'], 'array' );
600
  }
601
  }
602
 
604
  if ( ! empty( $options['deprecated'] ) ) {
605
 
606
  if ( isset( $options['deprecated']['webmasterTools']['googleAnalytics']['excludeUsers'] ) ) {
607
+ $dbOptions['deprecated']['webmasterTools']['googleAnalytics']['excludeUsers']['value'] = $this->sanitizeField( $options['deprecated']['webmasterTools']['googleAnalytics']['excludeUsers'], 'array' ); // phpcs:ignore Generic.Files.LineLength.MaxExceeded
608
  }
609
  if ( isset( $options['deprecated']['searchAppearance']['advanced']['excludePosts'] ) ) {
610
+ $dbOptions['deprecated']['searchAppearance']['advanced']['excludePosts']['value'] = $this->sanitizeField( $options['deprecated']['searchAppearance']['advanced']['excludePosts'], 'array' ); // phpcs:ignore Generic.Files.LineLength.MaxExceeded
611
  }
612
 
613
  if ( isset( $options['deprecated']['searchAppearance']['advanced']['excludeTerms'] ) ) {
614
+ $dbOptions['deprecated']['searchAppearance']['advanced']['excludeTerms']['value'] = $this->sanitizeField( $options['deprecated']['searchAppearance']['advanced']['excludeTerms'], 'array' ); // phpcs:ignore Generic.Files.LineLength.MaxExceeded
615
  }
616
  }
617
 
618
  // Social networks.
619
  if ( isset( $options['social']['profiles']['sameUsername']['included'] ) ) {
620
+ $dbOptions['social']['profiles']['sameUsername']['included']['value'] = $this->sanitizeField( $options['social']['profiles']['sameUsername']['included'], 'array' );
621
  }
622
 
623
+ $newOptions = ! empty( $options['sitemap']['html'] ) ? $options['sitemap']['html'] : null;
624
+ if ( ! empty( $newOptions ) && $this->sitemap->html->enable ) {
625
+ $newOptions = ! empty( $options['sitemap']['html'] ) ? $options['sitemap']['html'] : null;
626
+
627
+ $pageUrl = wp_parse_url( $newOptions['pageUrl'] );
628
+ $path = ! empty( $pageUrl['path'] ) ? untrailingslashit( $pageUrl['path'] ) : '';
629
+ if ( $path ) {
630
+ $existingPage = get_page_by_path( $path, OBJECT );
631
+ if ( is_object( $existingPage ) ) {
632
+ // If the page exists, don't override the previous URL.
633
+ $options['sitemap']['html']['pageUrl'] = $oldHtmlSitemapUrl;
634
+ }
635
+ }
636
+ }
637
+
638
+ aioseo()->optionsCache->setOptions( $this->optionsName, $dbOptions );
639
+
640
  // Update localized options.
641
  update_option( $this->optionsName . '_localized', $this->localized );
642
 
643
  // Update values.
644
+ $this->save( true );
645
 
646
  // If phone settings have changed, let's see if we need to dump the phone number notice.
647
  if (
670
  aioseo()->sitemap->scheduleRegeneration();
671
  }
672
  }
673
+
674
+ // This is required in order for the Pro options to be refreshed before they save data again.
675
+ $this->refresh();
676
  }
677
 
678
  /**
app/Common/Rss.php CHANGED
@@ -39,8 +39,8 @@ class Rss {
39
  *
40
  * @since 4.0.0
41
  *
42
- * @param string $content The
43
- * @return void
44
  */
45
  public function addRssContent( $content, $type = 'complete' ) {
46
  $content = trim( $content );
39
  *
40
  * @since 4.0.0
41
  *
42
+ * @param string $content The post content.
43
+ * @return string The post content with prepended/appended content.
44
  */
45
  public function addRssContent( $content, $type = 'complete' ) {
46
  $content = trim( $content );
app/Common/Schema/Breadcrumb.php CHANGED
@@ -56,7 +56,7 @@ class Breadcrumb {
56
  'name' => $post->post_title,
57
  'description' => aioseo()->meta->description->getDescription( $post ),
58
  'url' => get_permalink( $post ),
59
- 'type' => aioseo()->helpers->isWooCommerceShopPage() || is_home() ? 'CollectionPage' : $this->getPostGraph()
60
  ]
61
  );
62
 
56
  'name' => $post->post_title,
57
  'description' => aioseo()->meta->description->getDescription( $post ),
58
  'url' => get_permalink( $post ),
59
+ 'type' => aioseo()->helpers->isWooCommerceShopPage( $post->ID ) || is_home() ? 'CollectionPage' : $this->getPostGraph()
60
  ]
61
  );
62
 
app/Common/Schema/Graphs/Article.php CHANGED
@@ -40,6 +40,7 @@ class Article extends Graph {
40
  '@id' => aioseo()->schema->context['url'] . '#article',
41
  'name' => aioseo()->schema->context['name'],
42
  'description' => aioseo()->schema->context['description'],
 
43
  'headline' => $post->post_title,
44
  'author' => [ '@id' => get_author_posts_url( $post->post_author ) . '#author' ],
45
  'publisher' => [ '@id' => trailingslashit( home_url() ) . '#' . aioseo()->options->searchAppearance->global->schema->siteRepresents ],
40
  '@id' => aioseo()->schema->context['url'] . '#article',
41
  'name' => aioseo()->schema->context['name'],
42
  'description' => aioseo()->schema->context['description'],
43
+ 'inLanguage' => aioseo()->helpers->currentLanguageCodeBCP47(),
44
  'headline' => $post->post_title,
45
  'author' => [ '@id' => get_author_posts_url( $post->post_author ) . '#author' ],
46
  'publisher' => [ '@id' => trailingslashit( home_url() ) . '#' . aioseo()->options->searchAppearance->global->schema->siteRepresents ],
app/Common/Schema/Graphs/BreadcrumbList.php CHANGED
@@ -20,8 +20,8 @@ class BreadcrumbList extends Graph {
20
  * @return array $data The graph data.
21
  */
22
  public function get() {
23
- $breadcrumbs = aioseo()->schema->context['breadcrumb'];
24
- if ( ! is_array( $breadcrumbs ) || ! count( $breadcrumbs ) ) {
25
  return [];
26
  }
27
 
20
  * @return array $data The graph data.
21
  */
22
  public function get() {
23
+ $breadcrumbs = isset( aioseo()->schema->context['breadcrumb'] ) ? aioseo()->schema->context['breadcrumb'] : '';
24
+ if ( ! $breadcrumbs || ! count( $breadcrumbs ) ) {
25
  return [];
26
  }
27
 
app/Common/Schema/Graphs/Graph.php CHANGED
@@ -44,17 +44,34 @@ abstract class Graph {
44
 
45
  $metaData = wp_get_attachment_metadata( $attachmentId );
46
  if ( $metaData ) {
47
- $data['width'] = $metaData['width'];
48
- $data['height'] = $metaData['height'];
49
  }
50
 
51
- $caption = wp_get_attachment_caption( $attachmentId );
52
- if ( false !== $caption || ! empty( $caption ) ) {
53
  $data['caption'] = $caption;
54
  }
55
  return $data;
56
  }
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  /**
59
  * Returns the graph data for the avatar of a given user.
60
  *
44
 
45
  $metaData = wp_get_attachment_metadata( $attachmentId );
46
  if ( $metaData ) {
47
+ $data['width'] = (int) $metaData['width'];
48
+ $data['height'] = (int) $metaData['height'];
49
  }
50
 
51
+ $caption = $this->getImageCaption( $attachmentId );
52
+ if ( ! empty( $caption ) ) {
53
  $data['caption'] = $caption;
54
  }
55
  return $data;
56
  }
57
 
58
+ /**
59
+ * Get the image caption.
60
+ *
61
+ * @since 4.1.4
62
+ *
63
+ * @param int $attachmentId The attachment ID.
64
+ * @return string The caption.
65
+ */
66
+ private function getImageCaption( $attachmentId ) {
67
+ $caption = wp_get_attachment_caption( $attachmentId );
68
+ if ( ! empty( $caption ) ) {
69
+ return $caption;
70
+ }
71
+
72
+ return get_post_meta( $attachmentId, '_wp_attachment_image_alt', true );
73
+ }
74
+
75
  /**
76
  * Returns the graph data for the avatar of a given user.
77
  *
app/Common/Schema/Graphs/WebPage.php CHANGED
@@ -38,14 +38,18 @@ class WebPage extends Graph {
38
  'url' => aioseo()->schema->context['url'],
39
  'name' => aioseo()->meta->title->getTitle(),
40
  'description' => aioseo()->schema->context['description'],
41
- 'inLanguage' => get_bloginfo( 'language' ),
42
  'isPartOf' => [ '@id' => $homeUrl . '#website' ],
43
  'breadcrumb' => [ '@id' => aioseo()->schema->context['url'] . '#breadcrumblist' ]
44
  ];
45
 
46
  if ( is_singular() && ! is_page() ) {
47
- $data['author'] = aioseo()->schema->context['url'] . '#author';
48
- $data['creator'] = aioseo()->schema->context['url'] . '#author';
 
 
 
 
49
  }
50
 
51
  if ( isset( aioseo()->schema->context['description'] ) && aioseo()->schema->context['description'] ) {
38
  'url' => aioseo()->schema->context['url'],
39
  'name' => aioseo()->meta->title->getTitle(),
40
  'description' => aioseo()->schema->context['description'],
41
+ 'inLanguage' => aioseo()->helpers->currentLanguageCodeBCP47(),
42
  'isPartOf' => [ '@id' => $homeUrl . '#website' ],
43
  'breadcrumb' => [ '@id' => aioseo()->schema->context['url'] . '#breadcrumblist' ]
44
  ];
45
 
46
  if ( is_singular() && ! is_page() ) {
47
+ $post = aioseo()->helpers->getPost();
48
+ $author = get_author_posts_url( $post->post_author );
49
+ if ( ! empty( $author ) ) {
50
+ $data['author'] = $author . '#author';
51
+ $data['creator'] = $author . '#author';
52
+ }
53
  }
54
 
55
  if ( isset( aioseo()->schema->context['description'] ) && aioseo()->schema->context['description'] ) {
app/Common/Schema/Graphs/WebSite.php CHANGED
@@ -27,13 +27,17 @@ class WebSite extends Graph {
27
  'url' => $homeUrl,
28
  'name' => aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) ),
29
  'description' => aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'description' ) ),
 
30
  'publisher' => [ '@id' => $homeUrl . '#' . aioseo()->options->searchAppearance->global->schema->siteRepresents ]
31
  ];
32
 
33
  if ( is_front_page() && aioseo()->options->searchAppearance->advanced->sitelinks ) {
34
  $data['potentialAction'] = [
35
  '@type' => 'SearchAction',
36
- 'target' => $homeUrl . '?s={search_term_string}',
 
 
 
37
  'query-input' => 'required name=search_term_string',
38
  ];
39
  }
27
  'url' => $homeUrl,
28
  'name' => aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) ),
29
  'description' => aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'description' ) ),
30
+ 'inLanguage' => aioseo()->helpers->currentLanguageCodeBCP47(),
31
  'publisher' => [ '@id' => $homeUrl . '#' . aioseo()->options->searchAppearance->global->schema->siteRepresents ]
32
  ];
33
 
34
  if ( is_front_page() && aioseo()->options->searchAppearance->advanced->sitelinks ) {
35
  $data['potentialAction'] = [
36
  '@type' => 'SearchAction',
37
+ 'target' => [
38
+ '@type' => 'EntryPoint',
39
+ 'urlTemplate' => $homeUrl . '?s={search_term_string}'
40
+ ],
41
  'query-input' => 'required name=search_term_string',
42
  ];
43
  }
app/Common/Schema/Schema.php CHANGED
@@ -104,6 +104,7 @@ class Schema {
104
  }
105
  }
106
 
 
107
  $schema['@graph'] = array_values( $this->cleanData( $schema['@graph'] ) );
108
 
109
  return isset( $_GET['aioseo-dev'] ) ? wp_json_encode( $schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) : wp_json_encode( $schema );
@@ -204,8 +205,8 @@ class Schema {
204
  * @return string|array The graph name(s).
205
  */
206
  public function getPostGraphs( $post = null ) {
207
- $post = is_object( $post ) ? $post : aioseo()->helpers->getPost();
208
- $options = aioseo()->options->noConflict();
209
 
210
  $schemaType = 'default';
211
  $schemaTypeOptions = '';
@@ -218,18 +219,18 @@ class Schema {
218
  }
219
 
220
  // Get global settings if set to default.
221
- if ( 'default' === $schemaType && $options->searchAppearance->dynamic->postTypes->has( $post->post_type ) ) {
222
- $schemaType = $options->searchAppearance->dynamic->postTypes->{$post->post_type}->schemaType;
223
  }
224
 
225
  switch ( $schemaType ) {
226
  case 'WebPage':
227
  $webPageGraph = ! empty( $metaData->schema_type ) && 'default' !== $metaData->schema_type ? $schemaTypeOptions->webPage->webPageType :
228
- $options->searchAppearance->dynamic->postTypes->{$post->post_type}->webPageType;
229
  return ucfirst( $webPageGraph );
230
  case 'Article':
231
  $articleGraph = ! empty( $metaData->schema_type ) && 'default' !== $metaData->schema_type ? $schemaTypeOptions->article->articleType :
232
- $options->searchAppearance->dynamic->postTypes->{$post->post_type}->articleType;
233
  return [ 'WebPage', ucfirst( $articleGraph ) ];
234
  case 'none':
235
  return '';
@@ -259,7 +260,7 @@ class Schema {
259
  if ( is_array( $v ) ) {
260
  $v = $this->cleanData( $v );
261
  } else {
262
- $v = trim( wp_strip_all_tags( $v ) );
263
  }
264
 
265
  if ( empty( $v ) && ! in_array( $k, $this->nullableFields, true ) ) {
104
  }
105
  }
106
 
107
+ $schema['@graph'] = apply_filters( 'aioseo_schema_output', $schema['@graph'] );
108
  $schema['@graph'] = array_values( $this->cleanData( $schema['@graph'] ) );
109
 
110
  return isset( $_GET['aioseo-dev'] ) ? wp_json_encode( $schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) : wp_json_encode( $schema );
205
  * @return string|array The graph name(s).
206
  */
207
  public function getPostGraphs( $post = null ) {
208
+ $post = is_object( $post ) ? $post : aioseo()->helpers->getPost();
209
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
210
 
211
  $schemaType = 'default';
212
  $schemaTypeOptions = '';
219
  }
220
 
221
  // Get global settings if set to default.
222
+ if ( 'default' === $schemaType && $dynamicOptions->searchAppearance->postTypes->has( $post->post_type ) ) {
223
+ $schemaType = $dynamicOptions->searchAppearance->postTypes->{$post->post_type}->schemaType;
224
  }
225
 
226
  switch ( $schemaType ) {
227
  case 'WebPage':
228
  $webPageGraph = ! empty( $metaData->schema_type ) && 'default' !== $metaData->schema_type ? $schemaTypeOptions->webPage->webPageType :
229
+ $dynamicOptions->searchAppearance->postTypes->{$post->post_type}->webPageType;
230
  return ucfirst( $webPageGraph );
231
  case 'Article':
232
  $articleGraph = ! empty( $metaData->schema_type ) && 'default' !== $metaData->schema_type ? $schemaTypeOptions->article->articleType :
233
+ $dynamicOptions->searchAppearance->postTypes->{$post->post_type}->articleType;
234
  return [ 'WebPage', ucfirst( $articleGraph ) ];
235
  case 'none':
236
  return '';
260
  if ( is_array( $v ) ) {
261
  $v = $this->cleanData( $v );
262
  } else {
263
+ $v = is_int( $v ) ? $v : trim( wp_strip_all_tags( $v ) );
264
  }
265
 
266
  if ( empty( $v ) && ! in_array( $k, $this->nullableFields, true ) ) {
app/Common/Sitemap/Content.php CHANGED
@@ -154,6 +154,7 @@ class Content {
154
 
155
  // Override priority/frequency for static homepage.
156
  if ( $isStaticHomepage && $homePageId === $post->ID ) {
 
157
  $entry['changefreq'] = aioseo()->sitemap->priority->frequency( 'homePage' );
158
  $entry['priority'] = aioseo()->sitemap->priority->priority( 'homePage' );
159
  }
@@ -256,9 +257,9 @@ class Content {
256
  $entries = [];
257
  foreach ( aioseo()->sitemap->helpers->includedPostTypes( true ) as $postType ) {
258
  if (
259
- aioseo()->options->noConflict()->searchAppearance->dynamic->archives->has( $postType ) &&
260
- ! aioseo()->options->searchAppearance->dynamic->archives->$postType->advanced->robotsMeta->default &&
261
- aioseo()->options->searchAppearance->dynamic->archives->$postType->advanced->robotsMeta->noindex
262
  ) {
263
  continue;
264
  }
@@ -334,7 +335,7 @@ class Content {
334
  }
335
 
336
  /**
337
- * Adds the last modified date to a given term.
338
  *
339
  * @since 4.0.0
340
  *
@@ -342,8 +343,6 @@ class Content {
342
  * @return string The lastmod timestamp.
343
  */
344
  public function getTermLastModified( $termId ) {
345
- // @TODO: [V4+] Think about checking for excluded/noindexed posts.
346
- // Might be a hit on performance.
347
  $termRelationshipsTable = aioseo()->db->db->prefix . 'term_relationships';
348
  $lastModified = aioseo()->db
349
  ->start( aioseo()->db->db->posts . ' as p', true )
@@ -376,10 +375,11 @@ class Content {
376
  public function addl() {
377
  $entries = [];
378
  if ( 'posts' === get_option( 'show_on_front' ) || ! in_array( 'page', aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
379
- $frontPageId = (int) get_option( 'page_on_front' );
380
- $post = aioseo()->helpers->getPost( $frontPageId );
 
381
  $entries[] = [
382
- 'loc' => aioseo()->helpers->localizedUrl( '/' ),
383
  'lastmod' => $post ? aioseo()->helpers->formatDateTime( $post->post_modified_gmt ) : aioseo()->sitemap->helpers->lastModifiedPostTime(),
384
  'changefreq' => aioseo()->sitemap->priority->frequency( 'homePage' ),
385
  'priority' => aioseo()->sitemap->priority->priority( 'homePage' ),
154
 
155
  // Override priority/frequency for static homepage.
156
  if ( $isStaticHomepage && $homePageId === $post->ID ) {
157
+ $entry['loc'] = aioseo()->helpers->maybeRemoveTrailingSlash( $entry['loc'] );
158
  $entry['changefreq'] = aioseo()->sitemap->priority->frequency( 'homePage' );
159
  $entry['priority'] = aioseo()->sitemap->priority->priority( 'homePage' );
160
  }
257
  $entries = [];
258
  foreach ( aioseo()->sitemap->helpers->includedPostTypes( true ) as $postType ) {
259
  if (
260
+ aioseo()->dynamicOptions->noConflict()->searchAppearance->archives->has( $postType ) &&
261
+ ! aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->default &&
262
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->noindex
263
  ) {
264
  continue;
265
  }
335
  }
336
 
337
  /**
338
+ * Returns the last modified date for a given term.
339
  *
340
  * @since 4.0.0
341
  *
343
  * @return string The lastmod timestamp.
344
  */
345
  public function getTermLastModified( $termId ) {
 
 
346
  $termRelationshipsTable = aioseo()->db->db->prefix . 'term_relationships';
347
  $lastModified = aioseo()->db
348
  ->start( aioseo()->db->db->posts . ' as p', true )
375
  public function addl() {
376
  $entries = [];
377
  if ( 'posts' === get_option( 'show_on_front' ) || ! in_array( 'page', aioseo()->sitemap->helpers->includedPostTypes(), true ) ) {
378
+ $frontPageId = (int) get_option( 'page_on_front' );
379
+ $frontPageUrl = aioseo()->helpers->localizedUrl( '/' );
380
+ $post = aioseo()->helpers->getPost( $frontPageId );
381
  $entries[] = [
382
+ 'loc' => aioseo()->helpers->maybeRemoveTrailingSlash( $frontPageUrl ),
383
  'lastmod' => $post ? aioseo()->helpers->formatDateTime( $post->post_modified_gmt ) : aioseo()->sitemap->helpers->lastModifiedPostTime(),
384
  'changefreq' => aioseo()->sitemap->priority->frequency( 'homePage' ),
385
  'priority' => aioseo()->sitemap->priority->priority( 'homePage' ),
app/Common/Sitemap/Helpers.php CHANGED
@@ -208,10 +208,11 @@ class Helpers {
208
  }
209
 
210
  $options = aioseo()->options->noConflict();
 
211
  $publicPostTypes = aioseo()->helpers->getPublicPostTypes( true, $hasArchivesOnly );
212
  foreach ( $postTypes as $postType ) {
213
  // Check if post type is no longer registered.
214
- if ( ! in_array( $postType, $publicPostTypes, true ) || ! $options->searchAppearance->dynamic->postTypes->has( $postType ) ) {
215
  $postTypes = aioseo()->helpers->unsetValue( $postTypes, $postType );
216
  continue;
217
  }
@@ -225,7 +226,7 @@ class Helpers {
225
  }
226
 
227
  if (
228
- $options->searchAppearance->dynamic->postTypes->$postType->advanced->robotsMeta->default &&
229
  ! $options->searchAppearance->advanced->globalRobotsMeta->default &&
230
  $options->searchAppearance->advanced->globalRobotsMeta->noindex
231
  ) {
@@ -284,10 +285,11 @@ class Helpers {
284
  }
285
 
286
  $options = aioseo()->options->noConflict();
 
287
  $publicTaxonomies = aioseo()->helpers->getPublicTaxonomies( true );
288
  foreach ( $taxonomies as $taxonomy ) {
289
  // Check if taxonomy is no longer registered.
290
- if ( ! in_array( $taxonomy, $publicTaxonomies, true ) || ! $options->searchAppearance->dynamic->taxonomies->has( $taxonomy ) ) {
291
  $taxonomies = aioseo()->helpers->unsetValue( $taxonomies, $taxonomy );
292
  continue;
293
  }
@@ -299,7 +301,7 @@ class Helpers {
299
  }
300
 
301
  if (
302
- $options->searchAppearance->dynamic->taxonomies->$taxonomy->advanced->robotsMeta->default &&
303
  ! $options->searchAppearance->advanced->globalRobotsMeta->default &&
304
  $options->searchAppearance->advanced->globalRobotsMeta->noindex
305
  ) {
@@ -373,9 +375,13 @@ class Helpers {
373
  $type = 'general';
374
  }
375
 
376
- $advanced = aioseo()->options->sitemap->$type->advancedSettings->enable;
377
- $excluded = aioseo()->options->sitemap->$type->advancedSettings->$option;
378
- if ( ! $advanced || null === $excluded || ! count( $excluded ) ) {
 
 
 
 
379
  return '';
380
  }
381
 
@@ -386,6 +392,15 @@ class Helpers {
386
  $ids[] = $object->value;
387
  }
388
  }
 
 
 
 
 
 
 
 
 
389
  return count( $ids ) ? esc_sql( implode( ', ', $ids ) ) : '';
390
  }
391
 
208
  }
209
 
210
  $options = aioseo()->options->noConflict();
211
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
212
  $publicPostTypes = aioseo()->helpers->getPublicPostTypes( true, $hasArchivesOnly );
213
  foreach ( $postTypes as $postType ) {
214
  // Check if post type is no longer registered.
215
+ if ( ! in_array( $postType, $publicPostTypes, true ) || ! $dynamicOptions->searchAppearance->postTypes->has( $postType ) ) {
216
  $postTypes = aioseo()->helpers->unsetValue( $postTypes, $postType );
217
  continue;
218
  }
226
  }
227
 
228
  if (
229
+ $dynamicOptions->searchAppearance->postTypes->$postType->advanced->robotsMeta->default &&
230
  ! $options->searchAppearance->advanced->globalRobotsMeta->default &&
231
  $options->searchAppearance->advanced->globalRobotsMeta->noindex
232
  ) {
285
  }
286
 
287
  $options = aioseo()->options->noConflict();
288
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
289
  $publicTaxonomies = aioseo()->helpers->getPublicTaxonomies( true );
290
  foreach ( $taxonomies as $taxonomy ) {
291
  // Check if taxonomy is no longer registered.
292
+ if ( ! in_array( $taxonomy, $publicTaxonomies, true ) || ! $dynamicOptions->searchAppearance->taxonomies->has( $taxonomy ) ) {
293
  $taxonomies = aioseo()->helpers->unsetValue( $taxonomies, $taxonomy );
294
  continue;
295
  }
301
  }
302
 
303
  if (
304
+ $dynamicOptions->searchAppearance->taxonomies->$taxonomy->advanced->robotsMeta->default &&
305
  ! $options->searchAppearance->advanced->globalRobotsMeta->default &&
306
  $options->searchAppearance->advanced->globalRobotsMeta->noindex
307
  ) {
375
  $type = 'general';
376
  }
377
 
378
+ $hasFilter = has_filter( 'aioseo_sitemap_' . aioseo()->helpers->toSnakeCase( $option ) );
379
+ $advanced = aioseo()->options->sitemap->$type->advancedSettings->enable;
380
+ $excluded = aioseo()->options->sitemap->$type->advancedSettings->$option;
381
+ if (
382
+ ( ! $advanced || empty( $excluded ) ) &&
383
+ ! $hasFilter
384
+ ) {
385
  return '';
386
  }
387
 
392
  $ids[] = $object->value;
393
  }
394
  }
395
+
396
+ if ( 'excludePosts' === $option ) {
397
+ $ids = apply_filters( 'aioseo_sitemap_exclude_posts', $ids, $type );
398
+ }
399
+
400
+ if ( 'excludeTerms' === $option ) {
401
+ $ids = apply_filters( 'aioseo_sitemap_exclude_terms', $ids, $type );
402
+ }
403
+
404
  return count( $ids ) ? esc_sql( implode( ', ', $ids ) ) : '';
405
  }
406
 
app/Common/Sitemap/Html/Block.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Sitemap\Html;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Handles the HTML sitemap block.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class Block extends \AIOSEO\Plugin\Common\Utils\Blocks {
15
+ /**
16
+ * Registers the block.
17
+ *
18
+ * @since 4.1.3
19
+ *
20
+ * @return void
21
+ */
22
+ public function register() {
23
+ register_block_type(
24
+ 'aioseo/html-sitemap', [
25
+ 'attributes' => [
26
+ 'default' => [
27
+ 'type' => 'boolean',
28
+ 'default' => true
29
+ ],
30
+ 'post_types' => [
31
+ 'type' => 'string',
32
+ 'default' => wp_json_encode( [ 'post', 'page' ] )
33
+ ],
34
+ 'post_types_all' => [
35
+ 'type' => 'boolean',
36
+ 'default' => true
37
+ ],
38
+ 'taxonomies' => [
39
+ 'type' => 'string',
40
+ 'default' => wp_json_encode( [ 'category', 'post_tag' ] )
41
+ ],
42
+ 'taxonomies_all' => [
43
+ 'type' => 'boolean',
44
+ 'default' => true
45
+ ],
46
+ 'show_label' => [
47
+ 'type' => 'boolean',
48
+ 'default' => true
49
+ ],
50
+ 'archives' => [
51
+ 'type' => 'boolean',
52
+ 'default' => false
53
+ ],
54
+ 'publication_date' => [
55
+ 'type' => 'boolean',
56
+ 'default' => true
57
+ ],
58
+ 'nofollow_links' => [
59
+ 'type' => 'boolean',
60
+ 'default' => false
61
+ ],
62
+ 'order_by' => [
63
+ 'type' => 'string',
64
+ 'default' => 'publish_date'
65
+ ],
66
+ 'order' => [
67
+ 'type' => 'string',
68
+ 'default' => 'asc'
69
+ ],
70
+ 'excluded_posts' => [
71
+ 'type' => 'string',
72
+ 'default' => wp_json_encode( [] )
73
+ ],
74
+ 'excluded_terms' => [
75
+ 'type' => 'string',
76
+ 'default' => wp_json_encode( [] )
77
+ ],
78
+ 'is_admin' => [
79
+ 'type' => 'boolean',
80
+ 'default' => false
81
+ ]
82
+ ],
83
+ 'render_callback' => [ $this, 'render' ],
84
+ 'editor_style' => 'aioseo-html-sitemap'
85
+ ]
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Renders the block.
91
+ *
92
+ * @since 4.1.3
93
+ *
94
+ * @param array $attributes The attributes.
95
+ * @return string The HTML sitemap code.
96
+ */
97
+ public function render( $attributes ) {
98
+ if ( ! $attributes['default'] ) {
99
+ $jsonFields = [ 'post_types', 'taxonomies', 'excluded_posts', 'excluded_terms' ];
100
+ foreach ( $attributes as $k => $v ) {
101
+ if ( in_array( $k, $jsonFields, true ) ) {
102
+ $attributes[ $k ] = json_decode( $v );
103
+ }
104
+ }
105
+
106
+ $attributes['excluded_posts'] = $this->extractIds( $attributes['excluded_posts'] );
107
+ $attributes['excluded_terms'] = $this->extractIds( $attributes['excluded_terms'] );
108
+
109
+ if ( ! empty( $attributes['post_types_all'] ) ) {
110
+ $attributes['post_types'] = aioseo()->helpers->getPublicPostTypes( true );
111
+ }
112
+ if ( ! empty( $attributes['taxonomies_all'] ) ) {
113
+ $attributes['taxonomies'] = aioseo()->helpers->getPublicTaxonomies( true );
114
+ }
115
+ } else {
116
+ $attributes = [];
117
+ }
118
+
119
+ $attributes = aioseo()->htmlSitemap->frontend->getAttributes( $attributes );
120
+ return aioseo()->htmlSitemap->frontend->output( false, $attributes );
121
+ }
122
+
123
+ /**
124
+ * Extracts the IDs from the excluded objects.
125
+ *
126
+ * @since 4.1.3
127
+ *
128
+ * @param array $objects The objects.
129
+ * @return array The object IDs.
130
+ */
131
+ private function extractIds( $objects ) {
132
+ return array_map( function ( $object ) {
133
+ $object = json_decode( $object );
134
+ return (int) $object->value;
135
+ }, $objects );
136
+ }
137
+ }
app/Common/Sitemap/Html/CompactArchive.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Sitemap\Html;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Handles the Compact Archive's output.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class CompactArchive {
15
+ /**
16
+ * The shortcode attributes.
17
+ *
18
+ * @since 4.1.3
19
+ *
20
+ * @var array
21
+ */
22
+ private $attributes;
23
+
24
+ /**
25
+ * Outputs the compact archives sitemap.
26
+ *
27
+ * @since 4.1.3
28
+ *
29
+ * @param array $attributes The shortcode attributes.
30
+ * @param boolean $echo Whether the HTML code should be printed or returned.
31
+ * @return string The HTML for the compact archive.
32
+ */
33
+ public function output( $attributes, $echo = true ) {
34
+ $dateArchives = ( new Query )->archives();
35
+ $this->attributes = $attributes;
36
+
37
+ if ( 'asc' === strtolower( $this->attributes['order'] ) ) {
38
+ $dateArchives = array_reverse( $dateArchives, true );
39
+ }
40
+
41
+ $data = [
42
+ 'dateArchives' => $dateArchives,
43
+ 'lines' => ''
44
+ ];
45
+ foreach ( $dateArchives as $year => $months ) {
46
+ $data['lines'] .= $this->generateYearLine( $year, $months ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
47
+ }
48
+
49
+ ob_start();
50
+ aioseo()->templates->getTemplate( 'sitemap/html/compact-archive.php', $data );
51
+ $output = ob_get_clean();
52
+
53
+ if ( $echo ) {
54
+ echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
55
+ }
56
+ return $output;
57
+ }
58
+ // phpcs:enable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
59
+
60
+ /**
61
+ * Generates the HTML for a year line.
62
+ *
63
+ * @since 4.1.3
64
+ *
65
+ * @param int The year archive.
66
+ * @param array The month archives for the current year.
67
+ * @return string The HTML code for the year.
68
+ */
69
+ protected function generateYearLine( $year, $months ) {
70
+ $html = '<li><strong><a href="' . get_year_link( $year ) . '">' . esc_html( $year ) . '</a>: </strong> ';
71
+
72
+ for ( $month = 1; $month <= 12; $month++ ) {
73
+ $html .= $this->generateMonth( $year, $months, $month );
74
+ }
75
+
76
+ $html .= '</li>' . "\n";
77
+ return wp_kses_post( $html );
78
+ }
79
+
80
+ /**
81
+ * Generates the HTML for a month.
82
+ *
83
+ * @since 4.1.3
84
+ *
85
+ * @param int $year The year archive.
86
+ * @param array $months All month archives for the current year.
87
+ * @param int $month The month archive.
88
+ * @return string The HTML code for the month.
89
+ */
90
+ public function generateMonth( $year, $months, $month ) {
91
+ $hasPosts = isset( $months[ $month ] );
92
+ $dummyDate = strtotime( "2009/${month}/25" );
93
+ $monthAbbrevation = date_i18n( 'M', $dummyDate );
94
+
95
+ $html = '<span class="aioseo-empty-month">' . esc_html( $monthAbbrevation ) . '</span> ';
96
+ if ( $hasPosts ) {
97
+ $noFollow = filter_var( $this->attributes['nofollow_links'], FILTER_VALIDATE_BOOLEAN );
98
+ $html = sprintf(
99
+ '<a href="%1$s" title="%2$s"%3$s>%4$s</a> ',
100
+ get_month_link( $year, $month ),
101
+ esc_attr( date_i18n( 'F Y', $dummyDate ) ),
102
+ $noFollow ? ' rel="nofollow"' : '',
103
+ esc_html( $monthAbbrevation )
104
+ );
105
+ }
106
+ return $html;
107
+ }
108
+ }
app/Common/Sitemap/Html/Frontend.php ADDED
@@ -0,0 +1,498 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Sitemap\Html;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Handles the output of the HTML sitemap.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class Frontend {
15
+ /**
16
+ * Instance of Query class.
17
+ *
18
+ * @since 4.1.3
19
+ *
20
+ * @var Query
21
+ */
22
+ public $query;
23
+
24
+ /**
25
+ * The attributes for the block/widget/shortcode.
26
+ *
27
+ * @since 4.1.3
28
+ *
29
+ * @var array
30
+ */
31
+ private $attributes = [];
32
+
33
+ /**
34
+ * Class constructor.
35
+ *
36
+ * @since 4.1.3
37
+ */
38
+ public function __construct() {
39
+ $this->query = new Query;
40
+ }
41
+
42
+ /**
43
+ * Returns the attributes.
44
+ *
45
+ * @since 4.1.3
46
+ *
47
+ * @param array $attributes The user-defined attributes
48
+ * @return array The defaults with user-defined attributes merged.
49
+ */
50
+ public function getAttributes( $attributes = [] ) {
51
+ aioseo()->sitemap->type = 'html';
52
+
53
+ $defaults = [
54
+ 'label_tag' => 'h4',
55
+ 'show_label' => true,
56
+ 'order' => aioseo()->options->sitemap->html->sortDirection,
57
+ 'order_by' => aioseo()->options->sitemap->html->sortOrder,
58
+ 'nofollow_links' => false,
59
+ 'publication_date' => aioseo()->options->sitemap->html->publicationDate,
60
+ 'archives' => aioseo()->options->sitemap->html->compactArchives,
61
+ 'post_types' => aioseo()->sitemap->helpers->includedPostTypes(),
62
+ 'taxonomies' => aioseo()->sitemap->helpers->includedTaxonomies(),
63
+ 'excluded_posts' => [],
64
+ 'excluded_terms' => [],
65
+ 'is_admin' => false
66
+ ];
67
+
68
+ $attributes = shortcode_atts( $defaults, $attributes );
69
+ $attributes['show_label'] = filter_var( $attributes['show_label'], FILTER_VALIDATE_BOOLEAN );
70
+ $attributes['nofollow_links'] = filter_var( $attributes['nofollow_links'], FILTER_VALIDATE_BOOLEAN );
71
+ $attributes['is_admin'] = filter_var( $attributes['is_admin'], FILTER_VALIDATE_BOOLEAN );
72
+ return $attributes;
73
+ }
74
+
75
+ /**
76
+ * Formats the publish date according to what's set under Settings > General.
77
+ *
78
+ * @since 4.1.3
79
+ *
80
+ * @param string $date The date that should be formatted.
81
+ * @return string The formatted date.
82
+ */
83
+ private function formatDate( $date ) {
84
+ $dateFormat = apply_filters( 'aioseo_html_sitemap_date_format', get_option( 'date_format' ) );
85
+ return date_i18n( $dateFormat, strtotime( $date ) );
86
+ }
87
+
88
+ /**
89
+ * Returns the posts of a given post type that should be included.
90
+ *
91
+ * @since 4.1.3
92
+ *
93
+ * @param string $postType The post type.
94
+ * @param array $additionalArgs Additional arguments for the post query (optional).
95
+ * @return array The post entries.
96
+ */
97
+ private function posts( $postType, $additionalArgs = [] ) {
98
+ $posts = $this->query->posts( $postType, $additionalArgs );
99
+ if ( ! $posts ) {
100
+ return [];
101
+ }
102
+
103
+ $entries = [];
104
+ foreach ( $posts as $post ) {
105
+ $entry = [
106
+ 'id' => $post->ID,
107
+ 'title' => $post->post_title,
108
+ 'loc' => get_permalink( $post->ID ),
109
+ 'date' => $this->formatDate( $post->post_date_gmt ),
110
+ 'parent' => ! empty( $post->post_parent ) ? $post->post_parent : null
111
+ ];
112
+
113
+ $entries[] = $entry;
114
+ }
115
+
116
+ return $entries;
117
+ }
118
+
119
+ /**
120
+ * Returns the terms of a given taxonomy that should be included.
121
+ *
122
+ * @since 4.1.3
123
+ *
124
+ * @param string $taxonomy The taxonomy name.
125
+ * @param array $additionalArgs Additional arguments for the query (optional).
126
+ * @return array The term entries.
127
+ */
128
+ private function terms( $taxonomy, $additionalArgs = [] ) {
129
+ $terms = $this->query->terms( $taxonomy, $additionalArgs );
130
+ if ( ! $terms ) {
131
+ return [];
132
+ }
133
+
134
+ $entries = [];
135
+ foreach ( $terms as $term ) {
136
+ $entries[] = [
137
+ 'id' => $term->term_id,
138
+ 'title' => $term->name,
139
+ 'loc' => get_term_link( $term->term_id ),
140
+ 'parent' => ! empty( $term->parent ) ? $term->parent : null
141
+ ];
142
+ }
143
+
144
+ return $entries;
145
+ }
146
+
147
+ /**
148
+ * Outputs the sitemap to the frontend.
149
+ *
150
+ * @since 4.1.3
151
+ *
152
+ * @param bool $echo Whether the sitemap should be printed to the screen.
153
+ * @param array $attributes The shortcode attributes.
154
+ * @return string|void The HTML sitemap.
155
+ */
156
+ public function output( $echo = true, $attributes = [] ) {
157
+ if ( ! aioseo()->options->sitemap->html->enable ) {
158
+ return;
159
+ }
160
+
161
+ aioseo()->sitemap->type = 'html';
162
+ if ( filter_var( $attributes['archives'], FILTER_VALIDATE_BOOLEAN ) ) {
163
+ return ( new CompactArchive() )->output( $attributes, $echo );
164
+ }
165
+
166
+ if ( ! empty( $attributes['default'] ) ) {
167
+ $attributes = $this->getAttributes();
168
+ }
169
+
170
+ // Setting this allows us to use the helper functions of the general sitemap.
171
+ $this->attributes = $attributes;
172
+
173
+ if ( empty( $this->attributes['post_types'] ) && empty( $this->attributes['taxonomies'] ) ) {
174
+ $message = esc_html__( 'No posts/terms could be found.', 'all-in-one-seo-pack' );
175
+ if ( $echo ) {
176
+ echo $message; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
177
+ }
178
+ return $message;
179
+ }
180
+
181
+ // TODO: Consider moving all remaining HTML code below to a dedicated view instead of printing it in PHP.
182
+ $sitemap = sprintf(
183
+ '<div class="aioseo-html-sitemap%s">',
184
+ ! $this->attributes['show_label'] ? ' labels-hidden' : ''
185
+ );
186
+
187
+ $sitemap .= '<style>.aioseo-html-sitemap.labels-hidden ul { margin: 0; }</style>';
188
+
189
+ $postTypes = $this->getIncludedObjects( $this->attributes['post_types'] );
190
+ foreach ( $postTypes as $postType ) {
191
+ if ( 'attachment' === $postType ) {
192
+ continue;
193
+ }
194
+
195
+ // Check if post type is still registered.
196
+ if ( ! in_array( $postType, aioseo()->helpers->getPublicPostTypes( true ), true ) ) {
197
+ continue;
198
+ }
199
+
200
+ $posts = $this->posts( $postType, $attributes );
201
+ if ( empty( $posts ) ) {
202
+ continue;
203
+ }
204
+
205
+ $postTypeObject = get_post_type_object( $postType );
206
+ $label = ! empty( $postTypeObject->label ) ? $postTypeObject->label : ucfirst( $postType );
207
+
208
+ $sitemap .= '<div class="aioseo-html-' . esc_attr( $postType ) . '-sitemap">';
209
+ $sitemap .= $this->generateLabel( $label );
210
+
211
+ if ( is_post_type_hierarchical( $postType ) ) {
212
+ $sitemap .= $this->generateHierarchicalList( $posts ) . '</div>';
213
+ if ( $this->attributes['show_label'] ) {
214
+ $sitemap .= '<br />';
215
+ }
216
+ continue;
217
+ }
218
+
219
+ $sitemap .= $this->generateList( $posts );
220
+ if ( $this->attributes['show_label'] ) {
221
+ $sitemap .= '<br />';
222
+ }
223
+ }
224
+
225
+ $taxonomies = $this->getIncludedObjects( $this->attributes['taxonomies'], false );
226
+ foreach ( $taxonomies as $taxonomy ) {
227
+ // Check if post type is still registered.
228
+ if ( ! in_array( $taxonomy, aioseo()->helpers->getPublicTaxonomies( true ), true ) ) {
229
+ continue;
230
+ }
231
+
232
+ $terms = $this->terms( $taxonomy, $attributes );
233
+ if ( empty( $terms ) ) {
234
+ continue;
235
+ }
236
+
237
+ $taxonomyObject = get_taxonomy( $taxonomy );
238
+ $label = ! empty( $taxonomyObject->label ) ? $taxonomyObject->label : ucfirst( $taxonomy );
239
+
240
+ $sitemap .= '<div class="aioseo-html-' . esc_attr( $taxonomy ) . '-sitemap">';
241
+ $sitemap .= $this->generateLabel( $label );
242
+
243
+ if ( is_taxonomy_hierarchical( $taxonomy ) ) {
244
+ $sitemap .= $this->generateHierarchicalList( $terms ) . '</div>';
245
+ if ( $this->attributes['show_label'] ) {
246
+ $sitemap .= '<br />';
247
+ }
248
+ continue;
249
+ }
250
+
251
+ $sitemap .= $this->generateList( $terms );
252
+ if ( $this->attributes['show_label'] ) {
253
+ $sitemap .= '<br />';
254
+ }
255
+ }
256
+
257
+ $sitemap .= '</div>';
258
+
259
+ if ( $echo ) {
260
+ echo $sitemap; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
261
+ }
262
+ return $sitemap;
263
+ }
264
+
265
+ /**
266
+ * Generates the label for a section of the sitemap.
267
+ *
268
+ * @since 4.1.3
269
+ *
270
+ * @param string $label The label.
271
+ * @return string The HTML code for the label.
272
+ */
273
+ private function generateLabel( $label ) {
274
+ $labelTag = ! empty( $this->attributes['label_tag'] ) ? $this->attributes['label_tag'] : 'h4';
275
+ return $this->attributes['show_label']
276
+ ? sprintf( '<%2$s>%1$s</%2$s>', esc_attr( $label ), wp_kses_post( $labelTag ) )
277
+ : '';
278
+ }
279
+
280
+ /**
281
+ * Generates the HTML for a non-hierarchical list of objects.
282
+ *
283
+ * @since 4.1.3
284
+ *
285
+ * @param array $objects The object.
286
+ * @return string The HTML code.
287
+ */
288
+ private function generateList( $objects ) {
289
+ $list = '<ul>';
290
+ foreach ( $objects as $object ) {
291
+ $list .= $this->generateListItem( $object ) . '</li>';
292
+ }
293
+ return $list . '</ul></div>';
294
+ }
295
+
296
+ /**
297
+ * Generates a list item for an object (without the closing tag).
298
+ * We cannot close it as the caller might need to generate a hierarchical structure inside the list item.
299
+ *
300
+ * @since 4.1.3
301
+ *
302
+ * @param array $objects The object.
303
+ * @return string The HTML code.
304
+ */
305
+ private function generateListItem( $object ) {
306
+ $li = '';
307
+ if ( ! empty( $object['title'] ) ) {
308
+ $li .= '<li>';
309
+
310
+ // add nofollow to the link.
311
+ if ( filter_var( $this->attributes['nofollow_links'], FILTER_VALIDATE_BOOLEAN ) ) {
312
+ $li .= sprintf(
313
+ '<a href="%1$s" %2$s %3$s>',
314
+ esc_url( $object['loc'] ),
315
+ 'rel="nofollow"',
316
+ $this->attributes['is_admin'] ? 'target="_blank"' : ''
317
+ );
318
+ } else {
319
+ $li .= sprintf(
320
+ '<a href="%1$s" %2$s>',
321
+ esc_url( $object['loc'] ),
322
+ $this->attributes['is_admin'] ? 'target="_blank"' : ''
323
+ );
324
+ }
325
+
326
+ $li .= sprintf( '%s', esc_attr( $object['title'] ) );
327
+
328
+ // add publication date on the list item.
329
+ if ( ! empty( $object['date'] ) && filter_var( $this->attributes['publication_date'], FILTER_VALIDATE_BOOLEAN ) ) {
330
+ $li .= sprintf( ' (%s)', esc_attr( $object['date'] ) );
331
+ }
332
+
333
+ $li .= '</a>';
334
+ }
335
+ return $li;
336
+ }
337
+
338
+ /**
339
+ * Generates the HTML for a hierarchical list of objects.
340
+ *
341
+ * @since 4.1.3
342
+ *
343
+ * @param array $objects The objects.
344
+ * @return string The HTML of the hierarchical objects section.
345
+ */
346
+ private function generateHierarchicalList( $objects ) {
347
+ if ( empty( $objects ) ) {
348
+ return '';
349
+ }
350
+
351
+ $objects = $this->buildHierarchicalTree( $objects );
352
+
353
+ $list = '<ul>';
354
+ foreach ( $objects as $object ) {
355
+ $list .= $this->generateListItem(
356
+ $object,
357
+ [
358
+ 'publication_date' => $this->attributes['publication_date'],
359
+ 'nofollow_links' => $this->attributes['nofollow_links']
360
+ ]
361
+ );
362
+
363
+ if ( ! empty( $object['children'] ) ) {
364
+ $list .= $this->generateHierarchicalTree( $object );
365
+ }
366
+ $list .= '</li>';
367
+ }
368
+ $list .= '</ul>';
369
+ return $list;
370
+ }
371
+
372
+ /**
373
+ * Recursive helper function for generateHierarchicalList().
374
+ * Generates hierarchical structure for objects with child objects.
375
+ *
376
+ * @since 4.1.3
377
+ *
378
+ * @param array $object The object.
379
+ * @return string The HTML code of the hierarchical tree.
380
+ */
381
+ private function generateHierarchicalTree( $object ) {
382
+ static $nestedLevel = 0;
383
+
384
+ $tree = '<ul>';
385
+ foreach ( $object['children'] as $child ) {
386
+ $nestedLevel++;
387
+ $tree .= $this->generateListItem(
388
+ $child,
389
+ [
390
+ 'publication_date' => $this->attributes['publication_date'],
391
+ 'nofollow_links' => $this->attributes['nofollow_links']
392
+ ]
393
+ );
394
+ if ( ! empty( $child['children'] ) ) {
395
+ $tree .= $this->generateHierarchicalTree( $child );
396
+ }
397
+
398
+ // Because the list is closed off after the loop ends, we must keep track of the nest level so that all nested lists are closed.
399
+ for ( $i = 0; $i < $nestedLevel; $i++ ) {
400
+ $tree .= '</ul>';
401
+ $nestedLevel--;
402
+ }
403
+ }
404
+ return $tree;
405
+ }
406
+
407
+ /**
408
+ * Builds the structure for hierarchical objects that have a parent.
409
+ *
410
+ * @since 4.1.3
411
+ *
412
+ * @param array $objects The list of hierarchical objects.
413
+ * @param int $parent ID of the parent node.
414
+ * @return array Multidimensional array with the hierarchical structure.
415
+ */
416
+ private function buildHierarchicalTree( $objects ) {
417
+ $objects = json_decode( wp_json_encode( $objects ) );
418
+ foreach ( $objects as $index => $child ) {
419
+ if ( $child->parent ) {
420
+ foreach ( $objects as $parent ) {
421
+ // Find the parent among the other objects.
422
+ if ( (int) $child->parent === (int) $parent->id ) {
423
+ $parent->children[] = $child;
424
+ unset( $objects[ $index ] );
425
+ continue 2;
426
+ }
427
+ // If one of the objects already has children, try to recursively find the parent for the current child among those children.
428
+ if ( ! empty( $parent->children ) ) {
429
+ list( $children, $found ) = $this->findParentAmongChildren( $parent->children, $child );
430
+ if ( $found ) {
431
+ $parent->children = $children;
432
+ unset( $objects[ $index ] );
433
+ continue 2;
434
+ }
435
+ }
436
+ }
437
+ }
438
+ }
439
+ $objects = array_values( json_decode( wp_json_encode( $objects ), true ) );
440
+ return $objects;
441
+ }
442
+
443
+ /**
444
+ * Recursive helper function for buildHierarchicalTree().
445
+ * Finds the parent for child objects whose parent is a child of another object.
446
+ *
447
+ * @since 4.1.3
448
+ *
449
+ * @param array $parentChildren The child objects of the potential parent object.
450
+ * @param array $child The child object.
451
+ * @return array The parent's children + whether the parent was found.
452
+ */
453
+ private function findParentAmongChildren( $parentChildren, $child ) {
454
+ $found = false;
455
+ foreach ( $parentChildren as $parentChild ) {
456
+ if ( (int) $child->parent === (int) $parentChild->id ) {
457
+ $parentChild->children[] = $child;
458
+ $found = true;
459
+ break;
460
+ }
461
+ if ( ! empty( $parentChild->children ) ) {
462
+ return $this->findParentAmongChildren( $parentChild->children, $child );
463
+ }
464
+ }
465
+ return [ $parentChildren, $found ];
466
+ }
467
+
468
+ /**
469
+ * Returns the names of the included post types or taxonomies.
470
+ *
471
+ * @since 4.1.3
472
+ *
473
+ * @param array|string $objects The included post types/taxonomies.
474
+ * @param boolean $arePostTypes Whether the objects are post types.
475
+ * @return array The names of the included post types/taxonomies.
476
+ */
477
+ private function getIncludedObjects( $objects, $arePostTypes = true ) {
478
+ if ( is_array( $objects ) ) {
479
+ return $objects;
480
+ }
481
+
482
+ $exploded = explode( ',', $objects );
483
+ if ( ! empty( $exploded ) ) {
484
+ $objects = array_map( function( $object ) {
485
+ return trim( $object );
486
+ }, $exploded );
487
+
488
+ $publicObjects = $arePostTypes
489
+ ? aioseo()->helpers->getPublicPostTypes( true )
490
+ : aioseo()->helpers->getPublicTaxonomies( true );
491
+
492
+ $objects = array_filter( $objects, function( $object ) use ( $publicObjects ) {
493
+ return in_array( $object, $publicObjects, true );
494
+ });
495
+ }
496
+ return $objects;
497
+ }
498
+ }
app/Common/Sitemap/Html/Query.php ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Sitemap\Html;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Handles all queries for the HTML sitemap.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class Query {
15
+ /**
16
+ * Returns all eligble sitemap entries for a given post type.
17
+ *
18
+ * @since 4.1.3
19
+ *
20
+ * @param string $postType The post type.
21
+ * @param array $attributes The attributes.
22
+ * @return array The post objects.
23
+ */
24
+ public function posts( $postType, $attributes ) {
25
+ $fields = '`ID`, `post_title`,';
26
+ $fields .= '`post_parent`, `post_date_gmt`, `post_modified_gmt`';
27
+
28
+ $orderBy = '';
29
+ switch ( $attributes['order_by'] ) {
30
+ case 'last_updated':
31
+ $orderBy = 'post_modified_gmt';
32
+ break;
33
+ case 'alphabetical':
34
+ $orderBy = 'post_title';
35
+ break;
36
+ case 'id':
37
+ $orderBy = 'ID';
38
+ case 'publish_date':
39
+ default:
40
+ $orderBy = 'post_date_gmt';
41
+ break;
42
+ }
43
+
44
+ switch ( strtolower( $attributes['order'] ) ) {
45
+ case 'desc':
46
+ $orderBy .= ' DESC';
47
+ break;
48
+ default:
49
+ $orderBy .= ' ASC';
50
+ }
51
+
52
+ $query = aioseo()->db
53
+ ->start( 'posts' )
54
+ ->select( $fields )
55
+ ->where( 'post_status', 'publish' )
56
+ ->where( 'post_type', $postType );
57
+
58
+ $excludedPosts = $this->getExcludedObjects( $attributes );
59
+ if ( $excludedPosts ) {
60
+ $query->whereRaw( "( `ID` NOT IN ( $excludedPosts ) )" );
61
+ }
62
+
63
+ $posts = $query->orderBy( $orderBy )
64
+ ->run()
65
+ ->result();
66
+
67
+ foreach ( $posts as $post ) {
68
+ $post->ID = (int) $post->ID;
69
+ }
70
+
71
+ return $posts;
72
+ }
73
+
74
+ /**
75
+ * Returns all eligble sitemap entries for a given taxonomy.
76
+ *
77
+ * @since 4.1.3
78
+ *
79
+ * @param string $taxonomy The taxonomy name.
80
+ * @param array $attributes The attributes.
81
+ * @return array The term objects.
82
+ */
83
+ public function terms( $taxonomy, $attributes = [] ) {
84
+ $fields = 't.term_id, t.name, tt.parent';
85
+ $termRelationshipsTable = aioseo()->db->db->prefix . 'term_relationships';
86
+ $termTaxonomyTable = aioseo()->db->db->prefix . 'term_taxonomy';
87
+
88
+ $orderBy = '';
89
+ switch ( $attributes['order_by'] ) {
90
+ case 'alphabetical':
91
+ $orderBy = 't.name';
92
+ break;
93
+ // We can only sort by date after getting the terms.
94
+ case 'id':
95
+ case 'publish_date':
96
+ case 'last_updated':
97
+ default:
98
+ $orderBy = 't.term_id';
99
+ break;
100
+ }
101
+
102
+ switch ( strtolower( $attributes['order'] ) ) {
103
+ case 'desc':
104
+ $orderBy .= ' DESC';
105
+ break;
106
+ default:
107
+ $orderBy .= ' ASC';
108
+ }
109
+
110
+ $query = aioseo()->db
111
+ ->start( 'terms as t' )
112
+ ->select( $fields )
113
+ ->join( 'term_taxonomy as tt', 't.term_id = tt.term_id' )
114
+ ->whereRaw( "
115
+ ( `t`.`term_id` IN
116
+ (
117
+ SELECT `tt`.`term_id`
118
+ FROM `$termTaxonomyTable` as tt
119
+ WHERE `tt`.`taxonomy` = '$taxonomy'
120
+ AND `tt`.`count` > 0
121
+ )
122
+ )" );
123
+
124
+ $excludedTerms = $this->getExcludedObjects( $attributes, false );
125
+ if ( $excludedTerms ) {
126
+ $query->whereRaw("
127
+ ( `t`.`term_id` NOT IN
128
+ (
129
+ SELECT `tr`.`term_taxonomy_id`
130
+ FROM `$termRelationshipsTable` as tr
131
+ WHERE `tr`.`term_taxonomy_id` IN ( $excludedTerms )
132
+ )
133
+ )" );
134
+ }
135
+
136
+ $terms = $query->orderBy( $orderBy )
137
+ ->run()
138
+ ->result();
139
+
140
+ foreach ( $terms as $term ) {
141
+ $term->term_id = (int) $term->term_id;
142
+ $term->taxonomy = $taxonomy;
143
+ }
144
+
145
+ $shouldSort = false;
146
+ if ( 'last_updated' === $attributes['order_by'] ) {
147
+ $shouldSort = true;
148
+ foreach ( $terms as $term ) {
149
+ $term->timestamp = strtotime( aioseo()->sitemap->content->getTermLastModified( $term->term_id ) );
150
+ }
151
+ }
152
+
153
+ if ( 'publish_date' === $attributes['order_by'] ) {
154
+ $shouldSort = true;
155
+ foreach ( $terms as $term ) {
156
+ $term->timestamp = strtotime( $this->getTermPublishDate( $term->term_id ) );
157
+ }
158
+ }
159
+
160
+ if ( $shouldSort ) {
161
+ if ( 'asc' === strtolower( $attributes['order'] ) ) {
162
+ usort( $terms, function( $term1, $term2 ) {
163
+ return $term1->timestamp > $term2->timestamp;
164
+ } );
165
+ } else {
166
+ usort( $terms, function( $term1, $term2 ) {
167
+ return $term1->timestamp < $term2->timestamp;
168
+ } );
169
+ }
170
+ }
171
+
172
+ return $terms;
173
+ }
174
+
175
+ /**
176
+ * Returns a list of date archives that can be included.
177
+ *
178
+ * @since 4.1.3
179
+ *
180
+ * @return array The date archives.
181
+ */
182
+ public function archives() {
183
+ $result = aioseo()->db
184
+ ->start( 'posts', false, 'SELECT DISTINCT' )
185
+ ->select( 'YEAR(post_date) AS year, MONTH(post_date) AS month' )
186
+ ->where( 'post_type', 'post' )
187
+ ->where( 'post_status', 'publish' )
188
+ ->whereRaw( "post_password=''" )
189
+ ->orderBy( '`year` DESC, `month` DESC' )
190
+ ->run()
191
+ ->result();
192
+
193
+ $dates = [];
194
+ foreach ( $result as $date ) {
195
+ $dates[ $date->year ][ $date->month ] = 1;
196
+ }
197
+
198
+ return $dates;
199
+ }
200
+
201
+ /**
202
+ * Returns the publish date for a given term.
203
+ * This is the publish date of the oldest post that is assigned to the term.
204
+ *
205
+ * @since 4.1.3
206
+ *
207
+ * @param int $termId The term ID.
208
+ * @return int The publish date timestamp.
209
+ */
210
+ public function getTermPublishDate( $termId ) {
211
+ $termRelationshipsTable = aioseo()->db->db->prefix . 'term_relationships';
212
+
213
+ $post = aioseo()->db
214
+ ->start( 'posts as p' )
215
+ ->select( 'MIN(`p`.`post_date_gmt`) as publish_date' )
216
+ ->whereRaw( "
217
+ ( `p`.`ID` IN
218
+ (
219
+ SELECT `tr`.`object_id`
220
+ FROM `$termRelationshipsTable` as tr
221
+ WHERE `tr`.`term_taxonomy_id` = '$termId'
222
+ )
223
+ )" )
224
+ ->run()
225
+ ->result();
226
+
227
+ return ! empty( $post[0]->publish_date ) ? strtotime( $post[0]->publish_date ) : 0;
228
+ }
229
+
230
+ /**
231
+ * Returns a comma-separated string of excluded object IDs.
232
+ *
233
+ * @since 4.1.3
234
+ *
235
+ * @param array $attributes The attributes.
236
+ * @param boolean $posts Whether the objects are posts.
237
+ * @return string The excluded object IDs.
238
+ */
239
+ private function getExcludedObjects( $attributes, $posts = true ) {
240
+ $excludedObjects = $posts
241
+ ? aioseo()->sitemap->helpers->excludedPosts()
242
+ : aioseo()->sitemap->helpers->excludedTerms();
243
+ $key = $posts ? 'excluded_posts' : 'excluded_terms';
244
+
245
+ if ( ! empty( $attributes[ $key ] ) ) {
246
+ $ids = explode( ',', $excludedObjects );
247
+
248
+ $extraIds = [];
249
+ if ( is_array( $attributes[ $key ] ) ) {
250
+ $extraIds = $attributes[ $key ];
251
+ }
252
+ if ( is_string( $attributes[ $key ] ) ) {
253
+ $extraIds = array_map( 'trim', explode( ',', $attributes[ $key ] ) );
254
+ }
255
+
256
+ $ids = array_filter( array_merge( $ids, $extraIds ), 'is_numeric' );
257
+
258
+ $excludedObjects = esc_sql( implode( ', ', $ids ) );
259
+ }
260
+ return $excludedObjects;
261
+ }
262
+ }
app/Common/Sitemap/Html/Shortcode.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Sitemap\Html;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Handles the HTML sitemap shortcode.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class Shortcode {
15
+ /**
16
+ * Class constructor.
17
+ *
18
+ * @since 4.1.3
19
+ */
20
+ public function __construct() {
21
+ add_shortcode( 'aioseo_html_sitemap', [ $this, 'render' ] );
22
+ }
23
+
24
+ /**
25
+ * Shortcode callback.
26
+ *
27
+ * @since 4.1.3
28
+ *
29
+ * @param array $attributes The shortcode attributes.
30
+ * @return string|void The HTML sitemap.
31
+ */
32
+ public function render( $attributes ) {
33
+ $attributes = aioseo()->htmlSitemap->frontend->getAttributes( $attributes );
34
+ return aioseo()->htmlSitemap->frontend->output( false, $attributes );
35
+ }
36
+ }
app/Common/Sitemap/Html/Sitemap.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace AIOSEO\Plugin\Common\Sitemap\Html {
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Main class for the HTML sitemap.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class Sitemap {
15
+ /** Instance of the frontend class.
16
+ *
17
+ * @since 4.1.3
18
+ *
19
+ * @var Frontend
20
+ */
21
+ public $frontend;
22
+
23
+ /**
24
+ * Instance of the shortcode class.
25
+ *
26
+ * @since 4.1.3
27
+ *
28
+ * @var Shortcode
29
+ */
30
+ public $shortcode;
31
+
32
+ /**
33
+ * Instance of the block class.
34
+ *
35
+ * @since 4.1.3
36
+ *
37
+ * @var Block
38
+ */
39
+ public $block;
40
+
41
+ /**
42
+ * Whether the current queried page is the dedicated sitemap page.
43
+ *
44
+ * @since 4.1.3
45
+ *
46
+ * @var bool
47
+ */
48
+ public $isDedicatedPage = false;
49
+
50
+ /**
51
+ * Class constructor.
52
+ *
53
+ * @since 4.1.3
54
+ */
55
+ public function __construct() {
56
+ $this->frontend = new Frontend();
57
+ $this->shortcode = new Shortcode();
58
+ $this->block = new Block();
59
+
60
+ add_action( 'widgets_init', [ $this, 'registerWidget' ] );
61
+
62
+ if ( ! is_admin() || wp_doing_ajax() || wp_doing_cron() ) {
63
+ add_action( 'template_redirect', [ $this, 'checkForDedicatedPage' ] );
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Register our HTML sitemap widget.
69
+ *
70
+ * @since 4.1.3
71
+ *
72
+ * @return void
73
+ */
74
+ public function registerWidget() {
75
+ register_widget( 'AIOSEO\Plugin\Common\Sitemap\Html\Widget' );
76
+ }
77
+
78
+ /**
79
+ * Checks whether the current request is for our dedicated HTML sitemap page.
80
+ *
81
+ * @since 4.1.3
82
+ *
83
+ * @return void
84
+ */
85
+ public function checkForDedicatedPage() {
86
+ if ( ! aioseo()->options->sitemap->html->enable ) {
87
+ return;
88
+ }
89
+
90
+ global $wp;
91
+ $sitemapUrl = aioseo()->options->sitemap->html->pageUrl;
92
+ if ( ! $sitemapUrl || empty( $wp->request ) ) {
93
+ return;
94
+ }
95
+
96
+ $sitemapUrl = wp_parse_url( $sitemapUrl );
97
+ if ( empty( $sitemapUrl['path'] ) ) {
98
+ return;
99
+ }
100
+
101
+ $sitemapUrl = trim( $sitemapUrl['path'], '/' );
102
+ if ( trim( $wp->request, '/' ) === $sitemapUrl ) {
103
+ $this->isDedicatedPage = true;
104
+ $this->generatePage();
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Checks whether the current request is for our dedicated HTML sitemap page.
110
+ *
111
+ * @since 4.1.3
112
+ *
113
+ * @return void
114
+ */
115
+ private function generatePage() {
116
+ global $wp_query, $wp, $post;
117
+
118
+ $postId = -1337; // Set a negative ID to prevent conflicts with existing posts.
119
+ $sitemapUrl = aioseo()->options->sitemap->html->pageUrl;
120
+ $path = trim( wp_parse_url( $sitemapUrl )['path'], '/' );
121
+
122
+ $fakePost = new \stdClass();
123
+ $fakePost->ID = $postId;
124
+ $fakePost->post_author = 1;
125
+ $fakePost->post_date = current_time( 'mysql' );
126
+ $fakePost->post_date_gmt = current_time( 'mysql', 1 );
127
+ $fakePost->post_title = apply_filters( 'aioseo_html_sitemap_page_title', __( 'Sitemap', 'all-in-one-seo-pack' ) );
128
+ $fakePost->post_content = '[aioseo_html_sitemap archives=false]';
129
+ // We're using post instead of page to prevent calls to get_ancestors(), which will trigger errors.
130
+ // To loead the page template, we set is_page to true on the WP_Query object.
131
+ $fakePost->post_type = 'post';
132
+ $fakePost->post_status = 'publish';
133
+ $fakePost->comment_status = 'closed';
134
+ $fakePost->ping_status = 'closed';
135
+ $fakePost->post_name = $path;
136
+ $fakePost->filter = 'raw'; // Needed to prevent calls to the database when creating the WP_Post object.
137
+ $postObject = new \WP_Post( $fakePost );
138
+
139
+ $post = $postObject;
140
+
141
+ // We'll set as much properties on the WP_Query object as we can to prevent conflicts with other plugins/themes.
142
+ $wp_query->is_404 = false;
143
+ $wp_query->is_page = true;
144
+ $wp_query->is_singular = true;
145
+ $wp_query->post = $postObject;
146
+ $wp_query->posts = [ $postObject ];
147
+ $wp_query->queried_object = $postObject;
148
+ $wp_query->queried_object_id = $postId;
149
+ $wp_query->found_posts = 1;
150
+ $wp_query->post_count = 1;
151
+ $wp_query->max_num_pages = 1;
152
+
153
+ unset( $wp_query->query['error'] );
154
+ $wp_query->query_vars['error'] = '';
155
+
156
+ // We need to add the post object to the cache so that get_post() calls don't trigger database calls.
157
+ wp_cache_add( $postId, $postObject, 'posts' );
158
+
159
+ $GLOBALS['wp_query'] = $wp_query;
160
+ $wp->register_globals();
161
+
162
+ // Setting is_404 is not sufficient, so we still need to change the status code.
163
+ status_header( 200 );
164
+ }
165
+ }
166
+ }
167
+
168
+ namespace {
169
+ // Exit if accessed directly.
170
+ if ( ! defined( 'ABSPATH' ) ) {
171
+ exit;
172
+ }
173
+
174
+ if ( ! function_exists( 'aioseo_html_sitemap' ) ) {
175
+ /**
176
+ * Global function that can be used to print the HTML sitemap.
177
+ *
178
+ * @since 4.1.3
179
+ *
180
+ * @param array $attributes User-defined attributes that override the default settings.
181
+ * @param boolean $echo Whether to echo the output or return it.
182
+ * @return string The HTML sitemap code.
183
+ */
184
+ function aioseo_html_sitemap( $attributes = [], $echo = true ) {
185
+ $attributes = aioseo()->htmlSitemap->frontend->getAttributes( $attributes );
186
+ return aioseo()->htmlSitemap->frontend->output( $echo, $attributes );
187
+ }
188
+ }
189
+ }
app/Common/Sitemap/Html/Widget.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Sitemap\Html;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Class Widget.
11
+ *
12
+ * @since 4.1.3
13
+ */
14
+ class Widget extends \WP_Widget {
15
+ /**
16
+ * Class constructor.
17
+ *
18
+ * @since 4.1.3
19
+ */
20
+ public function __construct() {
21
+ // The default widget settings.
22
+ $this->defaults = [
23
+ 'title' => '',
24
+ 'show_label' => 'on',
25
+ 'archives' => '',
26
+ 'nofollow_links' => '',
27
+ 'order' => 'asc',
28
+ 'order_by' => 'publish_date',
29
+ 'publication_date' => 'on',
30
+ 'post_types' => [ 'post', 'page' ],
31
+ 'taxonomies' => [ 'category', 'post_tag' ],
32
+ 'excluded_posts' => '',
33
+ 'excluded_terms' => ''
34
+ ];
35
+
36
+ $widgetSlug = 'aioseo-html-sitemap-widget';
37
+ $widgetOptions = [
38
+ 'classname' => $widgetSlug,
39
+ // Translators: The short plugin name ("AIOSEO").
40
+ 'description' => sprintf( esc_html__( '%1$s HTML sitemap widget.', 'all-in-one-seo-pack' ), AIOSEO_PLUGIN_SHORT_NAME )
41
+ ];
42
+ $controlOptions = [
43
+ 'id_base' => $widgetSlug
44
+ ];
45
+
46
+ // Translators: 1 - The short plugin name ("AIOSEO").
47
+ parent::__construct( $widgetSlug, sprintf( esc_html__( '%1$s - HTML Sitemap', 'all-in-one-seo-pack' ), AIOSEO_PLUGIN_SHORT_NAME ), $widgetOptions, $controlOptions );
48
+ }
49
+
50
+ /**
51
+ * Callback for the widget.
52
+ *
53
+ * @since 4.1.3
54
+ *
55
+ * @param array $args The widget arguments.
56
+ * @param array $instance The widget instance options.
57
+ * @return void
58
+ */
59
+ public function widget( $args, $instance ) {
60
+ if ( ! aioseo()->options->sitemap->html->enable ) {
61
+ return;
62
+ }
63
+
64
+ // Merge with defaults.
65
+ $instance = wp_parse_args( (array) $instance, $this->defaults );
66
+
67
+ echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
68
+
69
+ if ( ! empty( $instance['title'] ) ) {
70
+ echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,Generic.Files.LineLength.MaxExceeded
71
+ }
72
+
73
+ $instance = aioseo()->htmlSitemap->frontend->getAttributes( $instance );
74
+ aioseo()->htmlSitemap->frontend->output( true, $instance );
75
+ echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
76
+ }
77
+
78
+ /**
79
+ * Callback to update the widget options.
80
+ *
81
+ * @since 4.1.3
82
+ *
83
+ * @param array $newOptions The new options.
84
+ * @param array $oldOptions The old options.
85
+ * @return array The new options.
86
+ */
87
+ public function update( $newOptions, $oldOptions ) {
88
+ $settings = [
89
+ 'title',
90
+ 'order',
91
+ 'order_by',
92
+ 'show_label',
93
+ 'publication_date',
94
+ 'archives',
95
+ 'excluded_posts',
96
+ 'excluded_terms'
97
+ ];
98
+
99
+ foreach ( $settings as $setting ) {
100
+ $newOptions[ $setting ] = ! empty( $newOptions[ $setting ] ) ? wp_strip_all_tags( $newOptions[ $setting ] ) : '';
101
+ }
102
+
103
+ $includedPostTypes = [];
104
+ if ( ! empty( $newOptions['post_types'] ) ) {
105
+ $postTypes = $this->getPublicPostTypes( true );
106
+ foreach ( $newOptions['post_types'] as $index => $v ) {
107
+ if ( is_numeric( $v ) ) {
108
+ $includedPostTypes[] = $postTypes[ $v ];
109
+ } else {
110
+ $includedPostTypes[] = $v;
111
+ }
112
+ }
113
+ }
114
+ $newOptions['post_types'] = $includedPostTypes;
115
+
116
+ $includedTaxonomies = [];
117
+ if ( ! empty( $newOptions['taxonomies'] ) ) {
118
+ $taxonomies = aioseo()->helpers->getPublicTaxonomies( true );
119
+ foreach ( $newOptions['taxonomies'] as $index => $v ) {
120
+ if ( is_numeric( $v ) ) {
121
+ $includedTaxonomies[] = $taxonomies[ $v ];
122
+ } else {
123
+ $includedTaxonomies[] = $v;
124
+ }
125
+ }
126
+ }
127
+ $newOptions['taxonomies'] = $includedTaxonomies;
128
+
129
+ if ( ! empty( $newOptions['excluded_posts'] ) ) {
130
+ $newOptions['excluded_posts'] = $this->sanitizeExcludedIds( $newOptions['excluded_posts'] );
131
+ }
132
+
133
+ if ( ! empty( $newOptions['excluded_terms'] ) ) {
134
+ $newOptions['excluded_terms'] = $this->sanitizeExcludedIds( $newOptions['excluded_terms'] );
135
+ }
136
+
137
+ return $newOptions;
138
+ }
139
+
140
+ /**
141
+ * Callback for the widgets options form.
142
+ *
143
+ * @since 4.1.3
144
+ *
145
+ * @param array $instance The widget options.
146
+ * @return void
147
+ */
148
+ public function form( $instance ) {
149
+ // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
150
+ $instance = wp_parse_args( (array) $instance, $this->defaults );
151
+ $postTypeObjects = $this->getPublicPostTypes();
152
+ $postTypes = $this->getPublicPostTypes( true );
153
+ $taxonomyObjects = aioseo()->helpers->getPublicTaxonomies();
154
+ // phpcs:enable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
155
+
156
+ include( AIOSEO_DIR . '/app/Common/Views/sitemap/html/widget-options.php' );
157
+ }
158
+
159
+ /**
160
+ * Returns the public post types (without attachments).
161
+ *
162
+ * @since 4.1.3
163
+ *
164
+ * @param boolean $namesOnly Whether only the names should be returned.
165
+ * @return array The public post types.
166
+ */
167
+ private function getPublicPostTypes( $namesOnly = false ) {
168
+ $postTypes = aioseo()->helpers->getPublicPostTypes( $namesOnly );
169
+ foreach ( $postTypes as $k => $postType ) {
170
+ if ( is_array( $postType ) && 'attachment' === $postType['name'] ) {
171
+ unset( $postTypes[ $k ] );
172
+ break;
173
+ }
174
+ if ( ! is_array( $postType ) && 'attachment' === $postType ) {
175
+ unset( $postTypes[ $k ] );
176
+ break;
177
+ }
178
+ }
179
+ return array_values( $postTypes );
180
+ }
181
+
182
+ /**
183
+ * Sanitizes the excluded IDs by removing any non-integer values.
184
+ *
185
+ * @since 4.1.3
186
+ *
187
+ * @param string $ids The IDs as a string, comma-separated.
188
+ * @return string The sanitized IDs as a string, comma-separated.
189
+ */
190
+ private function sanitizeExcludedIds( $ids ) {
191
+ $ids = array_map( 'trim', explode( ',', $ids ) );
192
+ $ids = array_filter( $ids, 'is_numeric' );
193
+ $ids = esc_sql( implode( ', ', $ids ) );
194
+ return $ids;
195
+ }
196
+ }
app/Common/Sitemap/Image.php CHANGED
@@ -32,6 +32,11 @@ class Image {
32
  return;
33
  }
34
 
 
 
 
 
 
35
  add_action( $this->imageScanAction, [ $this, 'scanPosts' ] );
36
 
37
  if ( wp_doing_ajax() || wp_doing_cron() ) {
@@ -113,15 +118,18 @@ class Image {
113
  }
114
 
115
  if ( ! empty( $post->post_password ) ) {
116
- return $this->updatePost( $post->ID );
 
117
  }
118
 
119
  if ( 'attachment' === $post->post_type ) {
120
  if ( ! wp_attachment_is( 'image', $post ) ) {
121
- return $this->updatePost( $post->ID );
 
122
  }
123
  $image = $this->buildEntries( [ $post->ID ] );
124
- return $this->updatePost( $post->ID, $image );
 
125
  }
126
 
127
  $postContent = $this->doShortcodes( $post->post_content );
@@ -134,7 +142,6 @@ class Image {
134
  $images[] = get_the_post_thumbnail_url( $post );
135
  }
136
 
137
- $images = $this->filter( $images );
138
  $images = $this->removeImageDimensions( $images );
139
 
140
  if ( aioseo()->helpers->isWooCommerceActive() && 'product' === $post->post_type ) {
@@ -142,18 +149,15 @@ class Image {
142
  }
143
 
144
  if ( ! $images ) {
145
- return $this->updatePost( $post->ID );
 
146
  }
147
 
148
- $parsedImages = [];
149
- foreach ( $images as $image ) {
150
- $attachmentId = is_numeric( $image ) ? $image : aioseo()->helpers->attachmentUrlToPostId( $image );
151
- $parsedImages[] = $attachmentId ? $attachmentId : $image;
152
- }
153
 
154
  // Limit to a 1,000 URLs, in accordance to Google's specifications.
155
- $images = array_slice( $this->buildEntries( $parsedImages ), 0, 1000 );
156
- return $this->updatePost( $post->ID, $images );
157
  }
158
 
159
  /**
@@ -199,12 +203,13 @@ class Image {
199
  *
200
  * @since 4.0.0
201
  *
202
- * @param array $ids Either a numeric post ID or the image URL if the ID of the image couldn't be found.
203
- * @return array The image entries.
204
  */
205
- private function buildEntries( $ids ) {
206
  $entries = [];
207
- foreach ( $ids as $id ) {
 
208
  if ( ! is_numeric( $id ) ) {
209
  $entries[] = [ 'image:loc' => aioseo()->sitemap->helpers->formatUrl( $id ) ];
210
  continue;
@@ -219,6 +224,27 @@ class Image {
219
  return $entries;
220
  }
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  /**
223
  * Extracts all image URls from the post content.
224
  *
@@ -240,36 +266,6 @@ class Image {
240
  return array_unique( $urls );
241
  }
242
 
243
- /**
244
- * Removes all URLs that aren't on our domain whitelist.
245
- *
246
- * @since 4.0.0
247
- *
248
- * @param array $urls The image URLs.
249
- * @return array The remaining image URLs.
250
- */
251
- private function filter( $urls ) {
252
- $allowedDomains = apply_filters( 'aioseo_sitemap_image_domains', [
253
- aioseo()->helpers->localizedUrl( '/' ),
254
- 'wp.com'
255
- ] );
256
-
257
- if ( ! count( $allowedDomains ) ) {
258
- return [];
259
- }
260
-
261
- $remainingUrls = [];
262
- foreach ( $urls as $url ) {
263
- foreach ( $allowedDomains as $domain ) {
264
- if ( preg_match( "#.*$domain.*#", $url ) ) {
265
- $remainingUrls[] = $url;
266
- continue;
267
- }
268
- }
269
- }
270
- return $remainingUrls;
271
- }
272
-
273
  /**
274
  * Removes image dimensions from the slug.
275
  *
32
  return;
33
  }
34
 
35
+ // Don't schedule a scan if an importer is running.
36
+ if ( aioseo()->importExport->isImportRunning() ) {
37
+ return;
38
+ }
39
+
40
  add_action( $this->imageScanAction, [ $this, 'scanPosts' ] );
41
 
42
  if ( wp_doing_ajax() || wp_doing_cron() ) {
118
  }
119
 
120
  if ( ! empty( $post->post_password ) ) {
121
+ $this->updatePost( $post->ID );
122
+ return;
123
  }
124
 
125
  if ( 'attachment' === $post->post_type ) {
126
  if ( ! wp_attachment_is( 'image', $post ) ) {
127
+ $this->updatePost( $post->ID );
128
+ return;
129
  }
130
  $image = $this->buildEntries( [ $post->ID ] );
131
+ $this->updatePost( $post->ID, $image );
132
+ return;
133
  }
134
 
135
  $postContent = $this->doShortcodes( $post->post_content );
142
  $images[] = get_the_post_thumbnail_url( $post );
143
  }
144
 
 
145
  $images = $this->removeImageDimensions( $images );
146
 
147
  if ( aioseo()->helpers->isWooCommerceActive() && 'product' === $post->post_type ) {
149
  }
150
 
151
  if ( ! $images ) {
152
+ $this->updatePost( $post->ID );
153
+ return;
154
  }
155
 
156
+ $images = apply_filters( 'aioseo_sitemap_images', $images );
 
 
 
 
157
 
158
  // Limit to a 1,000 URLs, in accordance to Google's specifications.
159
+ $images = array_slice( $images, 0, 1000 );
160
+ $this->updatePost( $post->ID, $this->buildEntries( $images ) );
161
  }
162
 
163
  /**
203
  *
204
  * @since 4.0.0
205
  *
206
+ * @param array $images The images, consisting of attachment IDs or external URLs.
207
+ * @return array The image entries.
208
  */
209
+ private function buildEntries( $images ) {
210
  $entries = [];
211
+ foreach ( $images as $image ) {
212
+ $id = $this->getImageId( $image );
213
  if ( ! is_numeric( $id ) ) {
214
  $entries[] = [ 'image:loc' => aioseo()->sitemap->helpers->formatUrl( $id ) ];
215
  continue;
224
  return $entries;
225
  }
226
 
227
+ /**
228
+ * Returns the ID of the image if it's hosted on the site. Otherwise it returns the external URL.
229
+ *
230
+ * @since 4.1.3
231
+ *
232
+ * @param int|string $image The attachment ID or URL.
233
+ * @return int|string The attachment ID or URL.
234
+ */
235
+ private function getImageId( $image ) {
236
+ if ( is_numeric( $image ) ) {
237
+ return $image;
238
+ }
239
+
240
+ $attachmentId = false;
241
+ if ( aioseo()->helpers->isValidAttachment( $image ) ) {
242
+ $attachmentId = aioseo()->helpers->attachmentUrlToPostId( $image );
243
+ }
244
+
245
+ return $attachmentId ? $attachmentId : $image;
246
+ }
247
+
248
  /**
249
  * Extracts all image URls from the post content.
250
  *
266
  return array_unique( $urls );
267
  }
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  /**
270
  * Removes image dimensions from the slug.
271
  *
app/Common/Sitemap/Priority.php CHANGED
@@ -85,6 +85,7 @@ class Priority {
85
 
86
  if ( ! isset( self::$globalPriority[ $pageType . $objectType ] ) ) {
87
  $options = aioseo()->options->noConflict();
 
88
  $pageTypeConditional = 'date' === $pageType ? 'archive' : $pageType;
89
  self::$globalPriority[ $pageType . $objectType ] = self::$advanced && $options->sitemap->general->advancedSettings->priority->has( $pageTypeConditional )
90
  ? json_decode( $options->sitemap->general->advancedSettings->priority->$pageTypeConditional->priority )
@@ -102,8 +103,10 @@ class Priority {
102
 
103
  if ( empty( self::$grouped[ $pageType . $objectType ] ) && self::$advanced ) {
104
  if ( ! isset( self::$objectTypePriority[ $pageType . $objectType ] ) ) {
105
- self::$objectTypePriority[ $pageType . $objectType ] = $options->sitemap->dynamic->priority->has( $pageType ) && $options->sitemap->dynamic->priority->$pageType->has( $objectType )
106
- ? json_decode( $options->sitemap->dynamic->priority->$pageType->$objectType->priority )
 
 
107
  : false;
108
  }
109
  }
@@ -155,8 +158,10 @@ class Priority {
155
 
156
  if ( empty( self::$grouped[ $pageType . $objectType ] ) && self::$advanced ) {
157
  if ( ! isset( self::$objectTypeFrequency[ $pageType . $objectType ] ) ) {
158
- self::$objectTypeFrequency[ $pageType . $objectType ] = $options->sitemap->dynamic->priority->has( $pageType ) && $options->sitemap->dynamic->priority->$pageType->has( $objectType )
159
- ? json_decode( $options->sitemap->dynamic->priority->$pageType->$objectType->frequency )
 
 
160
  : false;
161
  }
162
  }
85
 
86
  if ( ! isset( self::$globalPriority[ $pageType . $objectType ] ) ) {
87
  $options = aioseo()->options->noConflict();
88
+
89
  $pageTypeConditional = 'date' === $pageType ? 'archive' : $pageType;
90
  self::$globalPriority[ $pageType . $objectType ] = self::$advanced && $options->sitemap->general->advancedSettings->priority->has( $pageTypeConditional )
91
  ? json_decode( $options->sitemap->general->advancedSettings->priority->$pageTypeConditional->priority )
103
 
104
  if ( empty( self::$grouped[ $pageType . $objectType ] ) && self::$advanced ) {
105
  if ( ! isset( self::$objectTypePriority[ $pageType . $objectType ] ) ) {
106
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
107
+
108
+ self::$objectTypePriority[ $pageType . $objectType ] = $dynamicOptions->sitemap->priority->has( $pageType ) && $dynamicOptions->sitemap->priority->$pageType->has( $objectType )
109
+ ? json_decode( $dynamicOptions->sitemap->priority->$pageType->$objectType->priority )
110
  : false;
111
  }
112
  }
158
 
159
  if ( empty( self::$grouped[ $pageType . $objectType ] ) && self::$advanced ) {
160
  if ( ! isset( self::$objectTypeFrequency[ $pageType . $objectType ] ) ) {
161
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
162
+
163
+ self::$objectTypeFrequency[ $pageType . $objectType ] = $dynamicOptions->sitemap->priority->has( $pageType ) && $dynamicOptions->sitemap->priority->$pageType->has( $objectType )
164
+ ? json_decode( $dynamicOptions->sitemap->priority->$pageType->$objectType->frequency )
165
  : false;
166
  }
167
  }
app/Common/Sitemap/Query.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  namespace AIOSEO\Plugin\Common\Sitemap;
3
 
 
 
4
  // Exit if accessed directly.
5
  if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
@@ -29,7 +31,7 @@ class Query {
29
 
30
  if (
31
  empty( $includedPostTypes ) ||
32
- ( 'attachment' === $includedPostTypes && 'disabled' !== aioseo()->options->searchAppearance->dynamic->postTypes->attachment->redirectAttachmentUrls )
33
  ) {
34
  return [];
35
  }
@@ -101,8 +103,10 @@ class Query {
101
  $query->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset );
102
  }
103
 
104
- $posts = $query->orderBy( $orderBy )
105
- ->run()
 
 
106
  ->result();
107
 
108
  // Convert ID from string to int.
@@ -114,62 +118,44 @@ class Query {
114
  }
115
 
116
  /**
117
- * Filters the queried posts.
118
  *
119
- * @since 4.0.0
120
  *
121
- * @param array $posts The posts.
122
- * @return array $remainingPosts The remaining posts.
 
123
  */
124
- public function filterPosts( $posts ) {
125
- $remainingPosts = [];
126
- $isWooCommerceActive = aioseo()->helpers->isWooCommerceActive();
127
- $isWooCommerceNoindexing = $isWooCommerceActive && has_action( 'wp_head', 'wc_page_noindex' );
128
- $excludeHiddenProducts = apply_filters( 'aioseo_sitemap_woocommerce_exclude_hidden_products', true );
129
-
130
- foreach ( $posts as $post ) {
131
- if ( 'product' !== $post->post_type && is_numeric( $post ) ) {
132
- $remainingPosts[] = $post;
133
- continue;
134
- }
135
-
136
- switch ( $post->post_type ) {
137
- case 'page':
138
- if ( ! $isWooCommerceNoindexing || ! aioseo()->helpers->isWooCommercePage( $post->ID ) ) {
139
- $remainingPosts[] = $post;
140
- }
141
- break;
142
- case 'product':
143
- if ( ! $isWooCommerceActive || ! $excludeHiddenProducts || ! $this->isHiddenProduct( $post ) ) {
144
- $remainingPosts[] = $post;
145
- }
146
- break;
147
- case 'attachment':
148
- if ( ! $this->isInvalidAttachment( $post ) ) {
149
- $remainingPosts[] = $post;
150
- }
151
- break;
152
- default:
153
- $remainingPosts[] = $post;
154
- break;
155
- }
156
  }
157
-
158
- return $remainingPosts;
159
  }
160
 
161
  /**
162
- * Whether the WooCommerce product is hidden.
163
  *
164
- * @since 4.0.0
165
  *
166
- * @param Object $post The post.
167
- * @return boolean Whether the post is a hidden product.
168
  */
169
- private function isHiddenProduct( $post ) {
 
 
 
 
 
 
 
170
  static $hiddenProductIds = null;
171
  if ( null === $hiddenProductIds ) {
172
- $hiddenProducts = aioseo()->db->start( 'term_relationships as tr' )
 
173
  ->select( 'tr.object_id' )
174
  ->join( 'term_taxonomy as tt', 'tr.term_taxonomy_id = tt.term_taxonomy_id' )
175
  ->join( 'terms as t', 'tt.term_id = t.term_id' )
@@ -178,19 +164,44 @@ class Query {
178
  ->result();
179
 
180
  $hiddenProductIds = [];
181
- if ( ! empty( $hiddenProducts ) ) {
182
- foreach ( $hiddenProducts as $hiddenProduct ) {
183
- $hiddenProductIds[] = (int) $hiddenProduct->object_id;
184
- }
 
 
185
  }
 
186
  }
187
 
188
- $postId = $post;
189
- if ( ! is_numeric( $post ) ) {
190
- $postId = $post->ID;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  }
192
 
193
- return in_array( $postId, $hiddenProductIds, true );
194
  }
195
 
196
  /**
1
  <?php
2
  namespace AIOSEO\Plugin\Common\Sitemap;
3
 
4
+ use AIOSEO\Plugin\Common\Utils as CommonUtils;
5
+
6
  // Exit if accessed directly.
7
  if ( ! defined( 'ABSPATH' ) ) {
8
  exit;
31
 
32
  if (
33
  empty( $includedPostTypes ) ||
34
+ ( 'attachment' === $includedPostTypes && 'disabled' !== aioseo()->dynamicOptions->searchAppearance->postTypes->attachment->redirectAttachmentUrls )
35
  ) {
36
  return [];
37
  }
103
  $query->limit( aioseo()->sitemap->linksPerIndex, aioseo()->sitemap->offset );
104
  }
105
 
106
+ $query->orderBy( $orderBy );
107
+ $query = $this->filterPostQuery( $query, $postTypes );
108
+
109
+ $posts = $query->run()
110
  ->result();
111
 
112
  // Convert ID from string to int.
118
  }
119
 
120
  /**
121
+ * Filters the post query.
122
  *
123
+ * @since 4.1.4
124
  *
125
+ * @param \AIOSEO\Plugin\Common\Utils\Database $query The query.
126
+ * @param string $postType The post type.
127
+ * @return \AIOSEO\Plugin\Common\Utils\Database The filtered query.
128
  */
129
+ private function filterPostQuery( $query, $postType ) {
130
+ switch ( $postType ) {
131
+ case 'product':
132
+ return $this->excludeHiddenProducts( $query );
133
+ default:
134
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  }
136
+ return $query;
 
137
  }
138
 
139
  /**
140
+ * Adds a condition to the query to exclude hidden WooCommerce products.
141
  *
142
+ * @since 4.1.4
143
  *
144
+ * @param \AIOSEO\Plugin\Common\Utils\Database $query The query.
145
+ * @return \AIOSEO\Plugin\Common\Utils\Database The filtered query.
146
  */
147
+ private function excludeHiddenProducts( $query ) {
148
+ if (
149
+ ! aioseo()->helpers->isWooCommerceActive() ||
150
+ ! apply_filters( 'aioseo_sitemap_woocommerce_exclude_hidden_products', true )
151
+ ) {
152
+ return $query;
153
+ }
154
+
155
  static $hiddenProductIds = null;
156
  if ( null === $hiddenProductIds ) {
157
+ $tempDb = new CommonUtils\Database();
158
+ $hiddenProducts = $tempDb->start( 'term_relationships as tr' )
159
  ->select( 'tr.object_id' )
160
  ->join( 'term_taxonomy as tt', 'tr.term_taxonomy_id = tt.term_taxonomy_id' )
161
  ->join( 'terms as t', 'tt.term_id = t.term_id' )
164
  ->result();
165
 
166
  $hiddenProductIds = [];
167
+ if ( empty( $hiddenProducts ) ) {
168
+ return $query;
169
+ }
170
+
171
+ foreach ( $hiddenProducts as $hiddenProduct ) {
172
+ $hiddenProductIds[] = (int) $hiddenProduct->object_id;
173
  }
174
+ $hiddenProductIds = esc_sql( implode( ', ', $hiddenProductIds ) );
175
  }
176
 
177
+ $query->whereRaw( "p.ID NOT IN ( $hiddenProductIds )" );
178
+ return $query;
179
+ }
180
+
181
+ /**
182
+ * Filters the queried posts.
183
+ *
184
+ * @since 4.0.0
185
+ *
186
+ * @param array $posts The posts.
187
+ * @return array $remainingPosts The remaining posts.
188
+ */
189
+ public function filterPosts( $posts ) {
190
+ $remainingPosts = [];
191
+ foreach ( $posts as $post ) {
192
+ switch ( $post->post_type ) {
193
+ case 'attachment':
194
+ if ( ! $this->isInvalidAttachment( $post ) ) {
195
+ $remainingPosts[] = $post;
196
+ }
197
+ break;
198
+ default:
199
+ $remainingPosts[] = $post;
200
+ break;
201
+ }
202
  }
203
 
204
+ return $remainingPosts;
205
  }
206
 
207
  /**
app/Common/Sitemap/Root.php CHANGED
@@ -70,10 +70,10 @@ class Root {
70
 
71
  if (
72
  get_post_type_archive_link( $postType ) &&
73
- aioseo()->options->noConflict()->searchAppearance->dynamic->archives->has( $postType ) &&
74
  (
75
- aioseo()->options->searchAppearance->dynamic->archives->$postType->advanced->robotsMeta->default ||
76
- ! aioseo()->options->searchAppearance->dynamic->archives->$postType->advanced->robotsMeta->noindex
77
  )
78
  ) {
79
  $hasPostArchive = true;
70
 
71
  if (
72
  get_post_type_archive_link( $postType ) &&
73
+ aioseo()->dynamicOptions->noConflict()->searchAppearance->archives->has( $postType ) &&
74
  (
75
+ aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->default ||
76
+ ! aioseo()->dynamicOptions->searchAppearance->archives->$postType->advanced->robotsMeta->noindex
77
  )
78
  ) {
79
  $hasPostArchive = true;
app/Common/Sitemap/Sitemap.php CHANGED
@@ -287,7 +287,8 @@ class Sitemap {
287
  }
288
 
289
  if ( ! $entries ) {
290
- return $this->notFoundPage();
 
291
  }
292
 
293
  $this->headers();
287
  }
288
 
289
  if ( ! $entries ) {
290
+ $this->notFoundPage();
291
+ return;
292
  }
293
 
294
  $this->headers();
app/Common/Social/Facebook.php CHANGED
@@ -178,9 +178,9 @@ class Facebook {
178
  }
179
 
180
  $postType = get_post_type();
181
- $options = aioseo()->options->noConflict();
182
- $defaultObjectType = $options->social->facebook->general->dynamic->postTypes->has( $postType )
183
- ? $options->social->facebook->general->dynamic->postTypes->$postType->objectType
184
  : '';
185
 
186
  return ! empty( $defaultObjectType ) ? $defaultObjectType : 'article';
@@ -273,7 +273,7 @@ class Facebook {
273
  */
274
  public function getPublishedTime() {
275
  $post = aioseo()->helpers->getPost();
276
- return $post ? gmdate( 'Y-m-d\TH:i:s\Z', mysql2date( 'U', aioseo()->helpers->getPost()->post_date_gmt ) ) : '';
277
  }
278
 
279
  /**
@@ -285,7 +285,7 @@ class Facebook {
285
  */
286
  public function getModifiedTime() {
287
  $post = aioseo()->helpers->getPost();
288
- return $post ? gmdate( 'Y-m-d\TH:i:s\Z', mysql2date( 'U', aioseo()->helpers->getPost()->post_modified_gmt ) ) : '';
289
  }
290
 
291
 
@@ -331,14 +331,216 @@ class Facebook {
331
  }
332
 
333
  if ( aioseo()->options->social->facebook->advanced->useCategoriesInTags ) {
334
- $tags = array_merge( $tags, aioseo()->social->helpers->getAllCategories( $post->ID ) );
335
  }
336
 
337
  if ( aioseo()->options->social->facebook->advanced->usePostTagsInTags ) {
338
- $tags = array_merge( $tags, aioseo()->social->helpers->getAllTags( $post->ID ) );
339
  }
340
  }
341
 
342
  return aioseo()->meta->keywords->getUniqueKeywords( $tags, false );
343
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  }
178
  }
179
 
180
  $postType = get_post_type();
181
+ $dynamicOptions = aioseo()->dynamicOptions->noConflict();
182
+ $defaultObjectType = $dynamicOptions->social->facebook->general->postTypes->has( $postType )
183
+ ? $dynamicOptions->social->facebook->general->postTypes->$postType->objectType
184
  : '';
185
 
186
  return ! empty( $defaultObjectType ) ? $defaultObjectType : 'article';
273
  */
274
  public function getPublishedTime() {
275
  $post = aioseo()->helpers->getPost();
276
+ return $post ? aioseo()->helpers->formatDateTime( $post->post_date_gmt ) : '';
277
  }
278
 
279
  /**
285
  */
286
  public function getModifiedTime() {
287
  $post = aioseo()->helpers->getPost();
288
+ return $post ? aioseo()->helpers->formatDateTime( $post->post_modified_gmt ) : '';
289
  }
290
 
291
 
331
  }
332
 
333
  if ( aioseo()->options->social->facebook->advanced->useCategoriesInTags ) {
334
+ $tags = array_merge( $tags, aioseo()->helpers->getAllCategories( $post->ID ) );
335
  }
336
 
337
  if ( aioseo()->options->social->facebook->advanced->usePostTagsInTags ) {
338
+ $tags = array_merge( $tags, aioseo()->helpers->getAllTags( $post->ID ) );
339
  }
340
  }
341
 
342
  return aioseo()->meta->keywords->getUniqueKeywords( $tags, false );
343
  }
344
+
345
+ /**
346
+ * Retreive the locale.
347
+ *
348
+ * @since 4.1.4
349
+ *
350
+ * @return string The locale.
351
+ */
352
+ public function getLocale() {
353
+ $locale = get_locale();
354
+
355
+ // These are the locales FB supports.
356
+ $validLocales = [
357
+ 'af_ZA', // Afrikaans.
358
+ 'ak_GH', // Akan.
359
+ 'am_ET', // Amharic.
360
+ 'ar_AR', // Arabic.
361
+ 'as_IN', // Assamese.
362
+ 'ay_BO', // Aymara.
363
+ 'az_AZ', // Azerbaijani.
364
+ 'be_BY', // Belarusian.
365
+ 'bg_BG', // Bulgarian.
366
+ 'bp_IN', // Bhojpuri.
367
+ 'bn_IN', // Bengali.
368
+ 'br_FR', // Breton.
369
+ 'bs_BA', // Bosnian.
370
+ 'ca_ES', // Catalan.
371
+ 'cb_IQ', // Sorani Kurdish.
372
+ 'ck_US', // Cherokee.
373
+ 'co_FR', // Corsican.
374
+ 'cs_CZ', // Czech.
375
+ 'cx_PH', // Cebuano.
376
+ 'cy_GB', // Welsh.
377
+ 'da_DK', // Danish.
378
+ 'de_DE', // German.
379
+ 'el_GR', // Greek.
380
+ 'en_GB', // English (UK).
381
+ 'en_PI', // English (Pirate).
382
+ 'en_UD', // English (Upside Down).
383
+ 'en_US', // English (US).
384
+ 'em_ZM',
385
+ 'eo_EO', // Esperanto.
386
+ 'es_ES', // Spanish (Spain).
387
+ 'es_LA', // Spanish.
388
+ 'es_MX', // Spanish (Mexico).
389
+ 'et_EE', // Estonian.
390
+ 'eu_ES', // Basque.
391
+ 'fa_IR', // Persian.
392
+ 'fb_LT', // Leet Speak.
393
+ 'ff_NG', // Fulah.
394
+ 'fi_FI', // Finnish.
395
+ 'fo_FO', // Faroese.
396
+ 'fr_CA', // French (Canada).
397
+ 'fr_FR', // French (France).
398
+ 'fy_NL', // Frisian.
399
+ 'ga_IE', // Irish.
400
+ 'gl_ES', // Galician.
401
+ 'gn_PY', // Guarani.
402
+ 'gu_IN', // Gujarati.
403
+ 'gx_GR', // Classical Greek.
404
+ 'ha_NG', // Hausa.
405
+ 'he_IL', // Hebrew.
406
+ 'hi_IN', // Hindi.
407
+ 'hr_HR', // Croatian.
408
+ 'hu_HU', // Hungarian.
409
+ 'ht_HT', // Haitian Creole.
410
+ 'hy_AM', // Armenian.
411
+ 'id_ID', // Indonesian.
412
+ 'ig_NG', // Igbo.
413
+ 'is_IS', // Icelandic.
414
+ 'it_IT', // Italian.
415
+ 'ik_US',
416
+ 'iu_CA',
417
+ 'ja_JP', // Japanese.
418
+ 'ja_KS', // Japanese (Kansai).
419
+ 'jv_ID', // Javanese.
420
+ 'ka_GE', // Georgian.
421
+ 'kk_KZ', // Kazakh.
422
+ 'km_KH', // Khmer.
423
+ 'kn_IN', // Kannada.
424
+ 'ko_KR', // Korean.
425
+ 'ks_IN', // Kashmiri.
426
+ 'ku_TR', // Kurdish (Kurmanji).
427
+ 'ky_KG', // Kyrgyz.
428
+ 'la_VA', // Latin.
429
+ 'lg_UG', // Ganda.
430
+ 'li_NL', // Limburgish.
431
+ 'ln_CD', // Lingala.
432
+ 'lo_LA', // Lao.
433
+ 'lt_LT', // Lithuanian.
434
+ 'lv_LV', // Latvian.
435
+ 'mg_MG', // Malagasy.
436
+ 'mi_NZ', // Maori.
437
+ 'mk_MK', // Macedonian.
438
+ 'ml_IN', // Malayalam.
439
+ 'mn_MN', // Mongolian.
440
+ 'mr_IN', // Marathi.
441
+ 'ms_MY', // Malay.
442
+ 'mt_MT', // Maltese.
443
+ 'my_MM', // Burmese.
444
+ 'nb_NO', // Norwegian (bokmal).
445
+ 'nd_ZW', // Ndebele.
446
+ 'ne_NP', // Nepali.
447
+ 'nl_BE', // Dutch (Belgie).
448
+ 'nl_NL', // Dutch.
449
+ 'nn_NO', // Norwegian (nynorsk).
450
+ 'nr_ZA', // Southern Ndebele.
451
+ 'ns_ZA', // Northern Sotho.
452
+ 'ny_MW', // Chewa.
453
+ 'om_ET', // Oromo.
454
+ 'or_IN', // Oriya.
455
+ 'pa_IN', // Punjabi.
456
+ 'pl_PL', // Polish.
457
+ 'ps_AF', // Pashto.
458
+ 'pt_BR', // Portuguese (Brazil).
459
+ 'pt_PT', // Portuguese (Portugal).
460
+ 'qc_GT', // Quiché.
461
+ 'qu_PE', // Quechua.
462
+ 'qr_GR',
463
+ 'qz_MM', // Burmese (Zawgyi).
464
+ 'rm_CH', // Romansh.
465
+ 'ro_RO', // Romanian.
466
+ 'ru_RU', // Russian.
467
+ 'rw_RW', // Kinyarwanda.
468
+ 'sa_IN', // Sanskrit.
469
+ 'sc_IT', // Sardinian.
470
+ 'se_NO', // Northern Sami.
471
+ 'si_LK', // Sinhala.
472
+ 'su_ID', // Sundanese.
473
+ 'sk_SK', // Slovak.
474
+ 'sl_SI', // Slovenian.
475
+ 'sn_ZW', // Shona.
476
+ 'so_SO', // Somali.
477
+ 'sq_AL', // Albanian.
478
+ 'sr_RS', // Serbian.
479
+ 'ss_SZ', // Swazi.
480
+ 'st_ZA', // Southern Sotho.
481
+ 'sv_SE', // Swedish.
482
+ 'sw_KE', // Swahili.
483
+ 'sy_SY', // Syriac.
484
+ 'sz_PL', // Silesian.
485
+ 'ta_IN', // Tamil.
486
+ 'te_IN', // Telugu.
487
+ 'tg_TJ', // Tajik.
488
+ 'th_TH', // Thai.
489
+ 'tk_TM', // Turkmen.
490
+ 'tl_PH', // Filipino.
491
+ 'tl_ST', // Klingon.
492
+ 'tn_BW', // Tswana.
493
+ 'tr_TR', // Turkish.
494
+ 'ts_ZA', // Tsonga.
495
+ 'tt_RU', // Tatar.
496
+ 'tz_MA', // Tamazight.
497
+ 'uk_UA', // Ukrainian.
498
+ 'ur_PK', // Urdu.
499
+ 'uz_UZ', // Uzbek.
500
+ 've_ZA', // Venda.
501
+ 'vi_VN', // Vietnamese.
502
+ 'wo_SN', // Wolof.
503
+ 'xh_ZA', // Xhosa.
504
+ 'yi_DE', // Yiddish.
505
+ 'yo_NG', // Yoruba.
506
+ 'zh_CN', // Simplified Chinese (China).
507
+ 'zh_HK', // Traditional Chinese (Hong Kong).
508
+ 'zh_TW', // Traditional Chinese (Taiwan).
509
+ 'zu_ZA', // Zulu.
510
+ 'zz_TR', // Zazaki.
511
+ ];
512
+
513
+ // Catch some weird locales served out by WP that are not easily doubled up.
514
+ $fixLocales = [
515
+ 'ca' => 'ca_ES',
516
+ 'en' => 'en_US',
517
+ 'el' => 'el_GR',
518
+ 'et' => 'et_EE',
519
+ 'ja' => 'ja_JP',
520
+ 'sq' => 'sq_AL',
521
+ 'uk' => 'uk_UA',
522
+ 'vi' => 'vi_VN',
523
+ 'zh' => 'zh_CN',
524
+ ];
525
+
526
+ if ( isset( $fixLocales[ $locale ] ) ) {
527
+ $locale = $fixLocales[ $locale ];
528
+ }
529
+
530
+ // Convert locales like "es" to "es_ES", in case that works for the given locale (sometimes it does).
531
+ if ( 2 === strlen( $locale ) ) {
532
+ $locale = strtolower( $locale ) . '_' . strtoupper( $locale );
533
+ }
534
+
535
+ // Check to see if the locale is a valid FB one, if not, use en_US as a fallback.
536
+ if ( ! in_array( $locale, $validLocales, true ) ) {
537
+ $locale = strtolower( substr( $locale, 0, 2 ) ) . '_' . strtoupper( substr( $locale, 0, 2 ) );
538
+
539
+ if ( ! in_array( $locale, $validLocales, true ) ) {
540
+ $locale = 'en_US';
541
+ }
542
+ }
543
+
544
+ return apply_filters( 'aioseo_og_locale', $locale );
545
+ }
546
  }
app/Common/Social/Helpers.php DELETED
@@ -1,69 +0,0 @@
1
- <?php
2
- namespace AIOSEO\Plugin\Common\Social;
3
-
4
- // Exit if accessed directly.
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- }
8
-
9
- /**
10
- * Contains helper methods specific to the Social Meta.
11
- *
12
- * @since 4.0.0
13
- */
14
- class Helpers {
15
- /**
16
- * Returns all categories for a post.
17
- *
18
- * @since 4.0.0
19
- *
20
- * @param int $postId The post ID.
21
- * @return array $names The category names.
22
- */
23
- public function getAllCategories( $postId = 0 ) {
24
- $names = [];
25
- $categories = get_the_category( $postId );
26
- if ( $categories && count( $categories ) ) {
27
- foreach ( $categories as $category ) {
28
- $names[] = aioseo()->helpers->internationalize( $category->cat_name );
29
- }
30
- }
31
- return $names;
32
- }
33
-
34
- /**
35
- * Returns all tags for a post.
36
- *
37
- * @since 4.0.0
38
- *
39
- * @param int $postId The post ID.
40
- * @return array $names The tag names.
41
- */
42
- public function getAllTags( $postId = 0 ) {
43
- $names = [];
44
-
45
- $tags = get_the_tags( $postId );
46
- if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
47
- foreach ( $tags as $tag ) {
48
- if ( ! empty( $tag->name ) ) {
49
- $names[] = aioseo()->helpers->internationalize( $tag->name );
50
- }
51
- }
52
- }
53
-
54
- // Ultimate Tag Warrior integration.
55
- global $utw;
56
- if ( is_object( $utw ) ) {
57
- $tags = $utw->GetTagsForPost( $postId );
58
- if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
59
- foreach ( $tags as $tag ) {
60
- if ( ! empty( $tag->tag ) ) {
61
- $names[] = stripslashes( preg_replace( '#(-|_)#', $tag->tag ) );
62
- }
63
- }
64
- }
65
- }
66
-
67
- return $names;
68
- }
69
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Common/Social/Output.php CHANGED
@@ -46,6 +46,7 @@ class Output {
46
  }
47
 
48
  $meta = [
 
49
  'og:site_name' => aioseo()->helpers->encodeOutputHtml( aioseo()->social->facebook->getSiteName() ),
50
  'og:type' => aioseo()->social->facebook->getObjectType(),
51
  'og:title' => aioseo()->helpers->encodeOutputHtml( aioseo()->social->facebook->getTitle() ),
46
  }
47
 
48
  $meta = [
49
+ 'og:locale' => aioseo()->social->facebook->getLocale(),
50
  'og:site_name' => aioseo()->helpers->encodeOutputHtml( aioseo()->social->facebook->getSiteName() ),
51
  'og:type' => aioseo()->social->facebook->getObjectType(),
52
  'og:title' => aioseo()->helpers->encodeOutputHtml( aioseo()->social->facebook->getTitle() ),
app/Common/Social/Social.php CHANGED
@@ -30,7 +30,6 @@ class Social {
30
  $this->facebook = new Facebook();
31
  $this->twitter = new Twitter();
32
  $this->output = new Output();
33
- $this->helpers = new Helpers();
34
 
35
  $this->hooks();
36
  }
30
  $this->facebook = new Facebook();
31
  $this->twitter = new Twitter();
32
  $this->output = new Output();
 
33
 
34
  $this->hooks();
35
  }
app/Common/Social/Twitter.php CHANGED
@@ -58,7 +58,8 @@ class Twitter {
58
  $post = aioseo()->helpers->getPost();
59
  if ( $post && aioseo()->options->social->twitter->general->showAuthor ) {
60
  $twitterUser = get_the_author_meta( 'aioseo_twitter', $post->post_author );
61
- $author = aioseo()->social->twitter->prepareUsername( $twitterUser );
 
62
  }
63
  return $author;
64
  }
@@ -224,7 +225,7 @@ class Twitter {
224
  }
225
 
226
  if ( ! empty( $post->post_content ) ) {
227
- $minutes = aioseo()->helpers->getReadingTime( $post->post_content );
228
  if ( ! empty( $minutes ) ) {
229
  $data[] = [
230
  'label' => __( 'Est. reading time', 'all-in-one-seo-pack' ),
@@ -236,4 +237,18 @@ class Twitter {
236
 
237
  return $data;
238
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  }
58
  $post = aioseo()->helpers->getPost();
59
  if ( $post && aioseo()->options->social->twitter->general->showAuthor ) {
60
  $twitterUser = get_the_author_meta( 'aioseo_twitter', $post->post_author );
61
+ $author = $twitterUser ? $twitterUser : aioseo()->social->twitter->getTwitterUrl();
62
+ $author = aioseo()->social->twitter->prepareUsername( $author );
63
  }
64
  return $author;
65
  }
225
  }
226
 
227
  if ( ! empty( $post->post_content ) ) {
228
+ $minutes = $this->getReadingTime( $post->post_content );
229
  if ( ! empty( $minutes ) ) {
230
  $data[] = [
231
  'label' => __( 'Est. reading time', 'all-in-one-seo-pack' ),
237
 
238
  return $data;
239
  }
240
+
241
+ /**
242
+ * Returns the estimated reading time for a string.
243
+ *
244
+ * @since 4.0.0
245
+ *
246
+ * @param string $string The string to count.
247
+ * @return integer The estimated reading time as an integer.
248
+ */
249
+ private function getReadingTime( $string ) {
250
+ $wpm = 200;
251
+ $word = str_word_count( wp_strip_all_tags( $string ) );
252
+ return round( $word / $wpm );
253
+ }
254
  }
app/Common/Tools/Htaccess.php CHANGED
@@ -38,7 +38,8 @@ class Htaccess {
38
  return false;
39
  }
40
 
41
- return @$wpfs->get_contents( $this->path );
 
42
  }
43
 
44
  /**
38
  return false;
39
  }
40
 
41
+ $contents = @$wpfs->get_contents( $this->path );
42
+ return aioseo()->helpers->encodeOutputHtml( $contents );
43
  }
44
 
45
  /**
app/Common/Tools/RobotsTxt.php CHANGED
@@ -39,7 +39,6 @@ class RobotsTxt {
39
  }
40
 
41
  $original = explode( "\n", $original );
42
- $sitemapUrls = implode( "\r\n", array_merge( aioseo()->sitemap->helpers->getSitemapUrls(), $this->extractSitemapUrls( $original ) ) );
43
  $originalRules = $this->extractRules( $original );
44
  $networkRules = [];
45
  if ( is_multisite() ) {
@@ -53,13 +52,13 @@ class RobotsTxt {
53
  if ( ! aioseo()->options->tools->robots->enable ) {
54
  $networkAndOriginal = $this->mergeRules( $originalRules, $this->parseRules( $networkRules ) );
55
  $networkAndOriginal = $this->robotsArrayUnique( $networkAndOriginal );
56
- return $this->stringify( $networkAndOriginal ) . "\r\n" . $sitemapUrls;
57
  }
58
 
59
  $allRules = $this->mergeRules( $originalRules, $this->mergeRules( $this->parseRules( $networkRules ), $this->parseRules( aioseo()->options->tools->robots->rules ) ), true );
60
  $allRules = $this->robotsArrayUnique( $allRules );
61
 
62
- return $this->stringify( $allRules ) . "\r\n" . $sitemapUrls;
63
  }
64
 
65
  /**
@@ -172,9 +171,10 @@ class RobotsTxt {
172
  * Stringifies the parsed rules.
173
  *
174
  * @param array $allRules The rules array.
 
175
  * @return string The stringified rules.
176
  */
177
- private function stringify( $allRules ) {
178
  $robots = [];
179
  foreach ( $allRules as $agent => $rules ) {
180
  if ( empty( $agent ) ) {
@@ -195,7 +195,16 @@ class RobotsTxt {
195
 
196
  $robots[] = '';
197
  }
198
- return implode( "\r\n", $robots );
 
 
 
 
 
 
 
 
 
199
  }
200
 
201
  /**
@@ -231,7 +240,7 @@ class RobotsTxt {
231
  * @param array $lines The lines to extract from.
232
  * @return array An array of extracted rules.
233
  */
234
- private function extractRules( $lines ) {
235
  $rules = [];
236
  $userAgent = null;
237
  foreach ( $lines as $line ) {
@@ -379,6 +388,20 @@ class RobotsTxt {
379
  $currentRules = $this->parseRules( aioseo()->options->tools->robots->rules );
380
  $allRules = $this->mergeRules( $currentRules, $allRules, false, true );
381
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  $robots = [];
383
  foreach ( $allRules as $userAgent => $rules ) {
384
  if ( empty( $userAgent ) ) {
@@ -407,9 +430,7 @@ class RobotsTxt {
407
  }
408
  }
409
 
410
- aioseo()->options->tools->robots->rules = $robots;
411
-
412
- return true;
413
  }
414
 
415
  /**
39
  }
40
 
41
  $original = explode( "\n", $original );
 
42
  $originalRules = $this->extractRules( $original );
43
  $networkRules = [];
44
  if ( is_multisite() ) {
52
  if ( ! aioseo()->options->tools->robots->enable ) {
53
  $networkAndOriginal = $this->mergeRules( $originalRules, $this->parseRules( $networkRules ) );
54
  $networkAndOriginal = $this->robotsArrayUnique( $networkAndOriginal );
55
+ return $this->stringify( $networkAndOriginal, $original );
56
  }
57
 
58
  $allRules = $this->mergeRules( $originalRules, $this->mergeRules( $this->parseRules( $networkRules ), $this->parseRules( aioseo()->options->tools->robots->rules ) ), true );
59
  $allRules = $this->robotsArrayUnique( $allRules );
60
 
61
+ return $this->stringify( $allRules, $original );
62
  }
63
 
64
  /**
171
  * Stringifies the parsed rules.
172
  *
173
  * @param array $allRules The rules array.
174
+ * @param string $original The original robots.txt content.
175
  * @return string The stringified rules.
176
  */
177
+ private function stringify( $allRules, $original ) {
178
  $robots = [];
179
  foreach ( $allRules as $agent => $rules ) {
180
  if ( empty( $agent ) ) {
195
 
196
  $robots[] = '';
197
  }
198
+
199
+ $robots = implode( "\r\n", $robots ) . "\r\n";
200
+
201
+ $sitemapUrls = array_merge( aioseo()->sitemap->helpers->getSitemapUrls(), $this->extractSitemapUrls( $original ) );
202
+ if ( ! empty( $sitemapUrls ) ) {
203
+ $sitemapUrls = implode( "\r\n", $sitemapUrls );
204
+ $robots .= $sitemapUrls . "\r\n\r\n";
205
+ }
206
+
207
+ return $robots;
208
  }
209
 
210
  /**
240
  * @param array $lines The lines to extract from.
241
  * @return array An array of extracted rules.
242
  */
243
+ public function extractRules( $lines ) {
244
  $rules = [];
245
  $userAgent = null;
246
  foreach ( $lines as $line ) {
388
  $currentRules = $this->parseRules( aioseo()->options->tools->robots->rules );
389
  $allRules = $this->mergeRules( $currentRules, $allRules, false, true );
390
 
391
+ aioseo()->options->tools->robots->rules = aioseo()->robotsTxt->prepareRobotsTxt( $allRules );
392
+
393
+ return true;
394
+ }
395
+
396
+ /**
397
+ * Prepare robots.txt rules to save.
398
+ *
399
+ * @since 4.1.4
400
+ *
401
+ * @param array $allRules Array with the rules.
402
+ * @return array The prepared rules array.
403
+ */
404
+ public function prepareRobotsTxt( $allRules = [] ) {
405
  $robots = [];
406
  foreach ( $allRules as $userAgent => $rules ) {
407
  if ( empty( $userAgent ) ) {
430
  }
431
  }
432
 
433
+ return $robots;
 
 
434
  }
435
 
436
  /**
app/Common/Traits/Helpers/ActionScheduler.php CHANGED
@@ -49,4 +49,16 @@ trait ActionScheduler {
49
  ]);
50
  return ! empty( $actions );
51
  }
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
49
  ]);
50
  return ! empty( $actions );
51
  }
52
+
53
+ /**
54
+ * Unschedule an action.
55
+ *
56
+ * @since 4.1.4
57
+ *
58
+ * @param string $actionName The action name to unschedule.
59
+ * @return void
60
+ */
61
+ public function unscheduleAction( $actionName ) {
62
+ as_unschedule_action( $actionName, [], 'aioseo' );
63
+ }
64
  }
app/Common/Traits/Helpers/Arrays.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Contains array specific helper methods.
11
+ *
12
+ * @since 4.1.4
13
+ */
14
+ trait Arrays {
15
+ /**
16
+ * Unsets a given value in a given array.
17
+ * This should only be used if the given value only appears once in the array.
18
+ *
19
+ * @since 4.0.0
20
+ *
21
+ * @param array $array The array.
22
+ * @param string $value The value that needs to be removed from the array.
23
+ * @return array $array The filtered array.
24
+ */
25
+ public function unsetValue( $array, $value ) {
26
+ if ( in_array( $value, $array, true ) ) {
27
+ unset( $array[ array_search( $value, $array, true ) ] );
28
+ };
29
+ return $array;
30
+ }
31
+
32
+ /**
33
+ * Compares two multidimensional arrays to see if they're different.
34
+ *
35
+ * @since 4.0.0
36
+ *
37
+ * @param array $array1 The first array.
38
+ * @param array $array2 The second array.
39
+ * @return boolean Whether the arrays are different.
40
+ */
41
+ public function arraysDifferent( $array1, $array2 ) {
42
+ foreach ( $array1 as $key => $value ) {
43
+ // Check for non-existing values.
44
+ if ( ! isset( $array2[ $key ] ) ) {
45
+ return true;
46
+ }
47
+ if ( is_array( $value ) ) {
48
+ if ( $this->arraysDifferent( $value, $array2[ $key ] ) ) {
49
+ return true;
50
+ };
51
+ } else {
52
+ if ( $value !== $array2[ $key ] ) {
53
+ return true;
54
+ }
55
+ }
56
+ }
57
+ return false;
58
+ }
59
+
60
+ /**
61
+ * Checks whether the given array is associative.
62
+ * Arrays that only have consecutive, sequential numeric keys are numeric.
63
+ * Otherwise they are associative.
64
+ *
65
+ * @since 4.1.4
66
+ *
67
+ * @param array $array The array.
68
+ * @return bool Whether the array is associative.
69
+ */
70
+ public function isArrayAssociative( $array ) {
71
+ return 0 < count( array_filter( array_keys( $array ), 'is_string' ) );
72
+ }
73
+
74
+ /**
75
+ * Checks whether the given array is numeric.
76
+ *
77
+ * @since 4.1.4
78
+ *
79
+ * @param array $array The array.
80
+ * @return bool Whether the array is numeric.
81
+ */
82
+ public function isArrayNumeric( $array ) {
83
+ return ! $this->isArrayAssociative( $array );
84
+ }
85
+ }
app/Common/Traits/Helpers/Constants.php CHANGED
@@ -8,6 +8,20 @@ namespace AIOSEO\Plugin\Common\Traits\Helpers;
8
  * @since 4.0.17
9
  */
10
  trait Constants {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  * Returns the country name by code.
13
  *
@@ -21,7 +35,7 @@ trait Constants {
21
  }
22
 
23
  /**
24
- * Country list
25
  *
26
  * @since 4.0.17
27
  *
8
  * @since 4.0.17
9
  */
10
  trait Constants {
11
+ /**
12
+ * Returns the All in One SEO Logo
13
+ *
14
+ * @since 4.0.0
15
+ *
16
+ * @param string $width The width of the image.
17
+ * @param string $height The height of the image.
18
+ * @param string $colorCode The color of the image.
19
+ * @return string The logo as a string.
20
+ */
21
+ public function logo( $width, $height, $colorCode ) {
22
+ return '<svg viewBox="0 0 20 20" width="' . $width . '" height="' . $height . '" fill="none" xmlns="http://www.w3.org/2000/svg" class="aioseo-gear"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.98542 19.9708C15.5002 19.9708 19.9708 15.5002 19.9708 9.98542C19.9708 4.47063 15.5002 0 9.98542 0C4.47063 0 0 4.47063 0 9.98542C0 15.5002 4.47063 19.9708 9.98542 19.9708ZM8.39541 3.65464C8.26016 3.4485 8.0096 3.35211 7.77985 3.43327C7.51816 3.52572 7.26218 3.63445 7.01349 3.7588C6.79519 3.86796 6.68566 4.11731 6.73372 4.36049L6.90493 5.22694C6.949 5.44996 6.858 5.6763 6.68522 5.82009C6.41216 6.04734 6.16007 6.30426 5.93421 6.58864C5.79383 6.76539 5.57233 6.85907 5.35361 6.81489L4.50424 6.6433C4.26564 6.5951 4.02157 6.70788 3.91544 6.93121C3.85549 7.05738 3.79889 7.1862 3.74583 7.31758C3.69276 7.44896 3.64397 7.58105 3.59938 7.71369C3.52048 7.94847 3.61579 8.20398 3.81839 8.34133L4.53958 8.83027C4.72529 8.95617 4.81778 9.1819 4.79534 9.40826C4.75925 9.77244 4.76072 10.136 4.79756 10.4936C4.82087 10.7198 4.72915 10.9459 4.54388 11.0724L3.82408 11.5642C3.62205 11.7022 3.52759 11.9579 3.60713 12.1923C3.69774 12.4593 3.8043 12.7205 3.92615 12.9743C4.03313 13.1971 4.27749 13.3088 4.51581 13.2598L5.36495 13.0851C5.5835 13.0401 5.80533 13.133 5.94623 13.3093C6.16893 13.5879 6.42071 13.8451 6.6994 14.0756C6.87261 14.2188 6.96442 14.4448 6.92112 14.668L6.75296 15.5348C6.70572 15.7782 6.81625 16.0273 7.03511 16.1356C7.15876 16.1967 7.285 16.2545 7.41375 16.3086C7.54251 16.3628 7.67196 16.4126 7.80195 16.4581C8.18224 16.5912 8.71449 16.1147 9.108 15.7625C9.30205 15.5888 9.42174 15.343 9.42301 15.0798C9.42301 15.0784 9.42302 15.077 9.42302 15.0756L9.42301 13.6263C9.42301 13.6109 9.4236 13.5957 9.42476 13.5806C8.26248 13.2971 7.39838 12.2301 7.39838 10.9572V9.41823C7.39838 9.30125 7.49131 9.20642 7.60596 9.20642H8.32584V7.6922C8.32584 7.48312 8.49193 7.31364 8.69683 7.31364C8.90171 7.31364 9.06781 7.48312 9.06781 7.6922V9.20642H11.0155V7.6922C11.0155 7.48312 11.1816 7.31364 11.3865 7.31364C11.5914 7.31364 11.7575 7.48312 11.7575 7.6922V9.20642H12.4773C12.592 9.20642 12.6849 9.30125 12.6849 9.41823V10.9572C12.6849 12.2704 11.7653 13.3643 10.5474 13.6051C10.5477 13.6121 10.5478 13.6192 10.5478 13.6263L10.5478 15.0694C10.5478 15.3377 10.6711 15.5879 10.871 15.7622C11.2715 16.1115 11.8129 16.5837 12.191 16.4502C12.4527 16.3577 12.7086 16.249 12.9573 16.1246C13.1756 16.0155 13.2852 15.7661 13.2371 15.5229L13.0659 14.6565C13.0218 14.4334 13.1128 14.2071 13.2856 14.0633C13.5587 13.8361 13.8107 13.5792 14.0366 13.2948C14.177 13.118 14.3985 13.0244 14.6172 13.0685L15.4666 13.2401C15.7052 13.2883 15.9493 13.1756 16.0554 12.9522C16.1153 12.8261 16.1719 12.6972 16.225 12.5659C16.2781 12.4345 16.3269 12.3024 16.3714 12.1698C16.4503 11.935 16.355 11.6795 16.1524 11.5421L15.4312 11.0532C15.2455 10.9273 15.153 10.7015 15.1755 10.4752C15.2116 10.111 15.2101 9.74744 15.1733 9.38986C15.1499 9.16361 15.2417 8.93757 15.4269 8.811L16.1467 8.31927C16.3488 8.18126 16.4432 7.92558 16.3637 7.69115C16.2731 7.42411 16.1665 7.16292 16.0447 6.90915C15.9377 6.68638 15.6933 6.57462 15.455 6.62366L14.6059 6.79837C14.3873 6.84334 14.1655 6.75048 14.0246 6.57418C13.8019 6.29554 13.5501 6.03832 13.2714 5.80784C13.0982 5.6646 13.0064 5.43858 13.0497 5.2154L13.2179 4.34868C13.2651 4.10521 13.1546 3.85616 12.9357 3.74787C12.8121 3.68669 12.6858 3.62895 12.5571 3.5748C12.4283 3.52065 12.2989 3.47086 12.1689 3.42537C11.9388 3.34485 11.6884 3.44211 11.5538 3.64884L11.0746 4.38475C10.9513 4.57425 10.73 4.66862 10.5082 4.64573C10.1513 4.6089 9.79502 4.61039 9.44459 4.64799C9.22286 4.67177 9.00134 4.57818 8.87731 4.38913L8.39541 3.65464Z" fill="' . $colorCode . '" /></svg>'; // phpcs:ignore Generic.Files.LineLength.MaxExceeded
23
+ }
24
+
25
  /**
26
  * Returns the country name by code.
27
  *
35
  }
36
 
37
  /**
38
+ * Returns a list of countries.
39
  *
40
  * @since 4.0.17
41
  *
app/Common/Traits/Helpers/DateTime.php CHANGED
@@ -12,6 +12,43 @@ if ( ! defined( 'ABSPATH' ) ) {
12
  * @since 4.1.2
13
  */
14
  trait DateTime {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  /**
16
  * Formats a date in ISO8601 format.
17
  *
12
  * @since 4.1.2
13
  */
14
  trait DateTime {
15
+ /**
16
+ * Formats a timestamp as an ISO 8601 date.
17
+ *
18
+ * @since 4.0.0
19
+ *
20
+ * @param string $dateTime The raw datetime.
21
+ * @return string The formatted datetime.
22
+ */
23
+ public function formatDateTime( $dateTime ) {
24
+ return gmdate( 'c', mysql2date( 'U', $dateTime ) );
25
+ }
26
+
27
+ /**
28
+ * Returns the timezone offset.
29
+ * We use the code from wp_timezone_string() which became available in WP 5.3+
30
+ *
31
+ * @since 4.0.0
32
+ *
33
+ * @return string The timezone offset.
34
+ */
35
+ public function getTimeZoneOffset() {
36
+ $timezoneString = get_option( 'timezone_string' );
37
+ if ( $timezoneString ) {
38
+ return $timezoneString;
39
+ }
40
+
41
+ $offset = (float) get_option( 'gmt_offset' );
42
+ $hours = (int) $offset;
43
+ $minutes = ( $offset - $hours );
44
+ $sign = ( $offset < 0 ) ? '-' : '+';
45
+ $absHour = abs( $hours );
46
+ $absMins = abs( $minutes * 60 );
47
+ $tzOffset = sprintf( '%s%02d:%02d', $sign, $absHour, $absMins );
48
+
49
+ return $tzOffset;
50
+ }
51
+
52
  /**
53
  * Formats a date in ISO8601 format.
54
  *
app/Common/Traits/Helpers/Language.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Contains i18n and language (code) helper methods.
11
+ *
12
+ * @since 4.1.4
13
+ */
14
+ trait Language {
15
+ /**
16
+ * Returns the language of the current response.
17
+ *
18
+ * @since 4.1.4
19
+ *
20
+ * @return string The language code.
21
+ */
22
+ public function currentLanguageCode() {
23
+ global $wp_version;
24
+ if ( version_compare( $wp_version, '5.0', '<' ) ) {
25
+ return get_locale();
26
+ }
27
+ return determine_locale();
28
+ }
29
+
30
+ /**
31
+ * Returns the language of the current response in BCP 47 format.
32
+ *
33
+ * @since 4.1.4
34
+ *
35
+ * @return string The language code in BCP 47 format.
36
+ */
37
+ public function currentLanguageCodeBCP47() {
38
+ return str_replace( '_', '-', $this->currentLanguageCode() );
39
+ }
40
+ }
app/Common/Traits/Helpers/Strings.php CHANGED
@@ -37,6 +37,7 @@ trait Strings {
37
  * @return string The converted string.
38
  */
39
  public function toCamelCase( $string, $capitalize = false ) {
 
40
  if ( $capitalize ) {
41
  $string[0] = strtoupper( $string[0] );
42
  }
@@ -62,6 +63,71 @@ trait Strings {
62
  return $string;
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  /**
66
  * Returns string after converting it to lowercase.
67
  *
@@ -101,10 +167,65 @@ trait Strings {
101
  return false;
102
  }
103
 
104
- // Decode the string.
105
  json_decode( $string );
106
 
107
  // Return a boolean whether or not the last error matches.
108
  return json_last_error() === JSON_ERROR_NONE;
109
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
37
  * @return string The converted string.
38
  */
39
  public function toCamelCase( $string, $capitalize = false ) {
40
+ $string[0] = strtolower( $string[0] );
41
  if ( $capitalize ) {
42
  $string[0] = strtoupper( $string[0] );
43
  }
63
  return $string;
64
  }
65
 
66
+ /**
67
+ * Truncates a given string.
68
+ *
69
+ * @since 4.0.0
70
+ *
71
+ * @param string $string The string.
72
+ * @param int $maxCharacters The max. amount of characters.
73
+ * @param boolean $shouldHaveEllipsis Whether the string should have a trailing ellipsis (defaults to true).
74
+ * @return string $string The string.
75
+ */
76
+ public function truncate( $string, $maxCharacters, $shouldHaveEllipsis = true ) {
77
+ $length = strlen( $string );
78
+ $excessLength = $length - $maxCharacters;
79
+ if ( 0 < $excessLength ) {
80
+ // If the string is longer than 65535 characters, we first need to shorten it due to the character limit of the regex pattern quantifier.
81
+ if ( 65535 < $length ) {
82
+ $string = substr( $string, 0, 65534 );
83
+ }
84
+ $string = preg_replace( "#[^\pZ\pP]*.{{$excessLength}}$#", '', $string );
85
+ if ( $shouldHaveEllipsis ) {
86
+ $string = $string . ' ...';
87
+ }
88
+ }
89
+ return $string;
90
+ }
91
+
92
+ /**
93
+ * Escapes special regex characters.
94
+ *
95
+ * @since 4.0.5
96
+ *
97
+ * @param string $string The string.
98
+ * @return string The escaped string.
99
+ */
100
+ public function escapeRegex( $string ) {
101
+ return preg_quote( $string, '/' );
102
+ }
103
+
104
+ /**
105
+ * Escapes special regex characters inside the replacement string.
106
+ *
107
+ * @since 4.0.7
108
+ *
109
+ * @param string $string The string.
110
+ * @return string The escaped string.
111
+ */
112
+ public function escapeRegexReplacement( $string ) {
113
+ return str_replace( '$', '\$', $string );
114
+ }
115
+
116
+ /**
117
+ * preg_replace but with the replacement escaped.
118
+ *
119
+ * @since 4.0.10
120
+ *
121
+ * @param string $pattern The pattern to search for.
122
+ * @param string $replacement The replacement string.
123
+ * @param string $subject The subject to search in.
124
+ * @return string The subject with matches replaced.
125
+ */
126
+ public function pregReplace( $pattern, $replacement, $subject ) {
127
+ $replacement = $this->escapeRegexReplacement( $replacement );
128
+ return preg_replace( $pattern, $replacement, $subject );
129
+ }
130
+
131
  /**
132
  * Returns string after converting it to lowercase.
133
  *
167
  return false;
168
  }
169
 
 
170
  json_decode( $string );
171
 
172
  // Return a boolean whether or not the last error matches.
173
  return json_last_error() === JSON_ERROR_NONE;
174
  }
175
+
176
+ /**
177
+ * Strips punctuation from a given string.
178
+ *
179
+ * @since 4.0.0
180
+ *
181
+ * @param string $string The string.
182
+ * @return string The string without punctuation.
183
+ */
184
+ public function stripPunctuation( $string ) {
185
+ $string = preg_replace( '#\p{P}#u', '', $string );
186
+ // Trim both internal and external whitespace.
187
+ return preg_replace( '/\s\s+/u', ' ', trim( $string ) );
188
+ }
189
+
190
+ /**
191
+ * Returns the string after it is encoded with htmlspecialchars().
192
+ *
193
+ * @since 4.0.0
194
+ *
195
+ * @param string $string The string to encode.
196
+ * @return string The encoded string.
197
+ */
198
+ public function encodeOutputHtml( $string ) {
199
+ return htmlspecialchars( $string, ENT_COMPAT | ENT_HTML401, get_option( 'blog_charset' ), false );
200
+ }
201
+
202
+ /**
203
+ * Returns the string after all HTML entities have been decoded.
204
+ *
205
+ * @since 4.0.0
206
+ *
207
+ * @param string $string The string to decode.
208
+ * @return string The decoded string.
209
+ */
210
+ public function decodeHtmlEntities( $string ) {
211
+ return html_entity_decode( (string) $string, ENT_QUOTES );
212
+ }
213
+
214
+ /**
215
+ * Returns the given JSON formatted data tags as a comma separated list with their values instead.
216
+ *
217
+ * @since 4.1.0
218
+ *
219
+ * @param string $tags The JSON formatted data tags.
220
+ * @return string The comma separated values.
221
+ */
222
+ public function jsonTagsToCommaSeparatedList( $tags ) {
223
+ $tags = json_decode( $tags );
224
+
225
+ $values = [];
226
+ foreach ( $tags as $k => $tag ) {
227
+ $values[ $k ] = $tag->value;
228
+ }
229
+ return implode( ',', $values );
230
+ }
231
  }
app/Common/Traits/Helpers/Svg.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Contains SVG specific helper methods.
11
+ *
12
+ * @since 4.1.4
13
+ */
14
+ trait Svg {
15
+ /**
16
+ * Sanitizes a SVG string.
17
+ *
18
+ * @since 4.1.4
19
+ *
20
+ * @param string $svgString The SVG to check.
21
+ * @return string The sanitized SVG.
22
+ */
23
+ public function escSvg( $svgString ) {
24
+ if ( ! is_string( $svgString ) ) {
25
+ return false;
26
+ }
27
+
28
+ $ksesDefaults = wp_kses_allowed_html( 'post' );
29
+
30
+ $svgArgs = [
31
+ 'svg' => [
32
+ 'class' => true,
33
+ 'aria-hidden' => true,
34
+ 'aria-labelledby' => true,
35
+ 'role' => true,
36
+ 'xmlns' => true,
37
+ 'width' => true,
38
+ 'height' => true,
39
+ 'viewbox' => true, // <= Must be lower case!
40
+ ],
41
+ 'g' => [ 'fill' => true ],
42
+ 'title' => [ 'title' => true ],
43
+ 'path' => [
44
+ 'd' => true,
45
+ 'fill' => true,
46
+ ]
47
+ ];
48
+
49
+ return wp_kses( $svgString, array_merge( $ksesDefaults, $svgArgs ) );
50
+ }
51
+ }
app/Common/Traits/Helpers/ThirdParty.php ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Contains all third-party related helper methods.
11
+ *
12
+ * @since 4.1.4
13
+ */
14
+ trait ThirdParty {
15
+ /**
16
+ * Checks whether WooCommerce is active.
17
+ *
18
+ * @since 4.0.0
19
+ *
20
+ * @return boolean Whether WooCommerce is active.
21
+ */
22
+ public function isWooCommerceActive() {
23
+ return class_exists( 'woocommerce' );
24
+ }
25
+
26
+ /**
27
+ * Returns if the page is a WooCommerce page (Cart, Checkout, ...).
28
+ *
29
+ * @since 4.0.0
30
+ *
31
+ * @param int $postId The post ID.
32
+ * @return boolean Whether the page is a WooCommerce page or not.
33
+ */
34
+ public function isWooCommercePage( $postId = false ) {
35
+ if ( ! $this->isWooCommerceActive() ) {
36
+ return false;
37
+ }
38
+
39
+ static $cartPageId;
40
+ if ( ! $cartPageId ) {
41
+ $cartPageId = (int) get_option( 'woocommerce_cart_page_id' );
42
+ }
43
+
44
+ static $checkoutPageId;
45
+ if ( ! $checkoutPageId ) {
46
+ $checkoutPageId = (int) get_option( 'woocommerce_checkout_page_id' );
47
+ }
48
+
49
+ static $myAccountPageId;
50
+ if ( ! $myAccountPageId ) {
51
+ $myAccountPageId = (int) get_option( 'woocommerce_myaccount_page_id' );
52
+ }
53
+
54
+ static $termsPageId;
55
+ if ( ! $termsPageId ) {
56
+ $termsPageId = (int) get_option( 'woocommerce_terms_page_id' );
57
+ }
58
+
59
+ if (
60
+ $cartPageId === (int) $postId ||
61
+ $checkoutPageId === (int) $postId ||
62
+ $myAccountPageId === (int) $postId ||
63
+ $termsPageId === (int) $postId
64
+ ) {
65
+ return true;
66
+ }
67
+
68
+ return false;
69
+ }
70
+
71
+ /**
72
+ * Checks whether the queried object is the WooCommerce shop page.
73
+ *
74
+ * @since 4.0.0
75
+ *
76
+ * @param int $id The post ID to check against (optional).
77
+ * @return bool Whether the current page is the WooCommerce shop page.
78
+ */
79
+ public function isWooCommerceShopPage( $id = 0 ) {
80
+ if ( ! $this->isWooCommerceActive() ) {
81
+ return false;
82
+ }
83
+
84
+ if ( ! is_admin() && ! aioseo()->helpers->isAjaxCronRest() && function_exists( 'is_shop' ) ) {
85
+ return is_shop();
86
+ }
87
+
88
+ $id = ! $id && ! empty( $_GET['post'] ) ? (int) wp_unslash( $_GET['post'] ) : (int) $id; // phpcs:ignore HM.Security.ValidatedSanitizedInput
89
+ return $id && wc_get_page_id( 'shop' ) === $id;
90
+ }
91
+
92
+ /**
93
+ * Checks whether the queried object is the WooCommerce cart page.
94
+ *
95
+ * @since 4.1.3
96
+ *
97
+ * @param int $id The post ID to check against (optional).
98
+ * @return bool Whether the current page is the WooCommerce cart page.
99
+ */
100
+ public function isWooCommerceCartPage( $id = 0 ) {
101
+ if ( ! $this->isWooCommerceActive() ) {
102
+ return false;
103
+ }
104
+
105
+ if ( ! is_admin() && ! aioseo()->helpers->isAjaxCronRest() && function_exists( 'is_cart' ) ) {
106
+ return is_cart();
107
+ }
108
+
109
+ $id = ! $id && ! empty( $_GET['post'] ) ? (int) wp_unslash( $_GET['post'] ) : (int) $id; // phpcs:ignore HM.Security.ValidatedSanitizedInput
110
+ return $id && wc_get_page_id( 'cart' ) === $id;
111
+ }
112
+
113
+ /**
114
+ * Checks whether the queried object is the WooCommerce checkout page.
115
+ *
116
+ * @since 4.1.3
117
+ *
118
+ * @param int $id The post ID to check against (optional).
119
+ * @return bool Whether the current page is the WooCommerce checkout page.
120
+ */
121
+ public function isWooCommerceCheckoutPage( $id = 0 ) {
122
+ if ( ! $this->isWooCommerceActive() ) {
123
+ return false;
124
+ }
125
+
126
+ if ( ! is_admin() && ! aioseo()->helpers->isAjaxCronRest() && function_exists( 'is_checkout' ) ) {
127
+ return is_checkout();
128
+ }
129
+
130
+ $id = ! $id && ! empty( $_GET['post'] ) ? (int) wp_unslash( $_GET['post'] ) : (int) $id; // phpcs:ignore HM.Security.ValidatedSanitizedInput
131
+ return $id && wc_get_page_id( 'checkout' ) === $id;
132
+ }
133
+
134
+ /**
135
+ * Checks whether the queried object is the WooCommerce account page.
136
+ *
137
+ * @since 4.1.3
138
+ *
139
+ * @param int $id The post ID to check against (optional).
140
+ * @return bool Whether the current page is the WooCommerce account page.
141
+ */
142
+ public function isWooCommerceAccountPage( $id = 0 ) {
143
+ if ( ! $this->isWooCommerceActive() ) {
144
+ return false;
145
+ }
146
+
147
+ if ( ! is_admin() && ! aioseo()->helpers->isAjaxCronRest() && function_exists( 'is_account_page' ) ) {
148
+ return is_account_page();
149
+ }
150
+
151
+ $id = ! $id && ! empty( $_GET['post'] ) ? (int) wp_unslash( $_GET['post'] ) : (int) $id; // phpcs:ignore HM.Security.ValidatedSanitizedInput
152
+ return $id && wc_get_page_id( 'myaccount' ) === $id;
153
+ }
154
+
155
+ /**
156
+ * Internationalize.
157
+ *
158
+ * @since 4.0.0
159
+ *
160
+ * @param $in
161
+ * @return mixed|void
162
+ */
163
+ public function internationalize( $in ) {
164
+ if ( function_exists( 'langswitch_filter_langs_with_message' ) ) {
165
+ $in = langswitch_filter_langs_with_message( $in );
166
+ }
167
+
168
+ if ( function_exists( 'polyglot_filter' ) ) {
169
+ $in = polyglot_filter( $in );
170
+ }
171
+
172
+ if ( function_exists( 'qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) ) {
173
+ $in = qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage( $in );
174
+ } elseif ( function_exists( 'ppqtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) ) {
175
+ $in = ppqtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage( $in );
176
+ } elseif ( function_exists( 'qtranxf_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) ) {
177
+ $in = qtranxf_useCurrentLanguageIfNotFoundUseDefaultLanguage( $in );
178
+ }
179
+
180
+ return apply_filters( 'localization', $in );
181
+ }
182
+
183
+ /**
184
+ * Checks if WPML is active.
185
+ *
186
+ * @since 4.0.0
187
+ *
188
+ * @return bool True if it is, false if not.
189
+ */
190
+ public function isWpmlActive() {
191
+ return class_exists( 'SitePress' );
192
+ }
193
+
194
+ /**
195
+ * Localizes a given URL.
196
+ *
197
+ * This is required for compatibility with WPML.
198
+ *
199
+ * @since 4.0.0
200
+ *
201
+ * @param string $path The relative path of the URL.
202
+ * @return string $url The filtered URL.
203
+ */
204
+ public function localizedUrl( $path ) {
205
+ $url = apply_filters( 'wpml_home_url', home_url( '/' ) );
206
+
207
+ // Remove URL parameters.
208
+ preg_match_all( '/\?[\s\S]+/', $url, $matches );
209
+
210
+ // Get the base URL.
211
+ $url = preg_replace( '/\?[\s\S]+/', '', $url );
212
+ $url = trailingslashit( $url );
213
+ $url .= preg_replace( '/\//', '', $path, 1 );
214
+
215
+ // Readd URL parameters.
216
+ if ( $matches && $matches[0] ) {
217
+ $url .= $matches[0][0];
218
+ }
219
+
220
+ return $url;
221
+ }
222
+
223
+ /**
224
+ * Checks whether BuddyPress is active.
225
+ *
226
+ * @since 4.0.0
227
+ *
228
+ * @return boolean
229
+ */
230
+ public function isBuddyPressActive() {
231
+ return class_exists( 'BuddyPress' );
232
+ }
233
+
234
+ /**
235
+ * Checks whether the queried object is a buddy press user page.
236
+ *
237
+ * @since 4.0.0
238
+ *
239
+ * @return boolean
240
+ */
241
+ public function isBuddyPressUser() {
242
+ return $this->isBuddyPressActive() && function_exists( 'bp_is_user' ) && bp_is_user();
243
+ }
244
+
245
+ /**
246
+ * Returns if the page is a BuddyPress page (Activity, Members, Groups).
247
+ *
248
+ * @since 4.0.0
249
+ *
250
+ * @param int $postId The post ID.
251
+ * @return boolean If the page is a BuddyPress page or not.
252
+ */
253
+ public function isBuddyPressPage( $postId = false ) {
254
+ $bpPages = get_option( 'bp-pages' );
255
+
256
+ if ( empty( $bpPages ) ) {
257
+ return false;
258
+ }
259
+
260
+ foreach ( $bpPages as $page ) {
261
+ if ( (int) $page === (int) $postId ) {
262
+ return true;
263
+ }
264
+ }
265
+
266
+ return false;
267
+ }
268
+
269
+ /**
270
+ * Returns ACF fields as an array of meta keys and values.
271
+ *
272
+ * @since 4.0.6
273
+ *
274
+ * @param WP_Post|int $post The post.
275
+ * @param array $allowedTypes A whitelist of ACF field types.
276
+ * @return array An array of meta keys and values.
277
+ */
278
+ public function getAcfContent( $post = null, $types = [] ) {
279
+ $post = ( $post && is_object( $post ) ) ? $post : $this->getPost( $post );
280
+
281
+ if ( ! class_exists( 'ACF' ) || ! function_exists( 'get_field_objects' ) ) {
282
+ return [];
283
+ }
284
+
285
+ if ( defined( 'ACF_VERSION' ) && version_compare( ACF_VERSION, '5.7.0', '<' ) ) {
286
+ return [];
287
+ }
288
+
289
+ // Set defaults.
290
+ $allowedTypes = [
291
+ 'text',
292
+ 'textarea',
293
+ 'email',
294
+ 'url',
295
+ 'wysiwyg',
296
+ 'image',
297
+ 'gallery',
298
+ // 'link',
299
+ // 'taxonomy',
300
+ ];
301
+
302
+ $types = wp_parse_args( $types, $allowedTypes );
303
+ $acfFields = [];
304
+
305
+ $fieldObjects = get_field_objects( $post->ID );
306
+ if ( ! empty( $fieldObjects ) ) {
307
+ foreach ( $fieldObjects as $field ) {
308
+ if ( empty( $field['value'] ) ) {
309
+ continue;
310
+ }
311
+
312
+ if ( ! in_array( $field['type'], $types, true ) ) {
313
+ continue;
314
+ }
315
+
316
+ if ( 'url' === $field['type'] ) {
317
+ // Url field
318
+ $value = "<a href='{$field['value']}'>{$field['value']}</a>";
319
+ } elseif ( 'image' === $field['type'] ) {
320
+ // Image field
321
+ $value = "<img src='{$field['value']['url']}'>";
322
+ } elseif ( 'gallery' === $field['type'] ) {
323
+ // Image field
324
+ $value = "<img src='{$field['value'][0]['url']}'>";
325
+ } else {
326
+ // Other fields
327
+ $value = $field['value'];
328
+ }
329
+
330
+ if ( $value ) {
331
+ $acfFields[ $field['name'] ] = $value;
332
+ }
333
+ }
334
+ }
335
+
336
+ return $acfFields;
337
+ }
338
+ }
app/Common/Traits/Helpers/Vue.php ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ use AIOSEO\Plugin\Common\Models;
5
+ use AIOSEO\Plugin\Common\Tools;
6
+
7
+ // Exit if accessed directly.
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ /**
13
+ * Contains all Vue related helper methods.
14
+ *
15
+ * @since 4.1.4
16
+ */
17
+ trait Vue {
18
+ /**
19
+ * Returns the data for Vue.
20
+ *
21
+ * @since 4.0.0
22
+ *
23
+ * @param string $page The current page.
24
+ * @return array The data.
25
+ */
26
+ public function getVueData( $page = null ) {
27
+ $postTypeObj = get_post_type_object( get_post_type( get_the_ID() ) );
28
+ $screen = get_current_screen();
29
+
30
+ // Check if user has a custom filename from the V3 migration.
31
+ $sitemapFilename = aioseo()->sitemap->helpers->filename( 'general' );
32
+ $sitemapFilename = $sitemapFilename ? $sitemapFilename : 'sitemap';
33
+
34
+ $isStaticHomePage = 'page' === get_option( 'show_on_front' );
35
+ $staticHomePage = intval( get_option( 'page_on_front' ) );
36
+ $data = [
37
+ 'page' => $page,
38
+ 'screen' => [
39
+ 'base' => $screen->base,
40
+ 'postType' => $screen->post_type,
41
+ 'blockEditor' => isset( $screen->is_block_editor ) ? $screen->is_block_editor : false
42
+ ],
43
+ 'internalOptions' => aioseo()->internalOptions->all(),
44
+ 'options' => aioseo()->options->all(),
45
+ 'dynamicOptions' => aioseo()->dynamicOptions->all(),
46
+ 'settings' => aioseo()->settings->all(),
47
+ 'tags' => aioseo()->tags->all( true ),
48
+ 'nonce' => wp_create_nonce( 'wp_rest' ),
49
+ 'urls' => [
50
+ 'domain' => $this->getSiteDomain(),
51
+ 'mainSiteUrl' => $this->getSiteUrl(),
52
+ 'home' => home_url(),
53
+ 'restUrl' => rest_url(),
54
+ 'publicPath' => plugin_dir_url( AIOSEO_FILE ),
55
+ 'rssFeedUrl' => get_bloginfo( 'rss2_url' ),
56
+ 'generalSitemapUrl' => home_url( "/$sitemapFilename.xml" ),
57
+ 'rssSitemapUrl' => home_url( '/sitemap.rss' ),
58
+ 'robotsTxtUrl' => $this->getSiteUrl() . '/robots.txt',
59
+ 'blockedBotsLogUrl' => wp_upload_dir()['baseurl'] . '/aioseo/logs/aioseo-bad-bot-blocker.log',
60
+ 'upgradeUrl' => apply_filters( 'aioseo_upgrade_link', AIOSEO_MARKETING_URL ),
61
+ 'staticHomePage' => 'page' === get_option( 'show_on_front' ) ? get_edit_post_link( get_option( 'page_on_front' ), 'url' ) : null,
62
+ 'connect' => add_query_arg( [
63
+ 'siteurl' => site_url(),
64
+ 'homeurl' => home_url(),
65
+ 'redirect' => rawurldecode( base64_encode( admin_url( 'index.php?page=aioseo-connect' ) ) )
66
+ ], defined( 'AIOSEO_CONNECT_URL' ) ? AIOSEO_CONNECT_URL : 'https://connect.aioseo.com' ),
67
+ 'aio' => [
68
+ 'wizard' => admin_url( 'index.php?page=aioseo-setup-wizard' ),
69
+ 'dashboard' => admin_url( 'admin.php?page=aioseo' ),
70
+ 'settings' => admin_url( 'admin.php?page=aioseo-settings' ),
71
+ 'localSeo' => admin_url( 'admin.php?page=aioseo-local-seo' ),
72
+ 'featureManager' => admin_url( 'admin.php?page=aioseo-feature-manager' ),
73
+ 'sitemaps' => admin_url( 'admin.php?page=aioseo-sitemaps' ),
74
+ 'seoAnalysis' => admin_url( 'admin.php?page=aioseo-seo-analysis' ),
75
+ 'searchAppearance' => admin_url( 'admin.php?page=aioseo-search-appearance' ),
76
+ 'socialNetworks' => admin_url( 'admin.php?page=aioseo-social-networks' ),
77
+ 'tools' => admin_url( 'admin.php?page=aioseo-tools' ),
78
+ 'monsterinsights' => admin_url( 'admin.php?page=aioseo-monsterinsights' )
79
+ ],
80
+ 'admin' => [
81
+ 'widgets' => admin_url( 'widgets.php' ),
82
+ 'optionsReading' => admin_url( 'options-reading.php' ),
83
+ 'scheduledActions' => admin_url( '/tools.php?page=action-scheduler&status=pending&s=aioseo' ),
84
+ 'generalSettings' => admin_url( 'options-general.php' )
85
+ ]
86
+ ],
87
+ 'backups' => [],
88
+ 'importers' => [],
89
+ 'data' => [
90
+ 'server' => [
91
+ 'apache' => null,
92
+ 'nginx' => null
93
+ ],
94
+ 'robots' => [
95
+ 'defaultRules' => [],
96
+ 'hasPhysicalRobots' => null,
97
+ 'rewriteExists' => null,
98
+ 'sitemapUrls' => []
99
+ ],
100
+ 'logSizes' => [
101
+ 'badBotBlockerLog' => null
102
+ ],
103
+ 'status' => [],
104
+ 'htaccess' => '',
105
+ 'multisite' => is_multisite(),
106
+ 'network' => is_network_admin(),
107
+ 'mainSite' => is_main_site(),
108
+ 'subdomain' => defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL,
109
+ 'isWooCommerceActive' => $this->isWooCommerceActive(),
110
+ 'isBBPressActive' => class_exists( 'bbPress' ),
111
+ 'staticHomePage' => $isStaticHomePage ? $staticHomePage : false,
112
+ 'staticBlogPage' => $this->getBlogPageId(),
113
+ 'staticBlogPageTitle' => get_the_title( $this->getBlogPageId() ),
114
+ 'isDev' => $this->isDev(),
115
+ 'isSsl' => is_ssl()
116
+ ],
117
+ 'user' => [
118
+ 'email' => wp_get_current_user()->user_email,
119
+ 'roles' => $this->getUserRoles(),
120
+ 'customRoles' => $this->getCustomRoles(),
121
+ 'canManage' => aioseo()->access->canManage(),
122
+ 'capabilities' => aioseo()->access->getAllCapabilities(),
123
+ 'unfilteredHtml' => current_user_can( 'unfiltered_html' ),
124
+ 'locale' => function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale()
125
+ ],
126
+ 'plugins' => $this->getPluginData(),
127
+ 'postData' => [
128
+ 'postTypes' => $this->getPublicPostTypes( false, false, true ),
129
+ 'taxonomies' => $this->getPublicTaxonomies( false, true ),
130
+ 'archives' => $this->getPublicPostTypes( false, true, true )
131
+ ],
132
+ 'notifications' => Models\Notification::getNotifications( false ),
133
+ 'addons' => aioseo()->addons->getAddons(),
134
+ 'version' => AIOSEO_VERSION,
135
+ 'helpPanel' => json_decode( aioseo()->help->getDocs() ),
136
+ 'scheduledActions' => [
137
+ 'sitemaps' => []
138
+ ]
139
+ ];
140
+
141
+ if ( is_multisite() && ! is_network_admin() ) {
142
+ switch_to_blog( $this->getNetworkId() );
143
+ $options = aioseo()->options->noConflict();
144
+ $options->initNetwork();
145
+ $data['networkOptions'] = $options->all();
146
+ restore_current_blog();
147
+ }
148
+
149
+ if ( 'post' === $page ) {
150
+ $postId = get_the_ID();
151
+ $post = Models\Post::getPost( $postId );
152
+
153
+ $data['currentPost'] = [
154
+ 'context' => 'post',
155
+ 'tags' => aioseo()->tags->getDefaultPostTags( $postId ),
156
+ 'id' => $postId,
157
+ 'priority' => ! empty( $post->priority ) ? $post->priority : 'default',
158
+ 'frequency' => ! empty( $post->frequency ) ? $post->frequency : 'default',
159
+ 'permalink' => get_the_permalink(),
160
+ 'title' => ! empty( $post->title ) ? $post->title : aioseo()->meta->title->getPostTypeTitle( $postTypeObj->name ),
161
+ 'description' => ! empty( $post->description ) ? $post->description : aioseo()->meta->description->getPostTypeDescription( $postTypeObj->name ),
162
+ 'keywords' => ! empty( $post->keywords ) ? $post->keywords : wp_json_encode( [] ),
163
+ 'keyphrases' => ! empty( $post->keyphrases )
164
+ ? json_decode( $post->keyphrases )
165
+ : json_decode( '{"focus":{},"additional":[]}' ),
166
+ 'page_analysis' => ! empty( $post->page_analysis )
167
+ ? json_decode( $post->page_analysis )
168
+ : Models\Post::getPageAnalysisDefaults(),
169
+ 'loading' => [
170
+ 'focus' => false,
171
+ 'additional' => [],
172
+ ],
173
+ 'type' => $postTypeObj->labels->singular_name,
174
+ 'postType' => 'type' === $postTypeObj->name ? '_aioseo_type' : $postTypeObj->name,
175
+ 'isSpecialPage' => $this->isSpecialPage( $postId ),
176
+ 'isWooCommercePage' => $this->isWooCommercePage( $postId ),
177
+ 'seo_score' => (int) $post->seo_score,
178
+ 'pillar_content' => ( (int) $post->pillar_content ) === 0 ? false : true,
179
+ 'canonicalUrl' => $post->canonical_url,
180
+ 'default' => ( (int) $post->robots_default ) === 0 ? false : true,
181
+ 'noindex' => ( (int) $post->robots_noindex ) === 0 ? false : true,
182
+ 'noarchive' => ( (int) $post->robots_noarchive ) === 0 ? false : true,
183
+ 'nosnippet' => ( (int) $post->robots_nosnippet ) === 0 ? false : true,
184
+ 'nofollow' => ( (int) $post->robots_nofollow ) === 0 ? false : true,
185
+ 'noimageindex' => ( (int) $post->robots_noimageindex ) === 0 ? false : true,
186
+ 'noodp' => ( (int) $post->robots_noodp ) === 0 ? false : true,
187
+ 'notranslate' => ( (int) $post->robots_notranslate ) === 0 ? false : true,
188
+ 'maxSnippet' => null === $post->robots_max_snippet ? -1 : (int) $post->robots_max_snippet,
189
+ 'maxVideoPreview' => null === $post->robots_max_videopreview ? -1 : (int) $post->robots_max_videopreview,
190
+ 'maxImagePreview' => $post->robots_max_imagepreview,
191
+ 'modalOpen' => false,
192
+ 'tabs' => ( ! empty( $post->tabs ) )
193
+ ? json_decode( $post->tabs )
194
+ : json_decode( Models\Post::getDefaultTabsOptions() ),
195
+ 'generalMobilePrev' => false,
196
+ 'socialMobilePreview' => false,
197
+ 'og_object_type' => ! empty( $post->og_object_type ) ? $post->og_object_type : 'default',
198
+ 'og_title' => $post->og_title,
199
+ 'og_description' => $post->og_description,
200
+ 'og_image_custom_url' => $post->og_image_custom_url,
201
+ 'og_image_custom_fields' => $post->og_image_custom_fields,
202
+ 'og_image_type' => ! empty( $post->og_image_type ) ? $post->og_image_type : 'default',
203
+ 'og_video' => ! empty( $post->og_video ) ? $post->og_video : '',
204
+ 'og_article_section' => ! empty( $post->og_article_section ) ? $post->og_article_section : '',
205
+ 'og_article_tags' => ! empty( $post->og_article_tags ) ? $post->og_article_tags : wp_json_encode( [] ),
206
+ 'twitter_use_og' => ( (int) $post->twitter_use_og ) === 0 ? false : true,
207
+ 'twitter_card' => $post->twitter_card,
208
+ 'twitter_image_custom_url' => $post->twitter_image_custom_url,
209
+ 'twitter_image_custom_fields' => $post->twitter_image_custom_fields,
210
+ 'twitter_image_type' => $post->twitter_image_type,
211
+ 'twitter_title' => $post->twitter_title,
212
+ 'twitter_description' => $post->twitter_description,
213
+ 'schema_type' => ( ! empty( $post->schema_type ) ) ? $post->schema_type : 'default',
214
+ 'schema_type_options' => ( ! empty( $post->schema_type_options ) )
215
+ ? json_decode( Models\Post::getDefaultSchemaOptions( $post->schema_type_options ) )
216
+ : json_decode( Models\Post::getDefaultSchemaOptions() ),
217
+ 'metaDefaults' => [
218
+ 'title' => aioseo()->meta->title->getPostTypeTitle( $postTypeObj->name ),
219
+ 'description' => aioseo()->meta->description->getPostTypeDescription( $postTypeObj->name )
220
+ ]
221
+ ];
222
+
223
+ if ( ! $post->exists() ) {
224
+ $oldPostMeta = aioseo()->migration->meta->getMigratedPostMeta( $postId );
225
+ foreach ( $oldPostMeta as $k => $v ) {
226
+ if ( preg_match( '#robots_.*#', $k ) ) {
227
+ $oldPostMeta[ preg_replace( '#robots_#', '', $k ) ] = $v;
228
+ continue;
229
+ }
230
+ if ( 'canonical_url' === $k ) {
231
+ $oldPostMeta['canonicalUrl'] = $v;
232
+ }
233
+ }
234
+ $data['currentPost'] = array_merge( $data['currentPost'], $oldPostMeta );
235
+ }
236
+ }
237
+
238
+ if ( 'sitemaps' === $page ) {
239
+ try {
240
+ if ( as_next_scheduled_action( 'aioseo_static_sitemap_regeneration' ) ) {
241
+ $data['scheduledActions']['sitemap'][] = 'staticSitemapRegeneration';
242
+ }
243
+ } catch ( \Exception $e ) {
244
+ // Do nothing.
245
+ }
246
+ }
247
+
248
+ if ( 'setup-wizard' === $page ) {
249
+ $data['users'] = $this->getSiteUsers( [ 'administrator', 'editor', 'author' ] );
250
+ $data['importers'] = aioseo()->importExport->plugins();
251
+ }
252
+
253
+ if ( 'search-appearance' === $page ) {
254
+ $data['users'] = $this->getSiteUsers( [ 'administrator', 'editor', 'author' ] );
255
+ $data['data'] += [
256
+ 'staticHomePageTitle' => $isStaticHomePage ? aioseo()->meta->title->getTitle( $staticHomePage ) : '',
257
+ 'staticHomePageDescription' => $isStaticHomePage ? aioseo()->meta->description->getDescription( $staticHomePage ) : '',
258
+ ];
259
+ }
260
+
261
+ if ( 'social-networks' === $page ) {
262
+ $data['data'] += [
263
+ 'staticHomePageOgTitle' => $isStaticHomePage ? aioseo()->social->facebook->getTitle( $staticHomePage ) : '',
264
+ 'staticHomePageOgDescription' => $isStaticHomePage ? aioseo()->social->facebook->getDescription( $staticHomePage ) : '',
265
+ 'staticHomePageTwitterTitle' => $isStaticHomePage ? aioseo()->social->twitter->getTitle( $staticHomePage ) : '',
266
+ 'staticHomePageTwitterDescription' => $isStaticHomePage ? aioseo()->social->twitter->getDescription( $staticHomePage ) : '',
267
+ ];
268
+ }
269
+
270
+ if ( 'tools' === $page ) {
271
+ $data['backups'] = array_reverse( aioseo()->backup->all() );
272
+ $data['importers'] = aioseo()->importExport->plugins();
273
+ $data['data']['server'] = [
274
+ 'apache' => $this->isApache(),
275
+ 'nginx' => $this->isNginx()
276
+ ];
277
+ $data['data']['robots'] = [
278
+ 'defaultRules' => $page ? aioseo()->robotsTxt->getDefaultRules() : [],
279
+ 'hasPhysicalRobots' => aioseo()->robotsTxt->hasPhysicalRobotsTxt(),
280
+ 'rewriteExists' => aioseo()->robotsTxt->rewriteRulesExist(),
281
+ 'sitemapUrls' => array_merge( aioseo()->sitemap->helpers->getSitemapUrls(), $this->extractSitemapUrlsFromRobotsTxt() )
282
+ ];
283
+ $data['data']['logSizes'] = [
284
+ 'badBotBlockerLog' => $this->convertFileSize( aioseo()->badBotBlocker->getLogSize() )
285
+ ];
286
+ $data['data']['status'] = Tools\SystemStatus::getSystemStatusInfo();
287
+ $data['data']['htaccess'] = aioseo()->htaccess->getContents();
288
+ }
289
+
290
+ if ( 'settings' === $page ) {
291
+ $data['breadcrumbs']['defaultTemplate'] = aioseo()->helpers->encodeOutputHtml( aioseo()->breadcrumbs->frontend->getDefaultTemplate() );
292
+ }
293
+
294
+ $loadedAddons = aioseo()->addons->getLoadedAddons();
295
+ if ( ! empty( $loadedAddons ) ) {
296
+ foreach ( $loadedAddons as $addon ) {
297
+ if ( isset( $addon->helpers ) && method_exists( $addon->helpers, 'getVueData' ) ) {
298
+ $data = $addon->helpers->getVueData( $data, $page, isset( $post ) ? $post : null );
299
+ }
300
+ }
301
+ }
302
+
303
+ return $data;
304
+ }
305
+
306
+ /**
307
+ * Returns Jed-formatted localization data. Added for backwards-compatibility.
308
+ *
309
+ * @since 4.0.0
310
+ *
311
+ * @param string $domain Translation domain.
312
+ * @return array The information of the locale.
313
+ */
314
+ public function getJedLocaleData( $domain ) {
315
+ $translations = get_translations_for_domain( $domain );
316
+
317
+ $locale = [
318
+ '' => [
319
+ 'domain' => $domain,
320
+ 'lang' => is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(),
321
+ ],
322
+ ];
323
+
324
+ if ( ! empty( $translations->headers['Plural-Forms'] ) ) {
325
+ $locale['']['plural_forms'] = $translations->headers['Plural-Forms'];
326
+ }
327
+
328
+ foreach ( $translations->entries as $msgid => $entry ) {
329
+ $locale[ $msgid ] = $entry->translations;
330
+ }
331
+
332
+ // If any of the translated strings incorrectly contains HTML line breaks, we need to return or else the admin is no longer accessible - #2074.
333
+ $json = wp_json_encode( $locale );
334
+ if ( preg_match( '/<br[\s\/]*>/', $json ) ) {
335
+ return [];
336
+ }
337
+
338
+ return $locale;
339
+ }
340
+
341
+ /**
342
+ * Extracts existing sitemap URLs from the robots.txt file.
343
+ *
344
+ * We need this in case users have existing sitemap directives added to their robots.txt file.
345
+ *
346
+ * @since 4.0.10
347
+ *
348
+ * @return array An array with robots.txt sitemap directives.
349
+ */
350
+ private function extractSitemapUrlsFromRobotsTxt() {
351
+ // First, we need to remove our filter, so that it doesn't run unintentionally.
352
+ remove_filter( 'robots_txt', [ aioseo()->robotsTxt, 'buildRules' ], 10000 );
353
+ $robotsTxt = apply_filters( 'robots_txt', '', true );
354
+ add_filter( 'robots_txt', [ aioseo()->robotsTxt, 'buildRules' ], 10000, 2 );
355
+
356
+ if ( ! $robotsTxt ) {
357
+ return [];
358
+ }
359
+
360
+ $lines = explode( "\n", $robotsTxt );
361
+ if ( ! is_array( $lines ) || ! count( $lines ) ) {
362
+ return [];
363
+ }
364
+
365
+ return aioseo()->robotsTxt->extractSitemapUrls( explode( "\n", $robotsTxt ) );
366
+ }
367
+ }
app/Common/Traits/Helpers/Wp.php ADDED
@@ -0,0 +1,549 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ use AIOSEO\Plugin\Common\Utils;
5
+
6
+ // Exit if accessed directly.
7
+ if ( ! defined( 'ABSPATH' ) ) {
8
+ exit;
9
+ }
10
+
11
+ /**
12
+ * Contains all WP related helper methods.
13
+ *
14
+ * @since 4.1.4
15
+ */
16
+ trait Wp {
17
+ /**
18
+ * Whether or not we have a local connection.
19
+ *
20
+ * @since 4.0.0
21
+ *
22
+ * @var bool
23
+ */
24
+ private static $connection = false;
25
+
26
+ /**
27
+ * Helper method to enqueue scripts.
28
+ *
29
+ * @since 4.0.0
30
+ *
31
+ * @param string $script The script to enqueue.
32
+ * @param string $url The URL of the script.
33
+ * @param bool $vue Whether or not this is a vue script.
34
+ * @return void
35
+ */
36
+ public function enqueueScript( $script, $url, $vue = true ) {
37
+ if ( ! wp_script_is( $script, 'enqueued' ) ) {
38
+ wp_enqueue_script(
39
+ $script,
40
+ $this->getScriptUrl( $url, $vue ),
41
+ [],
42
+ aioseo()->version,
43
+ true
44
+ );
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Helper method to enqueue stylesheets.
50
+ *
51
+ * @since 4.0.0
52
+ *
53
+ * @param string $style The stylesheet to enqueue.
54
+ * @param string $url The URL of the stylesheet.
55
+ * @param bool $vue Whether or not this is a vue stylesheet.
56
+ * @return void
57
+ */
58
+ public function enqueueStyle( $style, $url, $vue = true ) {
59
+ if ( ! wp_style_is( $style, 'enqueued' ) && $this->shouldEnqueue( $url ) ) {
60
+ wp_enqueue_style(
61
+ $style,
62
+ $this->getScriptUrl( $url, $vue ),
63
+ [],
64
+ aioseo()->version
65
+ );
66
+ }
67
+ }
68
+
69
+ /** Whether or not we should enqueue a file.
70
+ *
71
+ * @since 4.0.0
72
+ *
73
+ * @param string $url The url to check against.
74
+ * @return bool Whether or not we should enqueue.
75
+ */
76
+ private function shouldEnqueue( $url ) {
77
+ $version = strtoupper( aioseo()->versionPath );
78
+ $host = defined( 'AIOSEO_DEV_' . $version ) ? constant( 'AIOSEO_DEV_' . $version ) : false;
79
+
80
+ if ( ! $host ) {
81
+ return true;
82
+ }
83
+
84
+ if ( false !== strpos( $url, 'chunk-common.css' ) ) {
85
+ // return false;
86
+ }
87
+
88
+ return true;
89
+ }
90
+
91
+ /**
92
+ * Retrieve the proper URL for this script or style.
93
+ *
94
+ * @since 4.0.0
95
+ *
96
+ * @param string $url The url.
97
+ * @param bool $vue Whether or not this is a vue script.
98
+ * @return string The modified url.
99
+ */
100
+ public function getScriptUrl( $url, $vue = true ) {
101
+ $version = strtoupper( aioseo()->versionPath );
102
+ $host = $vue && defined( 'AIOSEO_DEV_' . $version ) ? constant( 'AIOSEO_DEV_' . $version ) : false;
103
+ $localUrl = $url;
104
+ $url = plugins_url( 'dist/' . aioseo()->versionPath . '/assets/' . $url, AIOSEO_FILE );
105
+
106
+ if ( ! $host ) {
107
+ return $url;
108
+ }
109
+
110
+ if ( $host && ! self::$connection ) {
111
+ $splitHost = explode( ':', str_replace( '/', '', str_replace( 'http://', '', str_replace( 'https://', '', $host ) ) ) );
112
+ self::$connection = @fsockopen( $splitHost[0], $splitHost[1] ); // phpcs:ignore WordPress
113
+ }
114
+
115
+ if ( ! self::$connection ) {
116
+ return $url;
117
+ }
118
+
119
+ return $host . $localUrl;
120
+ }
121
+
122
+ /**
123
+ * Returns user roles in the current WP install.
124
+ *
125
+ * @since 4.0.0
126
+ *
127
+ * @return array An array of user roles.
128
+ */
129
+ public function getUserRoles() {
130
+ global $wp_roles;
131
+ if ( ! isset( $wp_roles ) ) {
132
+ $wp_roles = new \WP_Roles();
133
+ }
134
+ $roleNames = $wp_roles->get_names();
135
+ asort( $roleNames );
136
+
137
+ return $roleNames;
138
+ }
139
+
140
+ /**
141
+ * Returns the custom roles in the current WP install.
142
+ *
143
+ * @since 4.1.3
144
+ *
145
+ * @return array An array of custom roles.
146
+ */
147
+ public function getCustomRoles() {
148
+ $allRoles = $this->getUserRoles();
149
+
150
+ $toSkip = array_merge(
151
+ // Default WordPress roles.
152
+ [ 'superadmin', 'administrator', 'editor', 'author', 'contributor' ],
153
+ // Default AIOSEO roles.
154
+ [ 'aioseo_manager', 'aioseo_editor' ],
155
+ // Filterable roles.
156
+ apply_filters( 'aioseo_access_control_excluded_roles', array_merge( [
157
+ 'subscriber'
158
+ ], aioseo()->helpers->isWooCommerceActive() ? [ 'customer' ] : [] ) )
159
+ );
160
+
161
+ // Remove empty entries.
162
+ $toSkip = array_filter( $toSkip );
163
+
164
+ $customRoles = [];
165
+ foreach ( $allRoles as $roleName => $role ) {
166
+ // Skip specific roles.
167
+ if ( in_array( $roleName, $toSkip, true ) ) {
168
+ continue;
169
+ }
170
+
171
+ $customRoles[ $roleName ] = $role;
172
+ }
173
+
174
+ return $customRoles;
175
+ }
176
+
177
+ /**
178
+ * Returns an array of plugins with the active status.
179
+ *
180
+ * @since 4.0.0
181
+ *
182
+ * @return array An array of plugins with active status.
183
+ */
184
+ public function getPluginData() {
185
+ $pluginUpgrader = new Utils\PluginUpgraderSilentAjax();
186
+ $installedPlugins = array_keys( get_plugins() );
187
+
188
+ $plugins = [];
189
+ foreach ( $pluginUpgrader->pluginSlugs as $key => $slug ) {
190
+ $plugins[ $key ] = [
191
+ 'basename' => $slug,
192
+ 'installed' => in_array( $slug, $installedPlugins, true ),
193
+ 'activated' => is_plugin_active( $slug ),
194
+ 'adminUrl' => admin_url( $pluginUpgrader->pluginAdminUrls[ $key ] ),
195
+ 'canInstall' => aioseo()->addons->canInstall(),
196
+ 'canActivate' => aioseo()->addons->canActivate(),
197
+ 'wpLink' => ! empty( $pluginUpgrader->wpPluginLinks[ $key ] ) ? $pluginUpgrader->wpPluginLinks[ $key ] : null
198
+ ];
199
+ }
200
+
201
+ return $plugins;
202
+ }
203
+
204
+ /**
205
+ * Retrieve a list of public post types with slugs/icons.
206
+ *
207
+ * @since 4.0.0
208
+ *
209
+ * @param boolean $namesOnly Whether only the names should be returned.
210
+ * @param boolean $hasArchivesOnly Whether or not to only include post types which have archives.
211
+ * @param boolean $rewriteType Whether or not to rewrite the type slugs.
212
+ * @return array An array of public post types.
213
+ */
214
+ public function getPublicPostTypes( $namesOnly = false, $hasArchivesOnly = false, $rewriteType = false ) {
215
+ $postTypes = [];
216
+ $postObjects = get_post_types( [ 'public' => true ], 'objects' );
217
+ $woocommerce = class_exists( 'woocommerce' );
218
+ foreach ( $postObjects as $postObject ) {
219
+ if ( empty( $postObject->label ) ) {
220
+ continue;
221
+ }
222
+
223
+ // We don't want to include archives for the WooCommerce shop page.
224
+ if (
225
+ $hasArchivesOnly &&
226
+ (
227
+ ! $postObject->has_archive ||
228
+ ( 'product' === $postObject->name && $woocommerce )
229
+ )
230
+ ) {
231
+ continue;
232
+ }
233
+
234
+ if ( $namesOnly ) {
235
+ $postTypes[] = $postObject->name;
236
+ continue;
237
+ }
238
+
239
+ if ( 'attachment' === $postObject->name ) {
240
+ $postObject->label = __( 'Attachments', 'all-in-one-seo-pack' );
241
+ }
242
+
243
+ if ( 'product' === $postObject->name && $woocommerce ) {
244
+ $postObject->menu_icon = 'dashicons-products';
245
+ }
246
+
247
+ $name = $postObject->name;
248
+ if ( 'type' === $postObject->name && $rewriteType ) {
249
+ $name = '_aioseo_type';
250
+ }
251
+
252
+ $postTypes[] = [
253
+ 'name' => $name,
254
+ 'label' => ucwords( $postObject->label ),
255
+ 'singular' => ucwords( $postObject->labels->singular_name ),
256
+ 'icon' => $postObject->menu_icon,
257
+ 'hasExcerpt' => post_type_supports( $postObject->name, 'excerpt' ),
258
+ 'hasArchive' => $postObject->has_archive,
259
+ 'hierarchical' => $postObject->hierarchical,
260
+ 'taxonomies' => get_object_taxonomies( $name ),
261
+ 'slug' => isset( $postObject->rewrite['slug'] ) ? $postObject->rewrite['slug'] : $name
262
+ ];
263
+ }
264
+
265
+ return $postTypes;
266
+ }
267
+
268
+ /**
269
+ * Retrieve a list of public taxonomies with slugs/icons.
270
+ *
271
+ * @since 4.0.0
272
+ *
273
+ * @param boolean $namesOnly Whether only the names should be returned.
274
+ * @param boolean $rewriteType Whether or not to rewrite the type slugs.
275
+ * @return array An array of public taxonomies.
276
+ */
277
+ public function getPublicTaxonomies( $namesOnly = false, $rewriteType = false ) {
278
+ $taxonomies = [];
279
+ if ( count( $taxonomies ) ) {
280
+ return $taxonomies;
281
+ }
282
+
283
+ $taxObjects = get_taxonomies( [ 'public' => true ], 'objects' );
284
+ foreach ( $taxObjects as $taxObject ) {
285
+ if ( empty( $taxObject->label ) ) {
286
+ continue;
287
+ }
288
+
289
+ if ( in_array( $taxObject->name, [
290
+ 'product_shipping_class',
291
+ 'post_format'
292
+ ], true ) ) {
293
+ continue;
294
+ }
295
+
296
+ // We need to exclude product attributes from this list as well.
297
+ if (
298
+ 'pa_' === substr( $taxObject->name, 0, 3 ) &&
299
+ 'manage_product_terms' === $taxObject->cap->manage_terms &&
300
+ ! apply_filters( 'aioseo_woocommerce_product_attributes', false )
301
+ ) {
302
+ continue;
303
+ }
304
+
305
+ if ( $namesOnly ) {
306
+ $taxonomies[] = $taxObject->name;
307
+ continue;
308
+ }
309
+
310
+ $name = $taxObject->name;
311
+ if ( 'type' === $taxObject->name && $rewriteType ) {
312
+ $name = '_aioseo_type';
313
+ }
314
+
315
+ $taxonomies[] = [
316
+ 'name' => $name,
317
+ 'label' => ucwords( $taxObject->label ),
318
+ 'singular' => ucwords( $taxObject->labels->singular_name ),
319
+ 'icon' => strpos( $taxObject->label, 'categor' ) !== false ? 'dashicons-category' : 'dashicons-tag',
320
+ 'hierarchical' => $taxObject->hierarchical,
321
+ 'slug' => isset( $taxObject->rewrite['slug'] ) ? $taxObject->rewrite['slug'] : ''
322
+ ];
323
+ }
324
+
325
+ return $taxonomies;
326
+ }
327
+
328
+ /**
329
+ * Retrieve a list of users that match passed in roles.
330
+ *
331
+ * @since 4.0.0
332
+ *
333
+ * @return array An array of user data.
334
+ */
335
+ public function getSiteUsers( $roles ) {
336
+ static $users = [];
337
+
338
+ if ( ! empty( $users ) ) {
339
+ return $users;
340
+ }
341
+
342
+ $rolesWhere = [];
343
+ foreach ( $roles as $role ) {
344
+ $rolesWhere[] = '(um.meta_key = \'' . aioseo()->db->db->prefix . 'capabilities\' AND um.meta_value LIKE \'%\"' . $role . '\"%\')';
345
+ }
346
+ $dbUsers = aioseo()->db->start( 'users as u' )
347
+ ->select( 'u.ID, u.display_name, u.user_nicename, u.user_email' )
348
+ ->join( 'usermeta as um', 'u.ID = um.user_id' )
349
+ ->whereRaw( '(' . implode( ' OR ', $rolesWhere ) . ')' )
350
+ ->orderBy( 'u.user_nicename' )
351
+ ->run()
352
+ ->result();
353
+
354
+ foreach ( $dbUsers as $dbUser ) {
355
+ $users[] = [
356
+ 'id' => intval( $dbUser->ID ),
357
+ 'displayName' => $dbUser->display_name,
358
+ 'niceName' => $dbUser->user_nicename,
359
+ 'email' => $dbUser->user_email,
360
+ 'gravatar' => get_avatar_url( $dbUser->user_email )
361
+ ];
362
+ }
363
+
364
+ return $users;
365
+ }
366
+
367
+ /**
368
+ * Returns the ID of the site logo if it exists.
369
+ *
370
+ * @since 4.0.0
371
+ *
372
+ * @return int
373
+ */
374
+ public function getSiteLogoId() {
375
+ if ( ! get_theme_support( 'custom-logo' ) ) {
376
+ return false;
377
+ }
378
+ return get_theme_mod( 'custom_logo' );
379
+ }
380
+
381
+ /**
382
+ * Returns the URL of the site logo if it exists.
383
+ *
384
+ * @since 4.0.0
385
+ *
386
+ * @return string
387
+ */
388
+ public function getSiteLogoUrl() {
389
+ $id = $this->getSiteLogoId();
390
+ if ( ! $id ) {
391
+ return false;
392
+ }
393
+
394
+ $image = wp_get_attachment_image_src( $id, 'full' );
395
+ if ( empty( $image ) ) {
396
+ return false;
397
+ }
398
+ return $image[0];
399
+ }
400
+
401
+ /**
402
+ * Returns the filesystem object if we have access to it.
403
+ *
404
+ * @since 4.0.0
405
+ *
406
+ * @param array $args The connection args.
407
+ * @return WP_Filesystem The filesystem object.
408
+ */
409
+ public function wpfs( $args = [] ) {
410
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
411
+ WP_Filesystem( $args );
412
+
413
+ global $wp_filesystem;
414
+ if ( is_object( $wp_filesystem ) ) {
415
+ return $wp_filesystem;
416
+ }
417
+ return false;
418
+ }
419
+
420
+ /**
421
+ * Returns noindexed post types.
422
+ *
423
+ * @since 4.0.0
424
+ *
425
+ * @return array A list of noindexed post types.
426
+ */
427
+ public function getNoindexedPostTypes() {
428
+ return $this->getNoindexedObjects( 'postTypes' );
429
+ }
430
+
431
+ /**
432
+ * Checks whether a given post type is noindexed.
433
+ *
434
+ * @since 4.0.0
435
+ *
436
+ * @param string $postType The post type.
437
+ * @return bool Whether the post type is noindexed.
438
+ */
439
+ public function isPostTypeNoindexed( $postType ) {
440
+ $noindexedPostTypes = $this->getNoindexedPostTypes();
441
+ return in_array( $postType, $noindexedPostTypes, true );
442
+ }
443
+
444
+ /**
445
+ * Returns noindexed taxonomies.
446
+ *
447
+ * @since 4.0.0
448
+ *
449
+ * @return array A list of noindexed taxonomies.
450
+ */
451
+ public function getNoindexedTaxonomies() {
452
+ return $this->getNoindexedObjects( 'taxonomies' );
453
+ }
454
+
455
+ /**
456
+ * Checks whether a given post type is noindexed.
457
+ *
458
+ * @since 4.0.0
459
+ *
460
+ * @param string $taxonomy The taxonomy.
461
+ * @return bool Whether the taxonomy is noindexed.
462
+ */
463
+ public function isTaxonomyNoindexed( $taxonomy ) {
464
+ $noindexedTaxonomies = $this->getNoindexedTaxonomies();
465
+ return in_array( $taxonomy, $noindexedTaxonomies, true );
466
+ }
467
+
468
+ /**
469
+ * Returns noindexed object types of a given parent type.
470
+ *
471
+ * @since 4.0.0
472
+ *
473
+ * @param string $type The parent object type ("postTypes" or "taxonomies").
474
+ * @return array A list of noindexed objects types.
475
+ */
476
+ private function getNoindexedObjects( $type ) {
477
+ $noindexed = [];
478
+ foreach ( aioseo()->dynamicOptions->searchAppearance->$type->all() as $name => $object ) {
479
+ if (
480
+ ! $object['show'] ||
481
+ ( $object['advanced']['robotsMeta'] && ! $object['advanced']['robotsMeta']['default'] && $object['advanced']['robotsMeta']['noindex'] )
482
+ ) {
483
+ $noindexed[] = $name;
484
+ }
485
+ }
486
+ return $noindexed;
487
+ }
488
+
489
+ /**
490
+ * Returns all categories for a post.
491
+ *
492
+ * @since 4.1.4
493
+ *
494
+ * @param int $postId The post ID.
495
+ * @return array $names The category names.
496
+ */
497
+ public function getAllCategories( $postId = 0 ) {
498
+ $names = [];
499
+ $categories = get_the_category( $postId );
500
+ if ( $categories && count( $categories ) ) {
501
+ foreach ( $categories as $category ) {
502
+ $names[] = aioseo()->helpers->internationalize( $category->cat_name );
503
+ }
504
+ }
505
+ return $names;
506
+ }
507
+
508
+ /**
509
+ * Returns all tags for a post.
510
+ *
511
+ * @since 4.1.4
512
+ *
513
+ * @param int $postId The post ID.
514
+ * @return array $names The tag names.
515
+ */
516
+ public function getAllTags( $postId = 0 ) {
517
+ $names = [];
518
+
519
+ $tags = get_the_tags( $postId );
520
+ if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
521
+ foreach ( $tags as $tag ) {
522
+ if ( ! empty( $tag->name ) ) {
523
+ $names[] = aioseo()->helpers->internationalize( $tag->name );
524
+ }
525
+ }
526
+ }
527
+ return $names;
528
+ }
529
+
530
+ /**
531
+ * Loads the translations for a given domain.
532
+ *
533
+ * @since 4.1.4
534
+ *
535
+ * @return void
536
+ */
537
+ public function loadTextDomain( $domain ) {
538
+ if ( ! is_user_logged_in() ) {
539
+ return;
540
+ }
541
+
542
+ // Unload the domain in case WordPress has enqueued the translations for the site language instead of profile language.
543
+ // Reloading the text domain will otherwise not override the existing loaded translations.
544
+ unload_textdomain( $domain );
545
+
546
+ $mofile = $domain . '-' . get_user_locale() . '.mo';
547
+ load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile );
548
+ }
549
+ }
app/Common/Traits/Helpers/WpContext.php ADDED
@@ -0,0 +1,489 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Contains all context related helper methods.
11
+ * This includes methods to check the context of the current request, but also get WP objects.
12
+ *
13
+ * @since 4.1.4
14
+ */
15
+ trait WpContext {
16
+ /**
17
+ * Get the home page object.
18
+ *
19
+ * @since 4.1.1
20
+ *
21
+ * @return WP_Post|null The home page.
22
+ */
23
+ public function getHomePage() {
24
+ $homePageId = $this->getHomePageId();
25
+
26
+ return $homePageId ? get_post( $homePageId ) : null;
27
+ }
28
+
29
+ /**
30
+ * Get the ID of the home page.
31
+ *
32
+ * @since 4.0.0
33
+ *
34
+ * @return integer|null The home page ID.
35
+ */
36
+ public function getHomePageId() {
37
+ $pageShowOnFront = ( 'page' === get_option( 'show_on_front' ) );
38
+ $pageOnFrontId = get_option( 'page_on_front' );
39
+
40
+ return $pageShowOnFront && $pageOnFrontId ? (int) $pageOnFrontId : null;
41
+ }
42
+
43
+ /**
44
+ * Returns the blog page.
45
+ *
46
+ * @since 4.0.0
47
+ *
48
+ * @return WP_Post|null The blog page.
49
+ */
50
+ public function getBlogPage() {
51
+ $blogPageId = $this->getBlogPageId();
52
+
53
+ return $blogPageId ? get_post( $blogPageId ) : null;
54
+ }
55
+
56
+ /**
57
+ * Gets the current blog page id if it's configured.
58
+ *
59
+ * @since 4.1.1
60
+ *
61
+ * @return int|null
62
+ */
63
+ public function getBlogPageId() {
64
+ $pageShowOnFront = ( 'page' === get_option( 'show_on_front' ) );
65
+ $blogPageId = (int) get_option( 'page_for_posts' );
66
+
67
+ return $pageShowOnFront && $blogPageId ? $blogPageId : null;
68
+ }
69
+
70
+ /**
71
+ * Checks whether the current page is a taxonomy term archive.
72
+ *
73
+ * @since 4.0.0
74
+ *
75
+ * @return boolean Whether the current page is a taxonomy term archive.
76
+ */
77
+ public function isTaxTerm() {
78
+ $object = get_queried_object();
79
+ return $object instanceof \WP_Term;
80
+ }
81
+
82
+ /**
83
+ * Checks whether the current page is a static one.
84
+ *
85
+ * @since 4.0.0
86
+ *
87
+ * @return boolean Whether the current page is a static one.
88
+ */
89
+ public function isStaticPage() {
90
+ return $this->isStaticHomePage() || $this->isStaticPostsPage() || $this->isWooCommerceShopPage();
91
+ }
92
+
93
+ /**
94
+ * Checks whether the current page is the static homepage.
95
+ *
96
+ * @since 4.0.0
97
+ *
98
+ * @param mixed $post Pass in an optional post to check if its the static home page.
99
+ * @return boolean Whether the current page is the static homepage.
100
+ */
101
+ public function isStaticHomePage( $post = null ) {
102
+ static $isHomePage = null;
103
+ if ( null !== $isHomePage ) {
104
+ return $isHomePage;
105
+ }
106
+
107
+ $post = aioseo()->helpers->getPost( $post );
108
+ return ( 'page' === get_option( 'show_on_front' ) && ! empty( $post->ID ) && (int) get_option( 'page_on_front' ) === $post->ID );
109
+ }
110
+
111
+ /**
112
+ * Checks whether the current page is the static posts page.
113
+ *
114
+ * @since 4.0.0
115
+ *
116
+ * @return boolean Whether the current page is the static posts page.
117
+ */
118
+ public function isStaticPostsPage() {
119
+ return is_home() && ( 0 !== (int) get_option( 'page_for_posts' ) );
120
+ }
121
+
122
+ /**
123
+ * Checks whether current page supports meta.
124
+ *
125
+ * @since 4.0.0
126
+ *
127
+ * @return boolean Whether the current page supports meta.
128
+ */
129
+ public function supportsMeta() {
130
+ return ! is_date() && ! is_author() && ! is_search() && ! is_404();
131
+ }
132
+
133
+ /**
134
+ * Returns the network ID.
135
+ *
136
+ * @since 4.0.0
137
+ *
138
+ * @return int The integer of the blog/site id.
139
+ */
140
+ public function getNetworkId() {
141
+ if ( is_multisite() ) {
142
+ return get_network()->site_id;
143
+ }
144
+ return get_current_blog_id();
145
+ }
146
+
147
+ /**
148
+ * Returns the current post object.
149
+ *
150
+ * @since 4.0.0
151
+ *
152
+ * @param int $postId The post ID.
153
+ * @return WP_Post The post object.
154
+ */
155
+ public function getPost( $postId = false ) {
156
+ static $showOnFront = null;
157
+ static $pageOnFront = null;
158
+ static $pageForPosts = null;
159
+
160
+ $postId = is_a( $postId, 'WP_Post' ) ? $postId->ID : $postId;
161
+
162
+ if ( aioseo()->helpers->isWooCommerceShopPage( $postId ) ) {
163
+ return get_post( wc_get_page_id( 'shop' ) );
164
+ }
165
+
166
+ if ( is_front_page() || is_home() ) {
167
+ $showOnFront = $showOnFront ? $showOnFront : 'page' === get_option( 'show_on_front' );
168
+ if ( $showOnFront ) {
169
+ if ( is_front_page() ) {
170
+ $pageOnFront = $pageOnFront ? $pageOnFront : (int) get_option( 'page_on_front' );
171
+ return get_post( $pageOnFront );
172
+ } elseif ( is_home() ) {
173
+ $pageForPosts = $pageForPosts ? $pageForPosts : (int) get_option( 'page_for_posts' );
174
+ return get_post( $pageForPosts );
175
+ }
176
+ }
177
+
178
+ return get_post();
179
+ }
180
+
181
+ if (
182
+ $this->isScreenBase( 'post' ) ||
183
+ $postId ||
184
+ is_singular()
185
+ ) {
186
+ return get_post( $postId );
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Returns the page content.
192
+ *
193
+ * @since 4.0.0
194
+ *
195
+ * @param WP_Post|int $post The post.
196
+ * @return string The content.
197
+ */
198
+ public function getContent( $post = null ) {
199
+ $post = ( $post && is_object( $post ) ) ? $post : $post = $this->getPost( $post );
200
+
201
+ static $content = [];
202
+ if ( isset( $content[ $post->ID ] ) ) {
203
+ return $content[ $post->ID ];
204
+ }
205
+
206
+ if ( empty( $post->post_content ) ) {
207
+ return $post->post_content;
208
+ }
209
+
210
+ $postContent = $post->post_content;
211
+ if (
212
+ ! in_array( 'runShortcodesInDescription', aioseo()->internalOptions->deprecatedOptions, true ) ||
213
+ aioseo()->options->deprecated->searchAppearance->advanced->runShortcodesInDescription
214
+ ) {
215
+ $postContent = $this->doShortcodes( $postContent );
216
+ }
217
+
218
+ $postContent = wp_trim_words( $postContent, 55, apply_filters( 'excerpt_more', ' ' . '[&hellip;]' ) );
219
+ $postContent = str_replace( ']]>', ']]&gt;', $postContent );
220
+ $postContent = preg_replace( '#(<figure.*\/figure>|<img.*\/>)#', '', $postContent );
221
+ $content[ $post->ID ] = trim( wp_strip_all_tags( strip_shortcodes( $postContent ) ) );
222
+ return $content[ $post->ID ];
223
+ }
224
+
225
+ /**
226
+ * Returns custom fields as a string.
227
+ *
228
+ * @since 4.0.6
229
+ *
230
+ * @param WP_Post|int $post The post.
231
+ * @param array $keys The post meta_keys to check for values.
232
+ * @return string The custom field content.
233
+ */
234
+ public function getCustomFieldsContent( $post = null, $keys = [] ) {
235
+ $post = ( $post && is_object( $post ) ) ? $post : $this->getPost( $post );
236
+
237
+ $customFieldContent = '';
238
+
239
+ $acfFields = $this->getAcfContent( $post );
240
+ $acfFieldsKeys = [];
241
+
242
+ if ( ! empty( $acfFields ) ) {
243
+ foreach ( $acfFields as $acfField => $acfValue ) {
244
+ if ( in_array( $acfField, $keys, true ) ) {
245
+ $customFieldContent .= "{$acfValue} ";
246
+ $acfFieldsKeys[] = $acfField;
247
+ }
248
+ }
249
+ }
250
+
251
+ foreach ( $keys as $key ) {
252
+ if ( in_array( $key, $acfFieldsKeys, true ) ) {
253
+ continue;
254
+ }
255
+
256
+ $value = get_post_meta( $post->ID, $key, true );
257
+
258
+ if ( $value ) {
259
+ $customFieldContent .= "{$value} ";
260
+ }
261
+ }
262
+
263
+ return $customFieldContent;
264
+ }
265
+
266
+ /**
267
+ * Returns if the page is a special type (WooCommerce pages, Privacy page).
268
+ *
269
+ * @since 4.0.0
270
+ *
271
+ * @param int $postId The post ID.
272
+ * @return boolean If the page is special or not.
273
+ */
274
+ public function isSpecialPage( $postId = false ) {
275
+ if (
276
+ (int) get_option( 'page_for_posts' ) === (int) $postId ||
277
+ (int) get_option( 'wp_page_for_privacy_policy' ) === (int) $postId ||
278
+ $this->isBuddyPressPage( $postId ) ||
279
+ $this->isWooCommercePage( $postId )
280
+ ) {
281
+ return true;
282
+ }
283
+
284
+ return false;
285
+ }
286
+
287
+ /**
288
+ * Returns the page number of the current page.
289
+ *
290
+ * @since 4.0.0
291
+ *
292
+ * @return int The page number.
293
+ */
294
+ public function getPageNumber() {
295
+ $page = get_query_var( 'page' );
296
+ $paged = get_query_var( 'paged' );
297
+ return ! empty( $page )
298
+ ? $page
299
+ : (
300
+ ! empty( $paged )
301
+ ? $paged
302
+ : 1
303
+ );
304
+ }
305
+
306
+ /**
307
+ * Check if the post passed in is a valid post, not a revision or autosave.
308
+ *
309
+ * @since 4.0.5
310
+ *
311
+ * @param WP_Post $post The Post object to check.
312
+ * @return bool True if valid, false if not.
313
+ */
314
+ public function isValidPost( $post ) {
315
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
316
+ return false;
317
+ }
318
+
319
+ if ( ! is_object( $post ) ) {
320
+ $post = get_post( $post );
321
+ }
322
+
323
+ // In order to prevent recursion, we are skipping scheduled-action posts.
324
+ if (
325
+ empty( $post ) ||
326
+ 'scheduled-action' === $post->post_type ||
327
+ 'revision' === $post->post_type ||
328
+ 'publish' !== $post->post_status
329
+ ) {
330
+ return false;
331
+ }
332
+
333
+ return true;
334
+ }
335
+
336
+ /**
337
+ * Checks whether the given URL is a valid attachment.
338
+ *
339
+ * @since 4.0.13
340
+ *
341
+ * @param string $url The URL.
342
+ * @return boolean Whether the URL is a valid attachment.
343
+ */
344
+ public function isValidAttachment( $url ) {
345
+ $uploadDirUrl = aioseo()->helpers->escapeRegex( $this->getWpContentUrl() );
346
+ return preg_match( "/$uploadDirUrl.*/", $url );
347
+ }
348
+
349
+ /**
350
+ * Tries to convert an attachment URL into a post ID.
351
+ *
352
+ * This our own optimized version of attachment_url_to_postid().
353
+ *
354
+ * @since 4.0.13
355
+ *
356
+ * @param string $url The attachment URL.
357
+ * @return int|boolean The attachment ID or false if no attachment could be found.
358
+ */
359
+ public function attachmentUrlToPostId( $url ) {
360
+ $cacheName = "aioseo_attachment_url_to_post_id_$url";
361
+
362
+ $cachedId = wp_cache_get( $cacheName, 'aioseo' );
363
+ if ( $cachedId ) {
364
+ return 'none' !== $cachedId && is_numeric( $cachedId ) ? (int) $cachedId : false;
365
+ }
366
+
367
+ $path = $url;
368
+ $uploadDirInfo = wp_get_upload_dir();
369
+
370
+ $siteUrl = wp_parse_url( $uploadDirInfo['url'] );
371
+ $imagePath = wp_parse_url( $path );
372
+
373
+ // Force the protocols to match if needed.
374
+ if ( isset( $imagePath['scheme'] ) && ( $imagePath['scheme'] !== $siteUrl['scheme'] ) ) {
375
+ $path = str_replace( $imagePath['scheme'], $siteUrl['scheme'], $path );
376
+ }
377
+
378
+ if ( ! $this->isValidAttachment( $path ) ) {
379
+ wp_cache_set( $cacheName, 'none', 'aioseo', DAY_IN_SECONDS );
380
+ return false;
381
+ }
382
+
383
+ if ( 0 === strpos( $path, $uploadDirInfo['baseurl'] . '/' ) ) {
384
+ $path = substr( $path, strlen( $uploadDirInfo['baseurl'] . '/' ) );
385
+ }
386
+
387
+ $results = aioseo()->db->start( 'postmeta' )
388
+ ->select( 'post_id' )
389
+ ->where( 'meta_key', '_wp_attached_file' )
390
+ ->where( 'meta_value', $path )
391
+ ->limit( 1 )
392
+ ->run()
393
+ ->result();
394
+
395
+ if ( empty( $results[0]->post_id ) ) {
396
+ wp_cache_set( $cacheName, 'none', 'aioseo', DAY_IN_SECONDS );
397
+ return false;
398
+ }
399
+
400
+ wp_cache_set( $cacheName, $results[0]->post_id, 'aioseo', DAY_IN_SECONDS );
401
+ return $results[0]->post_id;
402
+ }
403
+
404
+ /**
405
+ * Returns true if the request is a non-legacy REST API request.
406
+ * This function was copied from WooCommerce and improved.
407
+ *
408
+ * @since 4.1.2
409
+ *
410
+ * @return bool True if this is a REST API request.
411
+ */
412
+ public function isRestApiRequest() {
413
+ global $wp_rewrite;
414
+
415
+ if ( empty( $wp_rewrite ) ) {
416
+ return false;
417
+ }
418
+
419
+ if ( empty( $_SERVER['REQUEST_URI'] ) ) {
420
+ return false;
421
+ }
422
+
423
+ $restUrl = wp_parse_url( get_rest_url() );
424
+ $restUrl = $restUrl['path'] . ( ! empty( $restUrl['query'] ) ? '?' . $restUrl['query'] : '' );
425
+
426
+ $isRestApiRequest = ( 0 === strpos( $_SERVER['REQUEST_URI'], $restUrl ) );
427
+
428
+ return apply_filters( 'aioseo_is_rest_api_request', $isRestApiRequest );
429
+ }
430
+
431
+ /**
432
+ * Checks whether the current request is an AJAX, CRON or REST request.
433
+ *
434
+ * @since 4.1.3
435
+ *
436
+ * @return bool Wether the request is an AJAX, CRON or REST request.
437
+ */
438
+ public function isAjaxCronRest() {
439
+ return wp_doing_ajax() || wp_doing_cron() || $this->isRestApiRequest();
440
+ }
441
+
442
+ /**
443
+ * Checks whether we're on the given screen.
444
+ *
445
+ * @since 4.0.7
446
+ *
447
+ * @param string $screenName The screen name.
448
+ * @return boolean Whether we're on the given screen.
449
+ */
450
+ public function isScreenBase( $screenName ) {
451
+ $screen = $this->getCurrentScreen();
452
+ if ( ! $screen || ! isset( $screen->base ) ) {
453
+ return false;
454
+ }
455
+ return $screen->base === $screenName;
456
+ }
457
+
458
+ /**
459
+ * Returns if current screen is of a post type
460
+ *
461
+ * @since 4.0.17
462
+ *
463
+ * @param string $postType Post type slug
464
+ *
465
+ * @return bool
466
+ */
467
+ public function isScreenPostType( $postType ) {
468
+ $screen = $this->getCurrentScreen();
469
+ if ( ! $screen || ! isset( $screen->post_type ) ) {
470
+ return false;
471
+ }
472
+ return $screen->post_type === $postType;
473
+ }
474
+
475
+ /**
476
+ * Gets current admin screen
477
+ *
478
+ * @since 4.0.17
479
+ *
480
+ * @return false|\WP_Screen|null
481
+ */
482
+ public function getCurrentScreen() {
483
+ if ( ! is_admin() || ! function_exists( 'get_current_screen' ) ) {
484
+ return false;
485
+ }
486
+
487
+ return get_current_screen();
488
+ }
489
+ }
app/Common/Traits/Helpers/WpUri.php ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Common\Traits\Helpers;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Contains all WordPress related URL, URI, path, slug, etc. related helper methods.
11
+ *
12
+ * @since 4.1.4
13
+ */
14
+ trait WpUri {
15
+ /**
16
+ * Returns the site domain.
17
+ *
18
+ * @since 4.0.0
19
+ *
20
+ * @return string The site's domain.
21
+ */
22
+ public function getSiteDomain() {
23
+ return wp_parse_url( home_url(), PHP_URL_HOST );
24
+ }
25
+
26
+ /**
27
+ * Returns the site URL.
28
+ * NOTE: For multisites inside a sub-directory, this returns the URL for the main site.
29
+ * This is intentional.
30
+ *
31
+ * @since 4.0.0
32
+ *
33
+ * @return string The site's domain.
34
+ */
35
+ public function getSiteUrl() {
36
+ return wp_parse_url( home_url(), PHP_URL_SCHEME ) . '://' . wp_parse_url( home_url(), PHP_URL_HOST );
37
+ }
38
+
39
+ /**
40
+ * Returns the current URL.
41
+ *
42
+ * @since 4.0.0
43
+ *
44
+ * @param boolean $canonical Whether or not to get the canonical URL.
45
+ * @return string The URL.
46
+ */
47
+ public function getUrl( $canonical = false ) {
48
+ if ( is_singular() ) {
49
+ $object = get_queried_object_id();
50
+ return $canonical ? wp_get_canonical_url( $object ) : get_permalink( $object );
51
+ }
52
+
53
+ global $wp;
54
+ return trailingslashit( home_url( $wp->request ) );
55
+ }
56
+
57
+ /**
58
+ * Gets the canonical URL for the current page/post.
59
+ *
60
+ * @since 4.0.0
61
+ *
62
+ * @return string $url The canonical URL.
63
+ */
64
+ public function canonicalUrl() {
65
+ static $canonicalUrl = '';
66
+ if ( $canonicalUrl ) {
67
+ return $canonicalUrl;
68
+ }
69
+
70
+ $metaData = [];
71
+ $post = $this->getPost();
72
+ if ( $post ) {
73
+ $metaData = aioseo()->meta->metaData->getMetaData( $post );
74
+ }
75
+
76
+ if ( is_category() || is_tag() || is_tax() ) {
77
+ $metaData = aioseo()->meta->metaData->getMetaData( get_queried_object() );
78
+ }
79
+
80
+ if ( $metaData && ! empty( $metaData->canonical_url ) ) {
81
+ return $metaData->canonical_url;
82
+ }
83
+
84
+ $url = $this->getUrl( true );
85
+ if ( aioseo()->options->searchAppearance->advanced->noPaginationForCanonical && 1 < $this->getPageNumber() ) {
86
+ $url = preg_replace( '#(\d+\/|(?<=\/)page\/\d+\/)$#', '', $url );
87
+ }
88
+
89
+ $url = $this->maybeRemoveTrailingSlash( $url );
90
+
91
+ // Get rid of /amp at the end of the URL.
92
+ if ( ! apply_filters( 'aioseo_disable_canonical_url_amp', false ) ) {
93
+ $url = preg_replace( '/\/amp$/', '', $url );
94
+ $url = preg_replace( '/\/amp\/$/', '/', $url );
95
+ }
96
+
97
+ $searchTerm = get_query_var( 's' );
98
+ if ( is_search() && ! empty( $searchTerm ) ) {
99
+ $url = add_query_arg( 's', $searchTerm, $url );
100
+ }
101
+
102
+ return apply_filters( 'aioseo_canonical_url', $url );
103
+ }
104
+
105
+ /**
106
+ * Formats a given URl as an absolute URL if it is relative.
107
+ *
108
+ * @since 4.0.0
109
+ *
110
+ * @param string $url The URL.
111
+ * @return string $url The absolute URL.
112
+ */
113
+ public function makeUrlAbsolute( $url ) {
114
+ if ( 0 !== strpos( $url, 'http' ) && '/' !== $url ) {
115
+ if ( 0 === strpos( $url, '//' ) ) {
116
+ $scheme = wp_parse_url( home_url(), PHP_URL_SCHEME );
117
+ $url = $scheme . ':' . $url;
118
+ } else {
119
+ $url = home_url( $url );
120
+ }
121
+ }
122
+ return $url;
123
+ }
124
+
125
+ /**
126
+ * Sanitizes a given domain.
127
+ *
128
+ * @since 4.0.0
129
+ *
130
+ * @param string $domain The domain to sanitize.
131
+ * @return mixed|string The sanitized domain.
132
+ */
133
+ public function sanitizeDomain( $domain ) {
134
+ $domain = trim( $domain );
135
+ $domain = strtolower( $domain );
136
+ if ( 0 === strpos( $domain, 'http://' ) ) {
137
+ $domain = substr( $domain, 7 );
138
+ } elseif ( 0 === strpos( $domain, 'https://' ) ) {
139
+ $domain = substr( $domain, 8 );
140
+ }
141
+ $domain = untrailingslashit( $domain );
142
+
143
+ return $domain;
144
+ }
145
+
146
+ /**
147
+ * Remove trailing slashes if not set in the permalink structure.
148
+ *
149
+ * @since 4.0.0
150
+ *
151
+ * @param string $url The original URL.
152
+ * @return string The adjusted URL.
153
+ */
154
+ public function maybeRemoveTrailingSlash( $url ) {
155
+ $permalinks = get_option( 'permalink_structure' );
156
+ if ( $permalinks && ( ! is_home() || ! is_front_page() ) ) {
157
+ $trailing = substr( $permalinks, -1 );
158
+ if ( '/' !== $trailing ) {
159
+ $url = untrailingslashit( $url );
160
+ }
161
+ }
162
+
163
+ // Don't slash urls with query args.
164
+ if ( false !== strpos( $url, '?' ) ) {
165
+ $url = untrailingslashit( $url );
166
+ }
167
+
168
+ return $url;
169
+ }
170
+
171
+ /**
172
+ * Removes image dimensions from the slug of a URL.
173
+ *
174
+ * @since 4.0.0
175
+ *
176
+ * @param string $url The image URL.
177
+ * @return string The formatted image URL.
178
+ */
179
+ public function removeImageDimensions( $url ) {
180
+ return $this->isValidAttachment( $url ) ? preg_replace( '#(-[0-9]*x[0-9]*)#', '', $url ) : $url;
181
+ }
182
+
183
+ /**
184
+ * Returns the URL for the WP content folder.
185
+ *
186
+ * @since 4.0.5
187
+ *
188
+ * @return string The URL.
189
+ */
190
+ public function getWpContentUrl() {
191
+ $info = wp_get_upload_dir();
192
+ return isset( $info['baseurl'] ) ? $info['baseurl'] : '';
193
+ }
194
+
195
+ /**
196
+ * Checks whether the given path is unique or not.
197
+ *
198
+ * @since 4.1.4
199
+ *
200
+ * @param string $path The path.
201
+ * @return boolean Whether the path exists.
202
+ */
203
+ public function pathExists( $path ) {
204
+ $url = $this->isUrl( $path )
205
+ ? $path
206
+ : trailingslashit( home_url() ) . trim( $path, '/' );
207
+
208
+ $status = wp_remote_retrieve_response_code( wp_remote_get( $url ) );
209
+ if ( ! $status ) {
210
+ // If there is no status code, we might be in a local environment with CURL misconfigured.
211
+ // In that case we can still check if a post exists for the path by quering the DB.
212
+ // TODO: Add support for terms here.
213
+ $post = $this->getPostbyPath( $path, OBJECT, $this->getPublicPostTypes( true ) );
214
+ return is_object( $post );
215
+ }
216
+ return 200 === $status;
217
+ }
218
+
219
+ /**
220
+ * Retrieves a post by its given path.
221
+ * Based on the built-in get_page_by_path() function, but only checks ancestry if the post type is actually hierarchical.
222
+ *
223
+ * @since 4.1.4
224
+ *
225
+ * @param string $path The path.
226
+ * @param string $output The output type. OBJECT, ARRAY_A, or ARRAY_N.
227
+ * @param string|array $postType The post type(s) to check against.
228
+ * @return Object|false The post or false on failure.
229
+ */
230
+ public function getPostByPath( $path, $output = OBJECT, $postType = 'page' ) {
231
+ $lastChanged = wp_cache_get_last_changed( 'aioseo_posts_by_path' );
232
+ $hash = md5( $path . serialize( $postType ) );
233
+ $cacheKey = "get_page_by_path:$hash:$lastChanged";
234
+ $cached = wp_cache_get( $cacheKey, 'aioseo_posts_by_path' );
235
+
236
+ if ( false !== $cached ) {
237
+ // Special case: '0' is a bad `$path`.
238
+ if ( '0' === $cached || 0 === $cached ) {
239
+ return false;
240
+ }
241
+ return get_post( $cached, $output );
242
+ }
243
+
244
+ $path = rawurlencode( urldecode( $path ) );
245
+ $path = str_replace( '%2F', '/', $path );
246
+ $path = str_replace( '%20', ' ', $path );
247
+ $parts = explode( '/', trim( $path, '/' ) );
248
+ $reversedParts = array_reverse( $parts );
249
+ $postNames = "'" . implode( "','", $parts ) . "'";
250
+
251
+ $postTypes = is_array( $postType ) ? $postType : [ $postType, 'attachment' ];
252
+ $postTypes = "'" . implode( "','", $postTypes ) . "'";
253
+
254
+ $posts = aioseo()->db->start( 'posts' )
255
+ ->select( 'ID, post_name, post_parent, post_type' )
256
+ ->whereRaw( "post_name in ( $postNames )" )
257
+ ->whereRaw( "post_type in ( $postTypes )" )
258
+ ->run()
259
+ ->result();
260
+
261
+ $foundId = 0;
262
+ foreach ( $posts as $post ) {
263
+ if ( $post->post_name === $reversedParts[0] ) {
264
+ $count = 0;
265
+ $p = $post;
266
+
267
+ // Loop through the given path parts from right to left, ensuring each matches the post ancestry.
268
+ while ( 0 !== (int) $p->post_parent && isset( $posts[ $p->post_parent ] ) ) {
269
+ $count++;
270
+ $parent = $posts[ $p->post_parent ];
271
+ if ( ! isset( $reversedParts[ $count ] ) || $parent->post_name !== $reversedParts[ $count ] ) {
272
+ break;
273
+ }
274
+ $p = $parent;
275
+ }
276
+
277
+ if (
278
+ 0 === (int) $p->post_parent &&
279
+ ( ! is_post_type_hierarchical( $p->post_type ) || count( $reversedParts ) === $count + 1 ) &&
280
+ $p->post_name === $reversedParts[ $count ]
281
+ ) {
282
+ $foundId = $post->ID;
283
+ if ( $post->post_type === $postType ) {
284
+ break;
285
+ }
286
+ }
287
+ }
288
+ }
289
+
290
+ // We cache misses as well as hits.
291
+ wp_cache_set( $cacheKey, $foundId, 'aioseo_posts_by_path' );
292
+ return $foundId ? get_post( $foundId, $output ) : false;
293
+ }
294
+
295
+ /**
296
+ * Validates a URL.
297
+ *
298
+ * @since 4.1.2
299
+ *
300
+ * @param string $url The url.
301
+ * @return bool Is it a valid/safe url.
302
+ */
303
+ public function isUrl( $url ) {
304
+ return esc_url_raw( $url ) === $url;
305
+ }
306
+ }
app/Common/Traits/Options.php CHANGED
@@ -13,22 +13,31 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  */
14
  trait Options {
15
  /**
16
- * The name to lookup the options with.
17
  *
18
- * @since 4.0.0
 
 
 
 
 
 
 
 
 
19
  *
20
  * @var string
21
  */
22
- public $optionsName = '';
23
 
24
  /**
25
- * The options array.
26
  *
27
  * @since 4.0.0
28
  *
29
- * @var array
30
  */
31
- protected $options = [];
32
 
33
  /**
34
  * Holds the localized options.
@@ -121,7 +130,8 @@ trait Options {
121
  }
122
 
123
  // If we need to set a sub-group, do that now.
124
- $defaults = $this->options[ $this->groupKey ];
 
125
  if ( ! empty( $this->subGroups ) ) {
126
  foreach ( $this->subGroups as $subGroup ) {
127
  $defaults = $defaults[ $subGroup ];
@@ -139,8 +149,8 @@ trait Options {
139
  return $this->setSubGroup( $name );
140
  }
141
 
142
- $value = isset( $this->options[ $this->groupKey ][ $name ]['value'] )
143
- ? $this->options[ $this->groupKey ][ $name ]['value']
144
  : (
145
  ! empty( $this->arguments[0] )
146
  ? $this->arguments[0]
@@ -170,7 +180,8 @@ trait Options {
170
  }
171
 
172
  // If we need to set a sub-group, do that now.
173
- $defaults = $this->options[ $this->groupKey ];
 
174
  if ( ! empty( $this->subGroups ) ) {
175
  foreach ( $this->subGroups as $subGroup ) {
176
  $defaults = $defaults[ $subGroup ];
@@ -252,7 +263,8 @@ trait Options {
252
  }
253
 
254
  // If we need to set a sub-group, do that now.
255
- $defaults = $this->options[ $this->groupKey ];
 
256
  if ( ! empty( $this->subGroups ) ) {
257
  foreach ( $this->subGroups as $subGroup ) {
258
  $defaults = &$defaults[ $subGroup ];
@@ -298,14 +310,15 @@ trait Options {
298
  update_option( $this->optionsName . '_localized', $this->localized );
299
  }
300
 
301
- $originalDefaults = $this->options[ $this->groupKey ];
302
  $pointer = &$originalDefaults;
303
  foreach ( $this->subGroups as $subGroup ) {
304
  $pointer = &$pointer[ $subGroup ];
305
  }
306
  $pointer = $defaults;
307
 
308
- $this->options[ $this->groupKey ] = $originalDefaults;
 
309
 
310
  $this->resetGroups();
311
 
@@ -326,7 +339,8 @@ trait Options {
326
  }
327
 
328
  // If we need to set a sub-group, do that now.
329
- $defaults = $this->options[ $this->groupKey ];
 
330
  if ( ! empty( $this->subGroups ) ) {
331
  foreach ( $this->subGroups as $subGroup ) {
332
  $defaults = &$defaults[ $subGroup ];
@@ -365,7 +379,8 @@ trait Options {
365
  }
366
 
367
  // If we need to set a sub-group, do that now.
368
- $defaults = $this->options[ $this->groupKey ];
 
369
  if ( ! empty( $this->subGroups ) ) {
370
  foreach ( $this->subGroups as $subGroup ) {
371
  $defaults = &$defaults[ $subGroup ];
@@ -388,11 +403,12 @@ trait Options {
388
 
389
  unset( $defaults[ $name ]['value'] );
390
 
391
- $this->options[ $this->groupKey ] = $defaults;
392
-
393
- $this->update();
394
 
395
  $this->resetGroups();
 
 
396
  }
397
 
398
  /**
@@ -405,13 +421,15 @@ trait Options {
405
  * @return array An array of options.
406
  */
407
  public function all( $include = [], $exclude = [] ) {
408
- // Make sure our dynamic options have loaded.
409
- $this->init( true );
410
 
411
- $originalGroupKey = $this->groupKey;
 
412
 
413
  // Refactor options.
414
- $refactored = $this->convertOptionsToValues( $this->options );
 
415
 
416
  $this->groupKey = null;
417
 
@@ -419,13 +437,13 @@ trait Options {
419
  return $this->allFiltered( $refactored, $include, $exclude );
420
  }
421
 
422
- if ( empty( $this->subGroups ) ) {
423
  $all = $refactored[ $originalGroupKey ];
424
  return $this->allFiltered( $all, $include, $exclude );
425
  }
426
 
427
  $returnable = &$refactored[ $originalGroupKey ];
428
- foreach ( $this->subGroups as $subGroup ) {
429
  $returnable = &$returnable[ $subGroup ];
430
  }
431
 
@@ -443,12 +461,17 @@ trait Options {
443
  * @return void
444
  */
445
  public function reset( $include = [], $exclude = [] ) {
 
 
 
446
  // Make sure our dynamic options have loaded.
447
- $this->init( true );
 
 
448
 
449
  // If we don't have a group key set, it means we want to reset everything.
450
- if ( empty( $this->groupKey ) ) {
451
- $groupKeys = array_keys( $this->options );
452
  foreach ( $groupKeys as $groupKey ) {
453
  $this->groupKey = $groupKey;
454
  $this->reset();
@@ -459,25 +482,27 @@ trait Options {
459
  }
460
 
461
  // If we need to set a sub-group, do that now.
462
- $keys = array_merge( [ $this->groupKey ], $this->subGroups );
463
- $defaults = $this->options[ $this->groupKey ];
464
- if ( ! empty( $this->subGroups ) ) {
465
- foreach ( $this->subGroups as $subGroup ) {
466
  $defaults = $defaults[ $subGroup ];
467
  }
468
  }
469
 
470
  // Refactor options.
471
- $defaults = $this->resetValues( $defaults, $this->defaultsMerged, $keys, $include, $exclude );
 
472
 
473
- $originalDefaults = $this->options[ $this->groupKey ];
474
  $pointer = &$originalDefaults;
475
- foreach ( $this->subGroups as $subGroup ) {
476
  $pointer = &$pointer[ $subGroup ];
477
  }
478
  $pointer = $defaults;
479
 
480
- $this->options[ $this->groupKey ] = $originalDefaults;
 
481
 
482
  $this->resetGroups();
483
 
@@ -527,13 +552,20 @@ trait Options {
527
  $optionOrGroup = '_aioseo_type';
528
  }
529
 
530
- // Make sure our dynamic options have loaded.
531
- $this->init( true );
 
 
 
 
 
 
532
 
533
  // If we need to set a sub-group, do that now.
534
- $defaults = $this->groupKey ? $this->options[ $this->groupKey ] : $this->options;
535
- if ( ! empty( $this->subGroups ) ) {
536
- foreach ( $this->subGroups as $subGroup ) {
 
537
  $defaults = $defaults[ $subGroup ];
538
  }
539
  }
@@ -549,17 +581,6 @@ trait Options {
549
  return false;
550
  }
551
 
552
- /**
553
- * In order to not have a conflict, we need to return a clone.
554
- *
555
- * @since 4.0.0
556
- *
557
- * @return Options The cloned Options object.
558
- */
559
- public function noConflict() {
560
- return clone $this;
561
- }
562
-
563
  /**
564
  * Filters the results based on passed in array.
565
  *
@@ -630,24 +651,79 @@ trait Options {
630
  : null;
631
  }
632
 
 
 
 
 
 
 
 
 
 
 
 
633
  /**
634
  * Updates the options in the database.
635
  *
636
  * @since 4.0.0
637
  *
638
- * @param array|null $options An optional options array.
 
 
639
  * @return void
640
  */
641
- public function update( $options = null ) {
 
 
 
642
  // First, we need to filter our options.
643
- $options = $this->filterOptions( $this->defaults, $options );
644
 
645
  // Refactor options.
646
  $refactored = $this->convertOptionsToValues( $options );
647
 
648
  $this->resetGroups();
649
 
650
- update_option( $this->optionsName, wp_json_encode( $refactored ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  }
652
 
653
  /**
@@ -660,7 +736,8 @@ trait Options {
660
  * @return array An array of filtered options.
661
  */
662
  public function filterOptions( $defaults, $options = null ) {
663
- $options = ! empty( $options ) ? $options : $this->options;
 
664
  return $this->filterRecursively( $options, $defaults );
665
  }
666
 
@@ -674,6 +751,10 @@ trait Options {
674
  * @return array A filtered array of options.
675
  */
676
  public function filterRecursively( $options, $defaults ) {
 
 
 
 
677
  foreach ( $options as $key => $value ) {
678
  if ( ! isset( $defaults[ $key ] ) ) {
679
  unset( $options[ $key ] );
@@ -714,6 +795,8 @@ trait Options {
714
  $array[ $k ] = sanitize_text_field( $preserveHtml ? htmlspecialchars( $v, ENT_NOQUOTES, 'UTF-8' ) : $v );
715
  }
716
  return $array;
 
 
717
  }
718
  }
719
 
@@ -836,9 +919,6 @@ trait Options {
836
 
837
  // @TODO: See if we need this? could just eliminate.
838
  if ( ! is_array( $value ) ) {
839
- $values[ $key ] = [
840
- 'value' => $value
841
- ];
842
  continue;
843
  }
844
 
@@ -860,14 +940,14 @@ trait Options {
860
  * @param array $options The options array.
861
  * @return array The converted options array.
862
  */
863
- protected function convertOptionsToValues( $options ) {
864
  foreach ( $options as $key => $value ) {
865
  if ( ! is_array( $value ) ) {
866
  continue;
867
  }
868
 
869
- if ( ! isset( $value['type'] ) ) {
870
- $options[ $key ] = $this->convertOptionsToValues( $value );
871
  continue;
872
  }
873
 
@@ -931,6 +1011,62 @@ trait Options {
931
  * @return void
932
  */
933
  public function refresh() {
 
 
934
  $this->init();
935
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
936
  }
13
  */
14
  trait Options {
15
  /**
16
+ * Whether or not this instance is a clone.
17
  *
18
+ * @since 4.1.4
19
+ *
20
+ * @var boolean
21
+ */
22
+ public $isClone = false;
23
+
24
+ /**
25
+ * Whether or not the options need to be saved to the DB.
26
+ *
27
+ * @since 4.1.4
28
  *
29
  * @var string
30
  */
31
+ public $shouldSave = false;
32
 
33
  /**
34
+ * The name to lookup the options with.
35
  *
36
  * @since 4.0.0
37
  *
38
+ * @var string
39
  */
40
+ public $optionsName = '';
41
 
42
  /**
43
  * Holds the localized options.
130
  }
131
 
132
  // If we need to set a sub-group, do that now.
133
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
134
+ $defaults = $cachedOptions[ $this->groupKey ];
135
  if ( ! empty( $this->subGroups ) ) {
136
  foreach ( $this->subGroups as $subGroup ) {
137
  $defaults = $defaults[ $subGroup ];
149
  return $this->setSubGroup( $name );
150
  }
151
 
152
+ $value = isset( $cachedOptions[ $this->groupKey ][ $name ]['value'] )
153
+ ? $cachedOptions[ $this->groupKey ][ $name ]['value']
154
  : (
155
  ! empty( $this->arguments[0] )
156
  ? $this->arguments[0]
180
  }
181
 
182
  // If we need to set a sub-group, do that now.
183
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
184
+ $defaults = $cachedOptions[ $this->groupKey ];
185
  if ( ! empty( $this->subGroups ) ) {
186
  foreach ( $this->subGroups as $subGroup ) {
187
  $defaults = $defaults[ $subGroup ];
263
  }
264
 
265
  // If we need to set a sub-group, do that now.
266
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
267
+ $defaults = json_decode( wp_json_encode( $cachedOptions[ $this->groupKey ] ), true );
268
  if ( ! empty( $this->subGroups ) ) {
269
  foreach ( $this->subGroups as $subGroup ) {
270
  $defaults = &$defaults[ $subGroup ];
310
  update_option( $this->optionsName . '_localized', $this->localized );
311
  }
312
 
313
+ $originalDefaults = json_decode( wp_json_encode( $cachedOptions[ $this->groupKey ] ), true );
314
  $pointer = &$originalDefaults;
315
  foreach ( $this->subGroups as $subGroup ) {
316
  $pointer = &$pointer[ $subGroup ];
317
  }
318
  $pointer = $defaults;
319
 
320
+ $cachedOptions[ $this->groupKey ] = $originalDefaults;
321
+ aioseo()->optionsCache->setOptions( $this->optionsName, $cachedOptions );
322
 
323
  $this->resetGroups();
324
 
339
  }
340
 
341
  // If we need to set a sub-group, do that now.
342
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
343
+ $defaults = $cachedOptions[ $this->groupKey ];
344
  if ( ! empty( $this->subGroups ) ) {
345
  foreach ( $this->subGroups as $subGroup ) {
346
  $defaults = &$defaults[ $subGroup ];
379
  }
380
 
381
  // If we need to set a sub-group, do that now.
382
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
383
+ $defaults = json_decode( wp_json_encode( $cachedOptions[ $this->groupKey ] ), true );
384
  if ( ! empty( $this->subGroups ) ) {
385
  foreach ( $this->subGroups as $subGroup ) {
386
  $defaults = &$defaults[ $subGroup ];
403
 
404
  unset( $defaults[ $name ]['value'] );
405
 
406
+ $cachedOptions[ $this->groupKey ] = $defaults;
407
+ aioseo()->optionsCache->setOptions( $this->optionsName, $cachedOptions );
 
408
 
409
  $this->resetGroups();
410
+
411
+ $this->update();
412
  }
413
 
414
  /**
421
  * @return array An array of options.
422
  */
423
  public function all( $include = [], $exclude = [] ) {
424
+ $originalGroupKey = $this->groupKey;
425
+ $originalSubGroups = $this->subGroups;
426
 
427
+ // Make sure our dynamic options have loaded.
428
+ $this->init();
429
 
430
  // Refactor options.
431
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
432
+ $refactored = $this->convertOptionsToValues( $cachedOptions );
433
 
434
  $this->groupKey = null;
435
 
437
  return $this->allFiltered( $refactored, $include, $exclude );
438
  }
439
 
440
+ if ( empty( $originalSubGroups ) ) {
441
  $all = $refactored[ $originalGroupKey ];
442
  return $this->allFiltered( $all, $include, $exclude );
443
  }
444
 
445
  $returnable = &$refactored[ $originalGroupKey ];
446
+ foreach ( $originalSubGroups as $subGroup ) {
447
  $returnable = &$returnable[ $subGroup ];
448
  }
449
 
461
  * @return void
462
  */
463
  public function reset( $include = [], $exclude = [] ) {
464
+ $originalGroupKey = $this->groupKey;
465
+ $originalSubGroups = $this->subGroups;
466
+
467
  // Make sure our dynamic options have loaded.
468
+ $this->init();
469
+
470
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
471
 
472
  // If we don't have a group key set, it means we want to reset everything.
473
+ if ( empty( $originalGroupKey ) ) {
474
+ $groupKeys = array_keys( $cachedOptions );
475
  foreach ( $groupKeys as $groupKey ) {
476
  $this->groupKey = $groupKey;
477
  $this->reset();
482
  }
483
 
484
  // If we need to set a sub-group, do that now.
485
+ $keys = array_merge( [ $originalGroupKey ], $originalSubGroups );
486
+ $defaults = json_decode( wp_json_encode( $cachedOptions[ $originalGroupKey ] ), true );
487
+ if ( ! empty( $originalSubGroups ) ) {
488
+ foreach ( $originalSubGroups as $subGroup ) {
489
  $defaults = $defaults[ $subGroup ];
490
  }
491
  }
492
 
493
  // Refactor options.
494
+ $resetValues = $this->resetValues( $defaults, $this->defaultsMerged, $keys, $include, $exclude );
495
+ $defaults = array_replace_recursive( $defaults, $resetValues );
496
 
497
+ $originalDefaults = json_decode( wp_json_encode( $cachedOptions[ $originalGroupKey ] ), true );
498
  $pointer = &$originalDefaults;
499
+ foreach ( $originalSubGroups as $subGroup ) {
500
  $pointer = &$pointer[ $subGroup ];
501
  }
502
  $pointer = $defaults;
503
 
504
+ $cachedOptions[ $originalGroupKey ] = $originalDefaults;
505
+ aioseo()->optionsCache->setOptions( $this->optionsName, $cachedOptions );
506
 
507
  $this->resetGroups();
508
 
552
  $optionOrGroup = '_aioseo_type';
553
  }
554
 
555
+ $originalGroupKey = $this->groupKey;
556
+ $originalSubGroups = $this->subGroups;
557
+
558
+ static $hasInitialized = false;
559
+ if ( ! $hasInitialized ) {
560
+ $hasInitialized = true;
561
+ $this->init();
562
+ }
563
 
564
  // If we need to set a sub-group, do that now.
565
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
566
+ $defaults = $originalGroupKey ? $cachedOptions[ $originalGroupKey ] : $cachedOptions;
567
+ if ( ! empty( $originalSubGroups ) ) {
568
+ foreach ( $originalSubGroups as $subGroup ) {
569
  $defaults = $defaults[ $subGroup ];
570
  }
571
  }
581
  return false;
582
  }
583
 
 
 
 
 
 
 
 
 
 
 
 
584
  /**
585
  * Filters the results based on passed in array.
586
  *
651
  : null;
652
  }
653
 
654
+ /**
655
+ * Gets the defaults options.
656
+ *
657
+ * @since 4.1.3
658
+ *
659
+ * @return array An array of dafults.
660
+ */
661
+ public function getDefaults() {
662
+ return $this->defaults;
663
+ }
664
+
665
  /**
666
  * Updates the options in the database.
667
  *
668
  * @since 4.0.0
669
  *
670
+ * @param string $optionsName An optional option name to update.
671
+ * @param string $defaults The defaults to filter the options by.
672
+ * @param array|null $options An optional options array.
673
  * @return void
674
  */
675
+ public function update( $optionsName = null, $defaults = null, $options = null ) {
676
+ $optionsName = empty( $optionsName ) ? $this->optionsName : $optionsName;
677
+ $defaults = empty( $defaults ) ? $this->defaults : $defaults;
678
+
679
  // First, we need to filter our options.
680
+ $options = $this->filterOptions( $defaults, $options );
681
 
682
  // Refactor options.
683
  $refactored = $this->convertOptionsToValues( $options );
684
 
685
  $this->resetGroups();
686
 
687
+ // The following needs to happen here (possibly a clone) as well as in the main instance.
688
+ $originalInstance = $this->getOriginalInstance();
689
+
690
+ // Update the DB options.
691
+ aioseo()->optionsCache->setDb( $optionsName, $refactored );
692
+
693
+ // Force a save here and in the main class.
694
+ $this->shouldSave = true;
695
+ $originalInstance->shouldSave = true;
696
+ }
697
+
698
+ /**
699
+ * Updates the options in the database.
700
+ *
701
+ * @since 4.1.4
702
+ *
703
+ * @param boolean $force Whether or not to force an immediate save.
704
+ * @param string $optionsName An optional option name to update.
705
+ * @param string $defaults The defaults to filter the options by.
706
+ * @return void
707
+ */
708
+ public function save( $force = false, $optionsName = null, $defaults = null ) {
709
+ if ( ! $this->shouldSave && ! $force ) {
710
+ return;
711
+ }
712
+
713
+ $optionsName = empty( $optionsName ) ? $this->optionsName : $optionsName;
714
+ $defaults = empty( $defaults ) ? $this->defaults : $defaults;
715
+
716
+ $this->update( $optionsName );
717
+
718
+ // First, we need to filter our options.
719
+ $options = $this->filterOptions( $defaults, null, $optionsName );
720
+
721
+ // Refactor options.
722
+ $refactored = $this->convertOptionsToValues( $options );
723
+
724
+ $this->resetGroups();
725
+
726
+ update_option( $optionsName, wp_json_encode( $refactored ) );
727
  }
728
 
729
  /**
736
  * @return array An array of filtered options.
737
  */
738
  public function filterOptions( $defaults, $options = null ) {
739
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
740
+ $options = ! empty( $options ) ? $options : json_decode( wp_json_encode( $cachedOptions ), true );
741
  return $this->filterRecursively( $options, $defaults );
742
  }
743
 
751
  * @return array A filtered array of options.
752
  */
753
  public function filterRecursively( $options, $defaults ) {
754
+ if ( ! is_array( $options ) ) {
755
+ return $options;
756
+ }
757
+
758
  foreach ( $options as $key => $value ) {
759
  if ( ! isset( $defaults[ $key ] ) ) {
760
  unset( $options[ $key ] );
795
  $array[ $k ] = sanitize_text_field( $preserveHtml ? htmlspecialchars( $v, ENT_NOQUOTES, 'UTF-8' ) : $v );
796
  }
797
  return $array;
798
+ case 'float':
799
+ return floatval( $value );
800
  }
801
  }
802
 
919
 
920
  // @TODO: See if we need this? could just eliminate.
921
  if ( ! is_array( $value ) ) {
 
 
 
922
  continue;
923
  }
924
 
940
  * @param array $options The options array.
941
  * @return array The converted options array.
942
  */
943
+ public function convertOptionsToValues( $options, $optionKey = 'type' ) {
944
  foreach ( $options as $key => $value ) {
945
  if ( ! is_array( $value ) ) {
946
  continue;
947
  }
948
 
949
+ if ( ! isset( $value[ $optionKey ] ) ) {
950
+ $options[ $key ] = $this->convertOptionsToValues( $value, $optionKey );
951
  continue;
952
  }
953
 
1011
  * @return void
1012
  */
1013
  public function refresh() {
1014
+ // Reset DB options to clear the cache.
1015
+ aioseo()->optionsCache->resetDb();
1016
  $this->init();
1017
  }
1018
+
1019
+ /**
1020
+ * Returns the DB options.
1021
+ *
1022
+ * @since 4.1.4
1023
+ *
1024
+ * @param string $optionsName The options name.
1025
+ * @return array The options.
1026
+ */
1027
+ public function getDbOptions( $optionsName ) {
1028
+ $cache = aioseo()->optionsCache->getDb( $optionsName );
1029
+ if ( empty( $cache ) ) {
1030
+ $options = json_decode( get_option( $optionsName ), true );
1031
+ $options = ! empty( $options ) ? $options : [];
1032
+
1033
+ // Set the cache.
1034
+ aioseo()->optionsCache->setDb( $optionsName, $options );
1035
+ }
1036
+
1037
+ return aioseo()->optionsCache->getDb( $optionsName );
1038
+ }
1039
+
1040
+ /**
1041
+ * In order to not have a conflict, we need to return a clone.
1042
+ *
1043
+ * @since 4.0.0
1044
+ *
1045
+ * @return Options The cloned Options object.
1046
+ */
1047
+ public function noConflict() {
1048
+ $class = clone $this;
1049
+ $class->isClone = true;
1050
+ return $class;
1051
+ }
1052
+
1053
+ /**
1054
+ * Get original instance. Since this could be a cloned object, let's get the original instance.
1055
+ *
1056
+ * @since 4.1.4
1057
+ *
1058
+ * @return self
1059
+ */
1060
+ public function getOriginalInstance() {
1061
+ if ( ! $this->isClone ) {
1062
+ return $this;
1063
+ }
1064
+
1065
+ $class = new \ReflectionClass( get_called_class() );
1066
+ $optionName = aioseo()->helpers->toCamelCase( $class->getShortName() );
1067
+
1068
+ if ( isset( aioseo()->{ $optionName } ) ) {
1069
+ return aioseo()->{ $optionName };
1070
+ }
1071
+ }
1072
  }
app/Common/Utils/Access.php CHANGED
@@ -15,11 +15,11 @@ class Access {
15
  * @var array
16
  */
17
  protected $capabilities = [
 
18
  'aioseo_general_settings',
19
  'aioseo_search_appearance_settings',
20
  'aioseo_social_networks_settings',
21
  'aioseo_sitemap_settings',
22
- 'aioseo_internal_links_settings',
23
  'aioseo_redirects_settings',
24
  'aioseo_seo_analysis_settings',
25
  'aioseo_tools_settings',
@@ -31,7 +31,8 @@ class Access {
31
  'aioseo_page_social_settings',
32
  'aioseo_local_seo_settings',
33
  'aioseo_page_local_seo_settings',
34
- 'aioseo_about_us_page'
 
35
  ];
36
 
37
  /**
@@ -43,7 +44,10 @@ class Access {
43
  */
44
  protected $roles = [
45
  'superadmin' => 'superadmin',
46
- 'administrator' => 'administrator'
 
 
 
47
  ];
48
 
49
  /**
@@ -53,12 +57,11 @@ class Access {
53
  */
54
  public function __construct() {
55
  $adminRoles = [];
56
- $wpRoles = wp_roles();
57
- $allRoles = $wpRoles->roles;
58
- foreach ( $allRoles as $key => $wpRole ) {
59
- $role = get_role( $key );
60
- if ( $role->has_cap( 'install_plugins' ) || $role->has_cap( 'publish_posts' ) ) {
61
- $adminRoles[ $key ] = $key;
62
  }
63
  }
64
 
@@ -74,29 +77,29 @@ class Access {
74
  * @return void
75
  */
76
  public function addCapabilities() {
 
 
77
  foreach ( $this->roles as $wpRole => $role ) {
78
  $roleObject = get_role( $wpRole );
79
  if ( ! is_object( $roleObject ) ) {
80
  continue;
81
  }
82
 
83
- if ( $this->canManage( $role ) ) {
84
  $roleObject->add_cap( 'aioseo_manage_seo' );
85
- } else {
86
- $roleObject->remove_cap( 'aioseo_manage_seo' );
87
  }
88
 
89
- if ( $this->isAdmin( $role ) ) {
90
- $roleObject->add_cap( 'aioseo_setup_wizard' );
91
- } else {
92
- $roleObject->remove_cap( 'aioseo_setup_wizard' );
93
- }
 
 
 
94
 
95
- foreach ( $this->getAllCapabilities( $role ) as $capability => $enabled ) {
96
- if ( $enabled ) {
97
  $roleObject->add_cap( $capability );
98
- } else {
99
- $roleObject->remove_cap( $capability );
100
  }
101
  }
102
  }
@@ -126,9 +129,12 @@ class Access {
126
  }
127
 
128
  $role = get_role( $key );
 
 
 
129
 
130
- // Anyone with install plugins can remain.
131
- if ( $role->has_cap( 'install_plugins' ) ) {
132
  continue;
133
  }
134
 
@@ -157,7 +163,13 @@ class Access {
157
  return true;
158
  }
159
 
160
- if ( $this->canPublish( $checkRole ) && false !== strpos( $capability, 'aioseo_page_' ) ) {
 
 
 
 
 
 
161
  return true;
162
  }
163
 
@@ -174,17 +186,28 @@ class Access {
174
  */
175
  public function getAllCapabilities( $role = null ) {
176
  $capabilities = [];
177
- foreach ( $this->capabilities as $capability ) {
178
  $capabilities[ $capability ] = $this->hasCapability( $capability, $role );
179
  }
180
 
181
- $capabilities['aioseo_setup_wizard'] = $this->isAdmin( $role );
182
- $capabilities['aioseo_admin'] = $this->isAdmin( $role );
183
- $capabilities['aioseo_manage_seo'] = $this->canManage( $role );
184
 
185
  return $capabilities;
186
  }
187
 
 
 
 
 
 
 
 
 
 
 
 
188
  /**
189
  * If the current user is an admin, or superadmin, they have access to all caps regardless.
190
  *
@@ -195,29 +218,14 @@ class Access {
195
  */
196
  public function isAdmin( $role = null ) {
197
  if ( $role ) {
198
- if ( is_multisite() && 'superadmin' === $role ) {
199
- return true;
200
- }
201
-
202
- if ( ! is_multisite() && 'administrator' === $role ) {
203
  return true;
204
  }
205
 
206
- $wpRoles = wp_roles();
207
- $allRoles = $wpRoles->roles;
208
- foreach ( $allRoles as $key => $wpRole ) {
209
- if ( $key === $role ) {
210
- $r = get_role( $key );
211
- if ( $r->has_cap( 'install_plugins' ) ) {
212
- return true;
213
- }
214
- }
215
- }
216
-
217
  return false;
218
  }
219
 
220
- if ( ( is_multisite() && current_user_can( 'superadmin' ) ) || current_user_can( 'administrator' ) || current_user_can( 'install_plugins' ) ) {
221
  return true;
222
  }
223
 
@@ -229,12 +237,13 @@ class Access {
229
  *
230
  * @since 4.0.9
231
  *
232
- * @param string $role The role to check.
233
- * @return boolean True if the role can publish.
 
234
  */
235
- protected function canPublish( $role ) {
236
  if ( empty( $role ) ) {
237
- return current_user_can( 'publish_posts' );
238
  }
239
 
240
  $wpRoles = wp_roles();
@@ -242,7 +251,7 @@ class Access {
242
  foreach ( $allRoles as $key => $wpRole ) {
243
  if ( $key === $role ) {
244
  $r = get_role( $key );
245
- if ( $r->has_cap( 'publish_posts' ) ) {
246
  return true;
247
  }
248
  }
@@ -252,15 +261,39 @@ class Access {
252
  }
253
 
254
  /**
255
- * Checks if the passed in role can manage AIOSEO.
256
  *
257
  * @since 4.0.0
258
  *
259
- * @param string $role The role to check against.
260
- * @return bool Whether or not the user can manage AIOSEO.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  */
262
- protected function canManage( $role ) {
263
- return $this->isAdmin( $role );
264
  }
265
 
266
  /**
15
  * @var array
16
  */
17
  protected $capabilities = [
18
+ 'aioseo_dashboard',
19
  'aioseo_general_settings',
20
  'aioseo_search_appearance_settings',
21
  'aioseo_social_networks_settings',
22
  'aioseo_sitemap_settings',
 
23
  'aioseo_redirects_settings',
24
  'aioseo_seo_analysis_settings',
25
  'aioseo_tools_settings',
31
  'aioseo_page_social_settings',
32
  'aioseo_local_seo_settings',
33
  'aioseo_page_local_seo_settings',
34
+ 'aioseo_about_us_page',
35
+ 'aioseo_setup_wizard'
36
  ];
37
 
38
  /**
44
  */
45
  protected $roles = [
46
  'superadmin' => 'superadmin',
47
+ 'administrator' => 'administrator',
48
+ 'editor' => 'editor',
49
+ 'author' => 'author',
50
+ 'contributor' => 'contributor'
51
  ];
52
 
53
  /**
57
  */
58
  public function __construct() {
59
  $adminRoles = [];
60
+ $allRoles = aioseo()->helpers->getUserRoles();
61
+ foreach ( $allRoles as $roleName => $wpRole ) {
62
+ $role = get_role( $roleName );
63
+ if ( $this->isAdmin( $roleName ) || $role->has_cap( 'publish_posts' ) ) {
64
+ $adminRoles[ $roleName ] = $roleName;
 
65
  }
66
  }
67
 
77
  * @return void
78
  */
79
  public function addCapabilities() {
80
+ $this->isUpdatingRoles = true;
81
+
82
  foreach ( $this->roles as $wpRole => $role ) {
83
  $roleObject = get_role( $wpRole );
84
  if ( ! is_object( $roleObject ) ) {
85
  continue;
86
  }
87
 
88
+ if ( $this->isAdmin( $role ) ) {
89
  $roleObject->add_cap( 'aioseo_manage_seo' );
 
 
90
  }
91
 
92
+ if ( current_user_can( 'edit_posts' ) ) {
93
+ $postCapabilities = [
94
+ 'aioseo_page_analysis',
95
+ 'aioseo_page_general_settings',
96
+ 'aioseo_page_advanced_settings',
97
+ 'aioseo_page_schema_settings',
98
+ 'aioseo_page_social_settings',
99
+ ];
100
 
101
+ foreach ( $postCapabilities as $capability ) {
 
102
  $roleObject->add_cap( $capability );
 
 
103
  }
104
  }
105
  }
129
  }
130
 
131
  $role = get_role( $key );
132
+ if ( empty( $role ) ) {
133
+ continue;
134
+ }
135
 
136
+ // Any Admin can remain.
137
+ if ( $this->isAdmin( $key ) ) {
138
  continue;
139
  }
140
 
163
  return true;
164
  }
165
 
166
+ if (
167
+ (
168
+ $this->can( 'publish_posts', $checkRole ) ||
169
+ $this->can( 'edit_posts', $checkRole )
170
+ ) &&
171
+ false !== strpos( $capability, 'aioseo_page_' )
172
+ ) {
173
  return true;
174
  }
175
 
186
  */
187
  public function getAllCapabilities( $role = null ) {
188
  $capabilities = [];
189
+ foreach ( $this->getCapabilityList() as $capability ) {
190
  $capabilities[ $capability ] = $this->hasCapability( $capability, $role );
191
  }
192
 
193
+ $capabilities['aioseo_admin'] = $this->isAdmin( $role );
194
+ $capabilities['aioseo_manage_seo'] = $this->isAdmin( $role );
195
+ $capabilities['aioseo_about_us_page'] = $this->canManage( $role );
196
 
197
  return $capabilities;
198
  }
199
 
200
+ /**
201
+ * Returns the capability list.
202
+ *
203
+ * @return 4.1.3
204
+ *
205
+ * @return array An array of capabilities.
206
+ */
207
+ public function getCapabilityList() {
208
+ return $this->capabilities;
209
+ }
210
+
211
  /**
212
  * If the current user is an admin, or superadmin, they have access to all caps regardless.
213
  *
218
  */
219
  public function isAdmin( $role = null ) {
220
  if ( $role ) {
221
+ if ( ( is_multisite() && 'superadmin' === $role ) || 'administrator' === $role ) {
 
 
 
 
222
  return true;
223
  }
224
 
 
 
 
 
 
 
 
 
 
 
 
225
  return false;
226
  }
227
 
228
+ if ( ( is_multisite() && current_user_can( 'superadmin' ) ) || current_user_can( 'administrator' ) ) {
229
  return true;
230
  }
231
 
237
  *
238
  * @since 4.0.9
239
  *
240
+ * @param string $capability The capability to check against.
241
+ * @param string $role The role to check.
242
+ * @return boolean True if the role can publish.
243
  */
244
+ protected function can( $capability, $role ) {
245
  if ( empty( $role ) ) {
246
+ return current_user_can( $capability );
247
  }
248
 
249
  $wpRoles = wp_roles();
251
  foreach ( $allRoles as $key => $wpRole ) {
252
  if ( $key === $role ) {
253
  $r = get_role( $key );
254
+ if ( $r->has_cap( $capability ) ) {
255
  return true;
256
  }
257
  }
261
  }
262
 
263
  /**
264
+ * Checks if the current user can manage AIOSEO.
265
  *
266
  * @since 4.0.0
267
  *
268
+ * @param string|null $checkRole A role to check against.
269
+ * @return bool Whether or not the user can manage AIOSEO.
270
+ */
271
+ public function canManage( $checkRole = null ) {
272
+ return $this->isAdmin( $checkRole );
273
+ }
274
+
275
+ /**
276
+ * Gets all options that the user does not have access to manage.
277
+ *
278
+ * @since 4.1.3
279
+ *
280
+ * @param string $role The given role.
281
+ * @return array An array with the option names.
282
+ */
283
+ public function getNotAllowedOptions() {
284
+ return [];
285
+ }
286
+
287
+ /**
288
+ * Gets all page fields that the user does not have access to manage.
289
+ *
290
+ * @since 4.1.3
291
+ *
292
+ * @param string $role The given role.
293
+ * @return array An array with the field names.
294
  */
295
+ public function getNotAllowedPageFields() {
296
+ return [];
297
  }
298
 
299
  /**
app/Common/Utils/Addons.php CHANGED
@@ -60,15 +60,76 @@ class Addons {
60
  // The API request will tell us if we can activate a plugin, but let's check if its already active.
61
  $installedPlugins = array_keys( get_plugins() );
62
  foreach ( $addons as $key => $addon ) {
63
- $addons[ $key ]->basename = $this->getAddonBasename( $addon->sku );
64
- $addons[ $key ]->installed = in_array( $this->getAddonBasename( $addon->sku ), $installedPlugins, true );
65
- $addons[ $key ]->isActive = is_plugin_active( $addons[ $key ]->basename );
66
- $addons[ $key ]->canInstall = $this->canInstall();
 
 
67
  }
68
 
69
  return $addons;
70
  }
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  /**
73
  * Get the data for a specific addon.
74
  *
@@ -302,6 +363,21 @@ class Addons {
302
  return true;
303
  }
304
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  /**
306
  * Load an addon into aioseo
307
  *
60
  // The API request will tell us if we can activate a plugin, but let's check if its already active.
61
  $installedPlugins = array_keys( get_plugins() );
62
  foreach ( $addons as $key => $addon ) {
63
+ $addons[ $key ]->basename = $this->getAddonBasename( $addon->sku );
64
+ $addons[ $key ]->installed = in_array( $this->getAddonBasename( $addon->sku ), $installedPlugins, true );
65
+ $addons[ $key ]->isActive = is_plugin_active( $addons[ $key ]->basename );
66
+ $addons[ $key ]->canInstall = $this->canInstall();
67
+ $addons[ $key ]->canActivate = $this->canActivate();
68
+ $addons[ $key ]->capability = $this->getManageCapability( $addon->sku );
69
  }
70
 
71
  return $addons;
72
  }
73
 
74
+ /**
75
+ * Returns the required capability to manage the addon.
76
+ *
77
+ * @since 4.1.3
78
+ *
79
+ * @param string $sku The addon sku.
80
+ * @return string The required capability.
81
+ */
82
+ protected function getManageCapability( $sku ) {
83
+ $capability = apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' );
84
+
85
+ switch ( $sku ) {
86
+ case 'aioseo-image-seo':
87
+ $capability = 'aioseo_search_appearance_settings';
88
+ break;
89
+ case 'aioseo-video-sitemap':
90
+ case 'aioseo-news-sitemap':
91
+ $capability = 'aioseo_sitemap_settings';
92
+ break;
93
+ case 'aioseo-redirects':
94
+ $capability = 'aioseo_redirects_settings';
95
+ break;
96
+ case 'aioseo-local-business':
97
+ $capability = 'aioseo_local_seo_settings';
98
+ break;
99
+ }
100
+ return $capability;
101
+ }
102
+
103
+ /**
104
+ * Check to see if there are unlicensed addons installed and activated.
105
+ *
106
+ * @since 4.1.3
107
+ *
108
+ * @return boolean True if there are unlicensed addons, false if not.
109
+ */
110
+ public function unlicensedAddons() {
111
+ $unlicensed = [
112
+ 'addons' => [],
113
+ // Translators: 1 - Opening bold tag, 2 - Plugin short name ("AIOSEO"), 3 - "Pro", 4 - Closing bold tag.
114
+ 'message' => sprintf(
115
+ __( 'The following addons cannot be used, because they require %1$s%2$s %3$s%4$s to work:', 'all-in-one-seo-pack' ),
116
+ '<strong>',
117
+ AIOSEO_PLUGIN_SHORT_NAME,
118
+ 'Pro',
119
+ '</strong>'
120
+ )
121
+ ];
122
+
123
+ $addons = $this->getAddons();
124
+ foreach ( $addons as $addon ) {
125
+ if ( $addon->isActive ) {
126
+ $unlicensed['addons'][] = $addon;
127
+ }
128
+ }
129
+
130
+ return $unlicensed;
131
+ }
132
+
133
  /**
134
  * Get the data for a specific addon.
135
  *
363
  return true;
364
  }
365
 
366
+ /**
367
+ * Determine if addons/plugins can be activated.
368
+ *
369
+ * @since 4.1.3
370
+ *
371
+ * @return bool True if yes, false if not.
372
+ */
373
+ public function canActivate() {
374
+ if ( ! current_user_can( 'activate_plugins' ) ) {
375
+ return false;
376
+ }
377
+
378
+ return true;
379
+ }
380
+
381
  /**
382
  * Load an addon into aioseo
383
  *
app/Common/Utils/Database.php CHANGED
@@ -273,7 +273,7 @@ class Database {
273
  * @return boolean Whether or not the table exists.
274
  */
275
  public function tableExists( $table ) {
276
- $results = $this->db->get_results( 'SHOW TABLES LIKE "' . $this->prefix . $table . '"' );
277
  return ! ( empty( $results ) );
278
  }
279
 
@@ -696,7 +696,8 @@ class Database {
696
  }
697
 
698
  foreach ( $values as &$value ) {
699
- if ( is_numeric( $value ) ) {
 
700
  // No change.
701
  } elseif ( is_null( $value ) || false !== stristr( $value, 'NULL' ) ) {
702
  // Change to a true NULL value.
@@ -890,26 +891,6 @@ class Database {
890
  return $this;
891
  }
892
 
893
- /**
894
- * Enable/disable HTML stripping.
895
- *
896
- * @since 4.0.0
897
- *
898
- * @param boolean $value Whether or not to enable/disable HTML stripping.
899
- * @return Database Returns the Database class which can be method chained for more query building.
900
- */
901
- public function setStripTags( $value ) {
902
- $options = $this->getEscapeOptions();
903
- if ( $value ) {
904
- $options = $options | DatabaseConnection::ESCAPE_STRIP_HTML;
905
- } else {
906
- $options = $options & ~DatabaseConnection::ESCAPE_STRIP_HTML;
907
- }
908
-
909
- $this->setEscapeOptions( $options );
910
- return $this;
911
- }
912
-
913
  /**
914
  * Set the output for the query.
915
  *
@@ -1147,13 +1128,14 @@ class Database {
1147
  $value = wp_strip_all_tags( $value );
1148
  }
1149
 
1150
- if ( ( $options & self::ESCAPE_FORCE ) !== 0 || php_sapi_name() === 'cli' ) {
1151
- $value = $this->db->_real_escape( $value );
1152
- }
1153
-
1154
- if ( ( $options & self::ESCAPE_QUOTE ) !== 0 && ! is_integer( $value ) ) {
1155
- $value = addslashes( $value );
1156
- $value = "'$value'";
 
1157
  }
1158
 
1159
  return $value;
273
  * @return boolean Whether or not the table exists.
274
  */
275
  public function tableExists( $table ) {
276
+ $results = $this->db->get_results( "SHOW TABLES LIKE '" . $this->prefix . $table . "'" );
277
  return ! ( empty( $results ) );
278
  }
279
 
696
  }
697
 
698
  foreach ( $values as &$value ) {
699
+ // Note: We can no longer check for `is_numeric` because a value like `61021e6242255` returns true and breaks the query.
700
+ if ( is_integer( $value ) || is_float( $value ) ) {
701
  // No change.
702
  } elseif ( is_null( $value ) || false !== stristr( $value, 'NULL' ) ) {
703
  // Change to a true NULL value.
891
  return $this;
892
  }
893
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
894
  /**
895
  * Set the output for the query.
896
  *
1128
  $value = wp_strip_all_tags( $value );
1129
  }
1130
 
1131
+ if (
1132
+ ( ( $options & self::ESCAPE_FORCE ) !== 0 || php_sapi_name() === 'cli' ) ||
1133
+ ( ( $options & self::ESCAPE_QUOTE ) !== 0 && ! is_integer( $value ) )
1134
+ ) {
1135
+ $value = esc_sql( $value );
1136
+ if ( ! is_integer( $value ) ) {
1137
+ $value = "'$value'";
1138
+ }
1139
  }
1140
 
1141
  return $value;
app/Common/Utils/Helpers.php CHANGED
@@ -6,8 +6,6 @@ if ( ! defined( 'ABSPATH' ) ) {
6
  exit;
7
  }
8
 
9
- use AIOSEO\Plugin\Common\Models;
10
- use AIOSEO\Plugin\Common\Tools;
11
  use AIOSEO\Plugin\Common\Traits\Helpers as TraitHelpers;
12
 
13
  /**
@@ -17,19 +15,18 @@ use AIOSEO\Plugin\Common\Traits\Helpers as TraitHelpers;
17
  */
18
  class Helpers {
19
  use TraitHelpers\ActionScheduler;
 
20
  use TraitHelpers\Constants;
21
  use TraitHelpers\DateTime;
 
22
  use TraitHelpers\Shortcodes;
23
  use TraitHelpers\Strings;
24
-
25
- /**
26
- * Whether or not we have a local connection.
27
- *
28
- * @since 4.0.0
29
- *
30
- * @var bool
31
- */
32
- private static $connection = false;
33
 
34
  /**
35
  * Generate a UTM URL from the url and medium/content passed in.
@@ -58,1802 +55,101 @@ class Helpers {
58
  'utm_medium' => $medium
59
  ];
60
 
61
- // Content is not used by default.
62
- if ( $content ) {
63
- $args['utm_content'] = $content;
64
- }
65
-
66
- // Return the new URL.
67
- $url = add_query_arg( $args, $url );
68
- return $esc ? esc_url( $url ) : $url;
69
- }
70
-
71
- /**
72
- * Get the home page object.
73
- *
74
- * @since 4.1.1
75
- *
76
- * @return WP_Post|null The home page.
77
- */
78
- public function getHomePage() {
79
- $homePageId = $this->getHomePageId();
80
-
81
- return $homePageId ? get_post( $homePageId ) : null;
82
- }
83
-
84
- /**
85
- * Get the ID of the home page.
86
- *
87
- * @since 4.0.0
88
- *
89
- * @return integer|null The home page ID.
90
- */
91
- public function getHomePageId() {
92
- $pageShowOnFront = ( 'page' === get_option( 'show_on_front' ) );
93
- $pageOnFrontId = get_option( 'page_on_front' );
94
-
95
- return $pageShowOnFront && $pageOnFrontId ? (int) $pageOnFrontId : null;
96
- }
97
-
98
- /**
99
- * Returns the blog page.
100
- *
101
- * @since 4.0.0
102
- *
103
- * @return WP_Post|null The blog page.
104
- */
105
- public function getBlogPage() {
106
- $blogPageId = $this->getBlogPageId();
107
-
108
- return $blogPageId ? get_post( $blogPageId ) : null;
109
- }
110
-
111
- /**
112
- * Gets the current blog page id if it's configured.
113
- *
114
- * @since 4.1.1
115
- *
116
- * @return int|null
117
- */
118
- public function getBlogPageId() {
119
- $pageShowOnFront = ( 'page' === get_option( 'show_on_front' ) );
120
- $blogPageId = (int) get_option( 'page_for_posts' );
121
-
122
- return $pageShowOnFront && $blogPageId ? $blogPageId : null;
123
- }
124
-
125
- /**
126
- * Returns the All in One SEO Logo
127
- *
128
- * @since 4.0.0
129
- *
130
- * @param string $width The width of the image.
131
- * @param string $height The height of the image.
132
- * @param string $colorCode The color of the image.
133
- * @return string The logo as a string.
134
- */
135
- public function logo( $width, $height, $colorCode ) {
136
- return '<svg viewBox="0 0 20 20" width="' . $width . '" height="' . $height . '" fill="none" xmlns="http://www.w3.org/2000/svg" class="aioseo-gear"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.98542 19.9708C15.5002 19.9708 19.9708 15.5002 19.9708 9.98542C19.9708 4.47063 15.5002 0 9.98542 0C4.47063 0 0 4.47063 0 9.98542C0 15.5002 4.47063 19.9708 9.98542 19.9708ZM8.39541 3.65464C8.26016 3.4485 8.0096 3.35211 7.77985 3.43327C7.51816 3.52572 7.26218 3.63445 7.01349 3.7588C6.79519 3.86796 6.68566 4.11731 6.73372 4.36049L6.90493 5.22694C6.949 5.44996 6.858 5.6763 6.68522 5.82009C6.41216 6.04734 6.16007 6.30426 5.93421 6.58864C5.79383 6.76539 5.57233 6.85907 5.35361 6.81489L4.50424 6.6433C4.26564 6.5951 4.02157 6.70788 3.91544 6.93121C3.85549 7.05738 3.79889 7.1862 3.74583 7.31758C3.69276 7.44896 3.64397 7.58105 3.59938 7.71369C3.52048 7.94847 3.61579 8.20398 3.81839 8.34133L4.53958 8.83027C4.72529 8.95617 4.81778 9.1819 4.79534 9.40826C4.75925 9.77244 4.76072 10.136 4.79756 10.4936C4.82087 10.7198 4.72915 10.9459 4.54388 11.0724L3.82408 11.5642C3.62205 11.7022 3.52759 11.9579 3.60713 12.1923C3.69774 12.4593 3.8043 12.7205 3.92615 12.9743C4.03313 13.1971 4.27749 13.3088 4.51581 13.2598L5.36495 13.0851C5.5835 13.0401 5.80533 13.133 5.94623 13.3093C6.16893 13.5879 6.42071 13.8451 6.6994 14.0756C6.87261 14.2188 6.96442 14.4448 6.92112 14.668L6.75296 15.5348C6.70572 15.7782 6.81625 16.0273 7.03511 16.1356C7.15876 16.1967 7.285 16.2545 7.41375 16.3086C7.54251 16.3628 7.67196 16.4126 7.80195 16.4581C8.18224 16.5912 8.71449 16.1147 9.108 15.7625C9.30205 15.5888 9.42174 15.343 9.42301 15.0798C9.42301 15.0784 9.42302 15.077 9.42302 15.0756L9.42301 13.6263C9.42301 13.6109 9.4236 13.5957 9.42476 13.5806C8.26248 13.2971 7.39838 12.2301 7.39838 10.9572V9.41823C7.39838 9.30125 7.49131 9.20642 7.60596 9.20642H8.32584V7.6922C8.32584 7.48312 8.49193 7.31364 8.69683 7.31364C8.90171 7.31364 9.06781 7.48312 9.06781 7.6922V9.20642H11.0155V7.6922C11.0155 7.48312 11.1816 7.31364 11.3865 7.31364C11.5914 7.31364 11.7575 7.48312 11.7575 7.6922V9.20642H12.4773C12.592 9.20642 12.6849 9.30125 12.6849 9.41823V10.9572C12.6849 12.2704 11.7653 13.3643 10.5474 13.6051C10.5477 13.6121 10.5478 13.6192 10.5478 13.6263L10.5478 15.0694C10.5478 15.3377 10.6711 15.5879 10.871 15.7622C11.2715 16.1115 11.8129 16.5837 12.191 16.4502C12.4527 16.3577 12.7086 16.249 12.9573 16.1246C13.1756 16.0155 13.2852 15.7661 13.2371 15.5229L13.0659 14.6565C13.0218 14.4334 13.1128 14.2071 13.2856 14.0633C13.5587 13.8361 13.8107 13.5792 14.0366 13.2948C14.177 13.118 14.3985 13.0244 14.6172 13.0685L15.4666 13.2401C15.7052 13.2883 15.9493 13.1756 16.0554 12.9522C16.1153 12.8261 16.1719 12.6972 16.225 12.5659C16.2781 12.4345 16.3269 12.3024 16.3714 12.1698C16.4503 11.935 16.355 11.6795 16.1524 11.5421L15.4312 11.0532C15.2455 10.9273 15.153 10.7015 15.1755 10.4752C15.2116 10.111 15.2101 9.74744 15.1733 9.38986C15.1499 9.16361 15.2417 8.93757 15.4269 8.811L16.1467 8.31927C16.3488 8.18126 16.4432 7.92558 16.3637 7.69115C16.2731 7.42411 16.1665 7.16292 16.0447 6.90915C15.9377 6.68638 15.6933 6.57462 15.455 6.62366L14.6059 6.79837C14.3873 6.84334 14.1655 6.75048 14.0246 6.57418C13.8019 6.29554 13.5501 6.03832 13.2714 5.80784C13.0982 5.6646 13.0064 5.43858 13.0497 5.2154L13.2179 4.34868C13.2651 4.10521 13.1546 3.85616 12.9357 3.74787C12.8121 3.68669 12.6858 3.62895 12.5571 3.5748C12.4283 3.52065 12.2989 3.47086 12.1689 3.42537C11.9388 3.34485 11.6884 3.44211 11.5538 3.64884L11.0746 4.38475C10.9513 4.57425 10.73 4.66862 10.5082 4.64573C10.1513 4.6089 9.79502 4.61039 9.44459 4.64799C9.22286 4.67177 9.00134 4.57818 8.87731 4.38913L8.39541 3.65464Z" fill="' . $colorCode . '" /></svg>'; // phpcs:ignore Generic.Files.LineLength.MaxExceeded
137
- }
138
-
139
- /**
140
- * Returns Jed-formatted localization data. Added for backwards-compatibility.
141
- *
142
- * @since 4.0.0
143
- *
144
- * @param string $domain Translation domain.
145
- * @return array An array of information for the locale.
146
- */
147
- public function getJedLocaleData( $domain ) {
148
- $translations = get_translations_for_domain( $domain );
149
-
150
- $locale = [
151
- '' => [
152
- 'domain' => $domain,
153
- 'lang' => is_admin() && function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(),
154
- ],
155
- ];
156
-
157
- if ( ! empty( $translations->headers['Plural-Forms'] ) ) {
158
- $locale['']['plural_forms'] = $translations->headers['Plural-Forms'];
159
- }
160
-
161
- foreach ( $translations->entries as $msgid => $entry ) {
162
- $locale[ $msgid ] = $entry->translations;
163
- }
164
-
165
- return $locale;
166
- }
167
-
168
- /**
169
- * Checks whether current page supports meta.
170
- *
171
- * @since 4.0.0
172
- *
173
- * @return boolean Whether the current page supports meta.
174
- */
175
- public function supportsMeta() {
176
- return ! is_date() && ! is_author() && ! is_search() && ! is_404();
177
- }
178
-
179
- /**
180
- * Checks whether the current page is a taxonomy term archive.
181
- *
182
- * @since 4.0.0
183
- *
184
- * @return boolean Whether the current page is a taxonomy term archive.
185
- */
186
- public function isTaxTerm() {
187
- $object = get_queried_object();
188
- return $object instanceof \WP_Term;
189
- }
190
-
191
- /**
192
- * Checks whether the current page is a static one.
193
- *
194
- * @since 4.0.0
195
- *
196
- * @return boolean Whether the current page is a static one.
197
- */
198
- public function isStaticPage() {
199
- return $this->isStaticHomePage() || $this->isStaticPostsPage() || $this->isWooCommerceShopPage();
200
- }
201
-
202
- /**
203
- * Checks whether the current page is the static homepage.
204
- *
205
- * @since 4.0.0
206
- *
207
- * @param mixed $post Pass in an optional post to check if its the static home page.
208
- * @return boolean Whether the current page is the static homepage.
209
- */
210
- public function isStaticHomePage( $post = null ) {
211
- static $isHomePage = null;
212
- if ( null !== $isHomePage ) {
213
- return $isHomePage;
214
- }
215
-
216
- $post = aioseo()->helpers->getPost( $post );
217
- return ( 'page' === get_option( 'show_on_front' ) && ! empty( $post->ID ) && (int) get_option( 'page_on_front' ) === $post->ID );
218
- }
219
-
220
- /**
221
- * Checks whether the current page is the static posts page.
222
- *
223
- * @since 4.0.0
224
- *
225
- * @return boolean Whether the current page is the static posts page.
226
- */
227
- public function isStaticPostsPage() {
228
- return is_home() && ( 0 !== (int) get_option( 'page_for_posts' ) );
229
- }
230
-
231
- /**
232
- * Checks whether WooCommerce is active.
233
- *
234
- * @since 4.0.0
235
- *
236
- * @return boolean Whether WooCommerce is active.
237
- */
238
- public function isWooCommerceActive() {
239
- return class_exists( 'woocommerce' );
240
- }
241
-
242
- /**
243
- * Checks whether the queried object is the WooCommerce shop page.
244
- *
245
- * @since 4.0.0
246
- *
247
- * @return boolean
248
- */
249
- public function isWooCommerceShopPage() {
250
- $screenCheck = true;
251
- if ( is_admin() && function_exists( 'get_current_screen' ) ) {
252
- $screen = get_current_screen();
253
- $screenCheck = 'edit' !== $screen->base;
254
- }
255
- return $this->isWooCommerceActive() && function_exists( 'is_shop' ) && is_shop() && $screenCheck;
256
- }
257
-
258
- /**
259
- * Checks whether BuddyPress is active.
260
- *
261
- * @since 4.0.0
262
- *
263
- * @return boolean
264
- */
265
- public function isBuddyPressActive() {
266
- return class_exists( 'BuddyPress' );
267
- }
268
-
269
- /**
270
- * Checks whether the queried object is a buddy press user page.
271
- *
272
- * @since 4.0.0
273
- *
274
- * @return boolean
275
- */
276
- public function isBuddyPressUser() {
277
- return $this->isBuddyPressActive() && function_exists( 'bp_is_user' ) && bp_is_user();
278
- }
279
-
280
- /**
281
- * Helper method to enqueue scripts.
282
- *
283
- * @since 4.0.0
284
- *
285
- * @param string $script The script to enqueue.
286
- * @param string $url The URL of the script.
287
- * @param bool $vue Whether or not this is a vue script.
288
- * @return void
289
- */
290
- public function enqueueScript( $script, $url, $vue = true ) {
291
- if ( ! wp_script_is( $script, 'enqueued' ) ) {
292
- wp_enqueue_script(
293
- $script,
294
- $this->getScriptUrl( $url, $vue ),
295
- [],
296
- aioseo()->version,
297
- true
298
- );
299
- }
300
- }
301
-
302
- /**
303
- * Helper method to enqueue stylesheets.
304
- *
305
- * @since 4.0.0
306
- *
307
- * @param string $style The stylesheet to enqueue.
308
- * @param string $url The URL of the stylesheet.
309
- * @param bool $vue Whether or not this is a vue stylesheet.
310
- * @return void
311
- */
312
- public function enqueueStyle( $style, $url, $vue = true ) {
313
- if ( ! wp_style_is( $style, 'enqueued' ) && $this->shouldEnqueue( $url ) ) {
314
- wp_enqueue_style(
315
- $style,
316
- $this->getScriptUrl( $url, $vue ),
317
- [],
318
- aioseo()->version
319
- );
320
- }
321
- }
322
-
323
- /**
324
- * Localizes a given URL.
325
- *
326
- * This is required for compatibility with WPML.
327
- *
328
- * @since 4.0.0
329
- *
330
- * @param string $path The relative path of the URL.
331
- * @return string $url The filtered URL.
332
- */
333
- public function localizedUrl( $path ) {
334
- $url = apply_filters( 'wpml_home_url', home_url( '/' ) );
335
-
336
- // Remove URL parameters.
337
- preg_match_all( '/\?[\s\S]+/', $url, $matches );
338
-
339
- // Get the base URL.
340
- $url = preg_replace( '/\?[\s\S]+/', '', $url );
341
- $url = trailingslashit( $url );
342
- $url .= preg_replace( '/\//', '', $path, 1 );
343
-
344
- // Readd URL parameters.
345
- if ( $matches && $matches[0] ) {
346
- $url .= $matches[0][0];
347
- }
348
-
349
- return $url;
350
- }
351
-
352
- /**
353
- * Unsets a given value in a given array.
354
- *
355
- * This function should only be used if the given value only appears once in the array.
356
- *
357
- * @since 4.0.0
358
- *
359
- * @param array $array The array.
360
- * @param string $value The value that needs to be removed from the array.
361
- * @return array $array The filtered array.
362
- */
363
- public function unsetValue( $array, $value ) {
364
- if ( in_array( $value, $array, true ) ) {
365
- unset( $array[ array_search( $value, $array, true ) ] );
366
- };
367
- return $array;
368
- }
369
-
370
- /**
371
- * Formats a timestamp as an ISO 8601 date.
372
- *
373
- * @since 4.0.0
374
- *
375
- * @param string $dateTime The raw datetime.
376
- * @return string The formatted datetime.
377
- */
378
- public function formatDateTime( $dateTime ) {
379
- return gmdate( 'c', mysql2date( 'U', $dateTime ) );
380
- }
381
-
382
- /**
383
- * Formats a given URl as an absolute URL if it is relative.
384
- *
385
- * @since 4.0.0
386
- *
387
- * @param string $url The URL.
388
- * @return string $url The absolute URL.
389
- */
390
- public function makeUrlAbsolute( $url ) {
391
- if ( 0 !== strpos( $url, 'http' ) && '/' !== $url ) {
392
- if ( 0 === strpos( $url, '//' ) ) {
393
- $scheme = wp_parse_url( home_url(), PHP_URL_SCHEME );
394
- $url = $scheme . ':' . $url;
395
- } else {
396
- $url = home_url( $url );
397
- }
398
- }
399
- return $url;
400
- }
401
-
402
- /** Whether or not we should enqueue a file.
403
- *
404
- * @since 4.0.0
405
- *
406
- * @param string $url The url to check against.
407
- * @return bool Whether or not we should enqueue.
408
- */
409
- private function shouldEnqueue( $url ) {
410
- $version = strtoupper( aioseo()->versionPath );
411
- $host = defined( 'AIOSEO_DEV_' . $version ) ? constant( 'AIOSEO_DEV_' . $version ) : false;
412
-
413
- if ( ! $host ) {
414
- return true;
415
- }
416
-
417
- if ( false !== strpos( $url, 'chunk-common.css' ) ) {
418
- // return false;
419
- }
420
-
421
- return true;
422
- }
423
-
424
- /**
425
- * Retrieve the proper URL for this script or style.
426
- *
427
- * @since 4.0.0
428
- *
429
- * @param string $url The url.
430
- * @param bool $vue Whether or not this is a vue script.
431
- * @return string The modified url.
432
- */
433
- public function getScriptUrl( $url, $vue = true ) {
434
- $version = strtoupper( aioseo()->versionPath );
435
- $host = $vue && defined( 'AIOSEO_DEV_' . $version ) ? constant( 'AIOSEO_DEV_' . $version ) : false;
436
- $localUrl = $url;
437
- $url = plugins_url( 'dist/' . aioseo()->versionPath . '/assets/' . $url, AIOSEO_FILE );
438
-
439
- if ( ! $host ) {
440
- return $url;
441
- }
442
-
443
- if ( $host && ! self::$connection ) {
444
- $splitHost = explode( ':', str_replace( '/', '', str_replace( 'http://', '', $host ) ) );
445
- self::$connection = @fsockopen( $splitHost[0], $splitHost[1] ); // phpcs:ignore WordPress
446
- }
447
-
448
- if ( ! self::$connection ) {
449
- return $url;
450
- }
451
-
452
- return $host . $localUrl;
453
- }
454
-
455
- /**
456
- * Gets the data for vue.
457
- *
458
- * @since 4.0.0
459
- *
460
- * @param string $page The current page.
461
- * @return array An array of data.
462
- */
463
- public function getVueData( $page = null ) {
464
- $postTypeObj = get_post_type_object( get_post_type( get_the_ID() ) );
465
- $screen = get_current_screen();
466
-
467
- // Check if user has a custom filename from the V3 migration.
468
- $sitemapFilename = aioseo()->sitemap->helpers->filename( 'general' );
469
- $sitemapFilename = $sitemapFilename ? $sitemapFilename : 'sitemap';
470
-
471
- $isStaticHomePage = 'page' === get_option( 'show_on_front' );
472
- $staticHomePage = intval( get_option( 'page_on_front' ) );
473
- $data = [
474
- 'page' => $page,
475
- 'translations' => $this->getJedLocaleData( 'all-in-one-seo-pack' ),
476
- 'screen' => [
477
- 'base' => $screen->base,
478
- 'postType' => $screen->post_type,
479
- 'blockEditor' => isset( $screen->is_block_editor ) ? $screen->is_block_editor : false
480
- ],
481
- 'internalOptions' => aioseo()->internalOptions->all(),
482
- 'options' => aioseo()->options->all(),
483
- 'settings' => aioseo()->settings->all(),
484
- 'tags' => aioseo()->tags->all( true ),
485
- 'nonce' => wp_create_nonce( 'wp_rest' ),
486
- 'urls' => [
487
- 'domain' => $this->getSiteDomain(),
488
- 'mainSiteUrl' => $this->getSiteUrl(),
489
- 'home' => home_url(),
490
- 'restUrl' => rest_url(),
491
- 'publicPath' => plugin_dir_url( AIOSEO_FILE ),
492
- 'rssFeedUrl' => get_bloginfo( 'rss2_url' ),
493
- 'generalSitemapUrl' => home_url( "/$sitemapFilename.xml" ),
494
- 'rssSitemapUrl' => home_url( '/sitemap.rss' ),
495
- 'robotsTxtUrl' => $this->getSiteUrl() . '/robots.txt',
496
- 'blockedBotsLogUrl' => wp_upload_dir()['baseurl'] . '/aioseo/logs/aioseo-bad-bot-blocker.log',
497
- 'upgradeUrl' => apply_filters( 'aioseo_upgrade_link', AIOSEO_MARKETING_URL ),
498
- 'staticHomePage' => 'page' === get_option( 'show_on_front' ) ? get_edit_post_link( get_option( 'page_on_front' ), 'url' ) : null,
499
- 'connect' => add_query_arg( [
500
- 'siteurl' => site_url(),
501
- 'homeurl' => home_url(),
502
- 'redirect' => rawurldecode( base64_encode( admin_url( 'index.php?page=aioseo-connect' ) ) )
503
- ], defined( 'AIOSEO_CONNECT_URL' ) ? AIOSEO_CONNECT_URL : 'https://connect.aioseo.com' ),
504
- 'aio' => [
505
- 'wizard' => admin_url( 'index.php?page=aioseo-setup-wizard' ),
506
- 'dashboard' => admin_url( 'admin.php?page=aioseo' ),
507
- 'settings' => admin_url( 'admin.php?page=aioseo-settings' ),
508
- 'localSeo' => admin_url( 'admin.php?page=aioseo-local-seo' ),
509
- 'featureManager' => admin_url( 'admin.php?page=aioseo-feature-manager' ),
510
- 'sitemaps' => admin_url( 'admin.php?page=aioseo-sitemaps' ),
511
- 'seoAnalysis' => admin_url( 'admin.php?page=aioseo-seo-analysis' ),
512
- 'searchAppearance' => admin_url( 'admin.php?page=aioseo-search-appearance' ),
513
- 'socialNetworks' => admin_url( 'admin.php?page=aioseo-social-networks' ),
514
- 'tools' => admin_url( 'admin.php?page=aioseo-tools' ),
515
- 'monsterinsights' => admin_url( 'admin.php?page=aioseo-monsterinsights' )
516
- ],
517
- 'admin' => [
518
- 'widgets' => admin_url( 'widgets.php' ),
519
- 'optionsReading' => admin_url( 'options-reading.php' ),
520
- 'scheduledActions' => admin_url( '/tools.php?page=action-scheduler&status=pending&s=aioseo' ),
521
- 'generalSettings' => admin_url( 'options-general.php' )
522
- ]
523
- ],
524
- 'backups' => [],
525
- 'importers' => [],
526
- 'data' => [
527
- 'server' => [
528
- 'apache' => null,
529
- 'nginx' => null
530
- ],
531
- 'robots' => [
532
- 'defaultRules' => [],
533
- 'hasPhysicalRobots' => null,
534
- 'rewriteExists' => null,
535
- 'sitemapUrls' => []
536
- ],
537
- 'logSizes' => [
538
- 'badBotBlockerLog' => null
539
- ],
540
- 'status' => [],
541
- 'htaccess' => '',
542
- 'multisite' => is_multisite(),
543
- 'network' => is_network_admin(),
544
- 'mainSite' => is_main_site(),
545
- 'subdomain' => defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL,
546
- 'isWooCommerceActive' => $this->isWooCommerceActive(),
547
- 'isBBPressActive' => class_exists( 'bbPress' ),
548
- 'staticHomePage' => $isStaticHomePage ? $staticHomePage : false,
549
- 'staticBlogPage' => $this->getBlogPageId(),
550
- 'staticBlogPageTitle' => get_the_title( $this->getBlogPageId() ),
551
- 'isDev' => $this->isDev()
552
- ],
553
- 'user' => [
554
- 'email' => wp_get_current_user()->user_email,
555
- 'roles' => $this->getUserRoles(),
556
- 'capabilities' => aioseo()->access->getAllCapabilities(),
557
- 'unfilteredHtml' => current_user_can( 'unfiltered_html' ),
558
- 'locale' => function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale()
559
- ],
560
- 'plugins' => $this->getPluginData(),
561
- 'postData' => [
562
- 'postTypes' => $this->getPublicPostTypes( false, false, true ),
563
- 'taxonomies' => $this->getPublicTaxonomies( false, true ),
564
- 'archives' => $this->getPublicPostTypes( false, true, true )
565
- ],
566
- 'notifications' => [
567
- 'active' => Models\Notification::getAllActiveNotifications(),
568
- 'dismissed' => Models\Notification::getAllDismissedNotifications()
569
- ],
570
- 'addons' => aioseo()->addons->getAddons(),
571
- 'version' => AIOSEO_VERSION,
572
- 'helpPanel' => json_decode( aioseo()->help->getDocs() ),
573
- 'scheduledActions' => [
574
- 'sitemaps' => []
575
- ]
576
- ];
577
-
578
- if ( is_multisite() && ! is_network_admin() ) {
579
- switch_to_blog( $this->getNetworkId() );
580
- $options = aioseo()->options->noConflict();
581
- $options->initNetwork();
582
- $data['networkOptions'] = $options->all();
583
- restore_current_blog();
584
- }
585
-
586
- if ( 'post' === $page ) {
587
- $postId = get_the_ID();
588
- $post = Models\Post::getPost( $postId );
589
-
590
- $data['currentPost'] = [
591
- 'context' => 'post',
592
- 'tags' => aioseo()->tags->getDefaultPostTags( $postId ),
593
- 'id' => $postId,
594
- 'priority' => ! empty( $post->priority ) ? $post->priority : 'default',
595
- 'frequency' => ! empty( $post->frequency ) ? $post->frequency : 'default',
596
- 'permalink' => get_the_permalink(),
597
- 'title' => ! empty( $post->title ) ? $post->title : aioseo()->meta->title->getPostTypeTitle( $postTypeObj->name ),
598
- 'description' => ! empty( $post->description ) ? $post->description : aioseo()->meta->description->getPostTypeDescription( $postTypeObj->name ),
599
- 'keywords' => ! empty( $post->keywords ) ? $post->keywords : wp_json_encode( [] ),
600
- 'keyphrases' => ! empty( $post->keyphrases )
601
- ? json_decode( $post->keyphrases )
602
- : json_decode( '{"focus":{},"additional":[]}' ),
603
- 'page_analysis' => ! empty( $post->page_analysis )
604
- ? json_decode( $post->page_analysis )
605
- : Models\Post::getPageAnalysisDefaults(),
606
- 'loading' => [
607
- 'focus' => false,
608
- 'additional' => [],
609
- ],
610
- 'type' => $postTypeObj->labels->singular_name,
611
- 'postType' => 'type' === $postTypeObj->name ? '_aioseo_type' : $postTypeObj->name,
612
- 'isSpecialPage' => $this->isSpecialPage( $postId ),
613
- 'isWooCommercePage' => $this->isWooCommercePage( $postId ),
614
- 'seo_score' => (int) $post->seo_score,
615
- 'pillar_content' => ( (int) $post->pillar_content ) === 0 ? false : true,
616
- 'canonicalUrl' => $post->canonical_url,
617
- 'default' => ( (int) $post->robots_default ) === 0 ? false : true,
618
- 'noindex' => ( (int) $post->robots_noindex ) === 0 ? false : true,
619
- 'noarchive' => ( (int) $post->robots_noarchive ) === 0 ? false : true,
620
- 'nosnippet' => ( (int) $post->robots_nosnippet ) === 0 ? false : true,
621
- 'nofollow' => ( (int) $post->robots_nofollow ) === 0 ? false : true,
622
- 'noimageindex' => ( (int) $post->robots_noimageindex ) === 0 ? false : true,
623
- 'noodp' => ( (int) $post->robots_noodp ) === 0 ? false : true,
624
- 'notranslate' => ( (int) $post->robots_notranslate ) === 0 ? false : true,
625
- 'maxSnippet' => null === $post->robots_max_snippet ? -1 : (int) $post->robots_max_snippet,
626
- 'maxVideoPreview' => null === $post->robots_max_videopreview ? -1 : (int) $post->robots_max_videopreview,
627
- 'maxImagePreview' => $post->robots_max_imagepreview,
628
- 'modalOpen' => false,
629
- 'tabs' => ( ! empty( $post->tabs ) )
630
- ? json_decode( $post->tabs )
631
- : json_decode( Models\Post::getDefaultTabsOptions() ),
632
- 'generalMobilePrev' => false,
633
- 'socialMobilePreview' => false,
634
- 'og_object_type' => ! empty( $post->og_object_type ) ? $post->og_object_type : 'default',
635
- 'og_title' => $post->og_title,
636
- 'og_description' => $post->og_description,
637
- 'og_image_custom_url' => $post->og_image_custom_url,
638
- 'og_image_custom_fields' => $post->og_image_custom_fields,
639
- 'og_image_type' => ! empty( $post->og_image_type ) ? $post->og_image_type : 'default',
640
- 'og_video' => ! empty( $post->og_video ) ? $post->og_video : '',
641
- 'og_article_section' => ! empty( $post->og_article_section ) ? $post->og_article_section : '',
642
- 'og_article_tags' => ! empty( $post->og_article_tags ) ? $post->og_article_tags : wp_json_encode( [] ),
643
- 'twitter_use_og' => ( (int) $post->twitter_use_og ) === 0 ? false : true,
644
- 'twitter_card' => $post->twitter_card,
645
- 'twitter_image_custom_url' => $post->twitter_image_custom_url,
646
- 'twitter_image_custom_fields' => $post->twitter_image_custom_fields,
647
- 'twitter_image_type' => $post->twitter_image_type,
648
- 'twitter_title' => $post->twitter_title,
649
- 'twitter_description' => $post->twitter_description,
650
- 'schema_type' => ( ! empty( $post->schema_type ) ) ? $post->schema_type : 'default',
651
- 'schema_type_options' => ( ! empty( $post->schema_type_options ) )
652
- ? json_decode( Models\Post::getDefaultSchemaOptions( $post->schema_type_options ) )
653
- : json_decode( Models\Post::getDefaultSchemaOptions() ),
654
- 'local_seo' => ( ! empty( $post->local_seo ) )
655
- ? Models\Post::getDefaultLocalSeoOptions( $post->local_seo )
656
- : json_decode( Models\Post::getDefaultLocalSeoOptions() ),
657
- 'metaDefaults' => [
658
- 'title' => aioseo()->meta->title->getPostTypeTitle( $postTypeObj->name ),
659
- 'description' => aioseo()->meta->description->getPostTypeDescription( $postTypeObj->name )
660
- ]
661
- ];
662
-
663
- if ( ! $post->exists() ) {
664
- $oldPostMeta = aioseo()->migration->meta->getMigratedPostMeta( $postId );
665
- foreach ( $oldPostMeta as $k => $v ) {
666
- if ( preg_match( '#robots_.*#', $k ) ) {
667
- $oldPostMeta[ preg_replace( '#robots_#', '', $k ) ] = $v;
668
- continue;
669
- }
670
- if ( 'canonical_url' === $k ) {
671
- $oldPostMeta['canonicalUrl'] = $v;
672
- }
673
- }
674
- $data['currentPost'] = array_merge( $data['currentPost'], $oldPostMeta );
675
- }
676
- }
677
-
678
- // @TODO: Contextualize all data attributes above to only show on pages that they are used on.
679
-
680
- if ( 'sitemaps' === $page ) {
681
- try {
682
- if ( as_next_scheduled_action( 'aioseo_static_sitemap_regeneration' ) ) {
683
- $data['scheduledActions']['sitemap'][] = 'staticSitemapRegeneration';
684
- }
685
- } catch ( \Exception $e ) {
686
- // Do nothing.
687
- }
688
- }
689
-
690
- if ( 'setup-wizard' === $page ) {
691
- $data['users'] = $this->getSiteUsers( [ 'administrator', 'editor', 'author' ] );
692
- $data['importers'] = aioseo()->importExport->plugins();
693
- }
694
-
695
- if ( 'search-appearance' === $page ) {
696
- $data['users'] = $this->getSiteUsers( [ 'administrator', 'editor', 'author' ] );
697
- $data['data'] += [
698
- 'staticHomePageTitle' => $isStaticHomePage ? aioseo()->meta->title->getTitle( $staticHomePage ) : '',
699
- 'staticHomePageDescription' => $isStaticHomePage ? aioseo()->meta->description->getDescription( $staticHomePage ) : '',
700
- ];
701
- }
702
-
703
- if ( 'social-networks' === $page ) {
704
- $data['data'] += [
705
- 'staticHomePageOgTitle' => $isStaticHomePage ? aioseo()->social->facebook->getTitle( $staticHomePage ) : '',
706
- 'staticHomePageOgDescription' => $isStaticHomePage ? aioseo()->social->facebook->getDescription( $staticHomePage ) : '',
707
- 'staticHomePageTwitterTitle' => $isStaticHomePage ? aioseo()->social->twitter->getTitle( $staticHomePage ) : '',
708
- 'staticHomePageTwitterDescription' => $isStaticHomePage ? aioseo()->social->twitter->getDescription( $staticHomePage ) : '',
709
- ];
710
- }
711
-
712
- if ( 'tools' === $page ) {
713
- $data['backups'] = array_reverse( aioseo()->backup->all() );
714
- $data['importers'] = aioseo()->importExport->plugins();
715
- $data['data']['server'] = [
716
- 'apache' => $this->isApache(),
717
- 'nginx' => $this->isNginx()
718
- ];
719
- $data['data']['robots'] = [
720
- 'defaultRules' => $page ? aioseo()->robotsTxt->getDefaultRules() : [],
721
- 'hasPhysicalRobots' => aioseo()->robotsTxt->hasPhysicalRobotsTxt(),
722
- 'rewriteExists' => aioseo()->robotsTxt->rewriteRulesExist(),
723
- 'sitemapUrls' => array_merge( aioseo()->sitemap->helpers->getSitemapUrls(), $this->extractSitemapUrlsFromRobotsTxt() )
724
- ];
725
- $data['data']['logSizes'] = [
726
- 'badBotBlockerLog' => $this->convertFileSize( aioseo()->badBotBlocker->getLogSize() )
727
- ];
728
- $data['data']['status'] = Tools\SystemStatus::getSystemStatusInfo();
729
- $data['data']['htaccess'] = aioseo()->htaccess->getContents();
730
- }
731
-
732
- if ( 'settings' === $page ) {
733
- $data['breadcrumbs']['defaultTemplate'] = aioseo()->helpers->encodeOutputHtml( aioseo()->breadcrumbs->frontend->getDefaultTemplate() );
734
- }
735
-
736
- $loadedAddons = aioseo()->addons->getLoadedAddons();
737
- if ( ! empty( $loadedAddons ) ) {
738
- foreach ( $loadedAddons as $addon ) {
739
- if ( isset( $addon->helpers ) && method_exists( $addon->helpers, 'getVueData' ) ) {
740
- $data = $addon->helpers->getVueData( $data, $page );
741
- }
742
- }
743
- }
744
-
745
- return $data;
746
- }
747
-
748
- /**
749
- * Returns user roles in the current WP install.
750
- *
751
- * @since 4.0.0
752
- *
753
- * @return array An array of user roles.
754
- */
755
- public function getUserRoles() {
756
- global $wp_roles;
757
- if ( ! isset( $wp_roles ) ) {
758
- $wp_roles = new WP_Roles();
759
- }
760
- $roleNames = $wp_roles->get_names();
761
- asort( $roleNames );
762
-
763
- return $roleNames;
764
- }
765
-
766
- /**
767
- * Returns an array of plugins with the active status.
768
- *
769
- * @since 4.0.0
770
- *
771
- * @return array An array of plugins with active status.
772
- */
773
- public function getPluginData() {
774
- $pluginUpgrader = new PluginUpgraderSilentAjax();
775
- $installedPlugins = array_keys( get_plugins() );
776
-
777
- $plugins = [];
778
- foreach ( $pluginUpgrader->pluginSlugs as $key => $slug ) {
779
- $plugins[ $key ] = [
780
- 'basename' => $slug,
781
- 'installed' => in_array( $slug, $installedPlugins, true ),
782
- 'activated' => is_plugin_active( $slug ),
783
- 'adminUrl' => admin_url( $pluginUpgrader->pluginAdminUrls[ $key ] ),
784
- 'canInstall' => aioseo()->addons->canInstall(),
785
- 'wpLink' => ! empty( $pluginUpgrader->wpPluginLinks[ $key ] ) ? $pluginUpgrader->wpPluginLinks[ $key ] : null
786
- ];
787
- }
788
-
789
- return $plugins;
790
- }
791
-
792
- /**
793
- * Retrieve a list of public post types with slugs/icons.
794
- *
795
- * @since 4.0.0
796
- *
797
- * @param boolean $namesOnly Whether only the names should be returned.
798
- * @param boolean $hasArchivesOnly Whether or not to only include post types which have archives.
799
- * @param boolean $rewriteType Whether or not to rewrite the type slugs.
800
- * @return array An array of public post types.
801
- */
802
- public function getPublicPostTypes( $namesOnly = false, $hasArchivesOnly = false, $rewriteType = false ) {
803
- $postTypes = [];
804
- $postObjects = get_post_types( [ 'public' => true ], 'objects' );
805
- $woocommerce = class_exists( 'woocommerce' );
806
- foreach ( $postObjects as $postObject ) {
807
- if ( empty( $postObject->label ) ) {
808
- continue;
809
- }
810
-
811
- // We don't want to include archives for the WooCommerce shop page.
812
- if (
813
- $hasArchivesOnly &&
814
- (
815
- ! $postObject->has_archive ||
816
- ( 'product' === $postObject->name && $woocommerce )
817
- )
818
- ) {
819
- continue;
820
- }
821
-
822
- if ( $namesOnly ) {
823
- $postTypes[] = $postObject->name;
824
- continue;
825
- }
826
-
827
- if ( 'attachment' === $postObject->name ) {
828
- $postObject->label = __( 'Attachments', 'all-in-one-seo-pack' );
829
- }
830
-
831
- if ( 'product' === $postObject->name && $woocommerce ) {
832
- $postObject->menu_icon = 'dashicons-products';
833
- }
834
-
835
- $name = $postObject->name;
836
- if ( 'type' === $postObject->name && $rewriteType ) {
837
- $name = '_aioseo_type';
838
- }
839
-
840
- $postTypes[] = [
841
- 'name' => $name,
842
- 'label' => ucwords( $postObject->label ),
843
- 'singular' => ucwords( $postObject->labels->singular_name ),
844
- 'icon' => $postObject->menu_icon,
845
- 'hasExcerpt' => post_type_supports( $postObject->name, 'excerpt' ),
846
- 'hasArchive' => $postObject->has_archive,
847
- 'hierarchical' => $postObject->hierarchical,
848
- 'taxonomies' => get_object_taxonomies( $name ),
849
- 'slug' => isset( $postObject->rewrite['slug'] ) ? $postObject->rewrite['slug'] : $name
850
- ];
851
- }
852
-
853
- return $postTypes;
854
- }
855
-
856
- /**
857
- * Retrieve a list of public taxonomies with slugs/icons.
858
- *
859
- * @since 4.0.0
860
- *
861
- * @param boolean $namesOnly Whether only the names should be returned.
862
- * @param boolean $rewriteType Whether or not to rewrite the type slugs.
863
- * @return array An array of public taxonomies.
864
- */
865
- public function getPublicTaxonomies( $namesOnly = false, $rewriteType = false ) {
866
- $taxonomies = [];
867
- if ( count( $taxonomies ) ) {
868
- return $taxonomies;
869
- }
870
-
871
- $taxObjects = get_taxonomies( [ 'public' => true ], 'objects' );
872
- foreach ( $taxObjects as $taxObject ) {
873
- if ( empty( $taxObject->label ) ) {
874
- continue;
875
- }
876
-
877
- if ( in_array( $taxObject->name, [
878
- 'product_shipping_class',
879
- 'post_format'
880
- ], true ) ) {
881
- continue;
882
- }
883
-
884
- // We need to exclude product attributes from this list as well.
885
- if (
886
- 'pa_' === substr( $taxObject->name, 0, 3 ) &&
887
- 'manage_product_terms' === $taxObject->cap->manage_terms &&
888
- ! apply_filters( 'aioseo_woocommerce_product_attributes', false )
889
- ) {
890
- continue;
891
- }
892
-
893
- if ( $namesOnly ) {
894
- $taxonomies[] = $taxObject->name;
895
- continue;
896
- }
897
-
898
- $name = $taxObject->name;
899
- if ( 'type' === $taxObject->name && $rewriteType ) {
900
- $name = '_aioseo_type';
901
- }
902
-
903
- $taxonomies[] = [
904
- 'name' => $name,
905
- 'label' => ucwords( $taxObject->label ),
906
- 'singular' => ucwords( $taxObject->labels->singular_name ),
907
- 'icon' => strpos( $taxObject->label, 'categor' ) !== false ? 'dashicons-category' : 'dashicons-tag',
908
- 'hierarchical' => $taxObject->hierarchical,
909
- 'slug' => isset( $taxObject->rewrite['slug'] ) ? $taxObject->rewrite['slug'] : ''
910
- ];
911
- }
912
-
913
- return $taxonomies;
914
- }
915
-
916
- /**
917
- * Returns noindexed post types.
918
- *
919
- * @since 4.0.0
920
- *
921
- * @return array A list of noindexed post types.
922
- */
923
- public function getNoindexedPostTypes() {
924
- return $this->getNoindexedObjects( 'postTypes' );
925
- }
926
-
927
- /**
928
- * Checks whether a given post type is noindexed.
929
- *
930
- * @since 4.0.0
931
- *
932
- * @param string $postType The post type.
933
- * @return bool Whether the post type is noindexed.
934
- */
935
- public function isPostTypeNoindexed( $postType ) {
936
- $noindexedPostTypes = $this->getNoindexedPostTypes();
937
- return in_array( $postType, $noindexedPostTypes, true );
938
- }
939
-
940
- /**
941
- * Returns noindexed taxonomies.
942
- *
943
- * @since 4.0.0
944
- *
945
- * @return array A list of noindexed taxonomies.
946
- */
947
- public function getNoindexedTaxonomies() {
948
- return $this->getNoindexedObjects( 'taxonomies' );
949
- }
950
-
951
- /**
952
- * Checks whether a given post type is noindexed.
953
- *
954
- * @since 4.0.0
955
- *
956
- * @param string $taxonomy The taxonomy.
957
- * @return bool Whether the taxonomy is noindexed.
958
- */
959
- public function isTaxonomyNoindexed( $taxonomy ) {
960
- $noindexedTaxonomies = $this->getNoindexedTaxonomies();
961
- return in_array( $taxonomy, $noindexedTaxonomies, true );
962
- }
963
-
964
- /**
965
- * Returns noindexed object types of a given parent type.
966
- *
967
- * @since 4.0.0
968
- *
969
- * @param string $type The parent object type ("postTypes" or "taxonomies").
970
- * @return array A list of noindexed objects types.
971
- */
972
- private function getNoindexedObjects( $type ) {
973
- $noindexed = [];
974
- foreach ( aioseo()->options->searchAppearance->dynamic->$type->all() as $name => $object ) {
975
- if (
976
- ! $object['show'] ||
977
- ( $object['advanced']['robotsMeta'] && ! $object['advanced']['robotsMeta']['default'] && $object['advanced']['robotsMeta']['noindex'] )
978
- ) {
979
- $noindexed[] = $name;
980
- }
981
- }
982
- return $noindexed;
983
- }
984
-
985
- /**
986
- * Retrieve a list of users that match passed in roles.
987
- *
988
- * @since 4.0.0
989
- *
990
- * @return array An array of user data.
991
- */
992
- public function getSiteUsers( $roles ) {
993
- static $users = [];
994
-
995
- if ( ! empty( $users ) ) {
996
- return $users;
997
- }
998
-
999
- $rolesWhere = [];
1000
- foreach ( $roles as $role ) {
1001
- $rolesWhere[] = '(um.meta_key = \'' . aioseo()->db->db->prefix . 'capabilities\' AND um.meta_value LIKE \'%\"' . $role . '\"%\')';
1002
- }
1003
- $dbUsers = aioseo()->db->start( 'users as u' )
1004
- ->select( 'u.ID, u.display_name, u.user_nicename, u.user_email' )
1005
- ->join( 'usermeta as um', 'u.ID = um.user_id' )
1006
- ->whereRaw( '(' . implode( ' OR ', $rolesWhere ) . ')' )
1007
- ->orderBy( 'u.user_nicename' )
1008
- ->run()
1009
- ->result();
1010
-
1011
- foreach ( $dbUsers as $dbUser ) {
1012
- $users[] = [
1013
- 'id' => intval( $dbUser->ID ),
1014
- 'displayName' => $dbUser->display_name,
1015
- 'niceName' => $dbUser->user_nicename,
1016
- 'email' => $dbUser->user_email,
1017
- 'gravatar' => get_avatar_url( $dbUser->user_email )
1018
- ];
1019
- }
1020
-
1021
- return $users;
1022
- }
1023
-
1024
- /**
1025
- * Strips punctuation from a given string.
1026
- *
1027
- * @since 4.0.0
1028
- *
1029
- * @param string $string The string.
1030
- * @return string The string without punctuation.
1031
- */
1032
- public function stripPunctuation( $string ) {
1033
- $string = preg_replace( '#\p{P}#u', '', $string );
1034
- // Trim both internal and external whitespace.
1035
- return preg_replace( '/\s\s+/u', ' ', trim( $string ) );
1036
- }
1037
-
1038
- /*
1039
- * Sanitize Domain
1040
- *
1041
- * @since 4.0.0
1042
- *
1043
- * @param string $domain The domain to sanitize.
1044
- * @return mixed|string The sanitized domain.
1045
- */
1046
- public function sanitizeDomain( $domain ) {
1047
- $domain = trim( $domain );
1048
- $domain = strtolower( $domain );
1049
- if ( 0 === strpos( $domain, 'http://' ) ) {
1050
- $domain = substr( $domain, 7 );
1051
- } elseif ( 0 === strpos( $domain, 'https://' ) ) {
1052
- $domain = substr( $domain, 8 );
1053
- }
1054
- $domain = untrailingslashit( $domain );
1055
-
1056
- return $domain;
1057
- }
1058
-
1059
- /**
1060
- * Get's the site domain.
1061
- *
1062
- * @since 4.0.0
1063
- *
1064
- * @return string The site's domain.
1065
- */
1066
- public function getSiteDomain() {
1067
- return wp_parse_url( home_url(), PHP_URL_HOST );
1068
- }
1069
-
1070
- /**
1071
- * Get's the site URL.
1072
- * NOTE: For multisites inside a sub-directory, this returns the URL for the main site.
1073
- * This is intentional.
1074
- *
1075
- * @since 4.0.0
1076
- *
1077
- * @return string The site's domain.
1078
- */
1079
- public function getSiteUrl() {
1080
- return wp_parse_url( home_url(), PHP_URL_SCHEME ) . '://' . wp_parse_url( home_url(), PHP_URL_HOST );
1081
- }
1082
-
1083
- /**
1084
- * Returns the current URL.
1085
- *
1086
- * @since 4.0.0
1087
- *
1088
- * @param boolean $canonical Whether or not to get the canonical URL.
1089
- * @return string The URL.
1090
- */
1091
- public function getUrl( $canonical = false ) {
1092
- if ( is_singular() ) {
1093
- $object = get_queried_object_id();
1094
- return $canonical ? wp_get_canonical_url( $object ) : get_permalink( $object );
1095
- }
1096
-
1097
- global $wp;
1098
- return trailingslashit( home_url( $wp->request ) );
1099
- }
1100
-
1101
- /**
1102
- * Gets the canonical URL for the current page/post.
1103
- *
1104
- * @since 4.0.0
1105
- *
1106
- * @return string $url The canonical URL.
1107
- */
1108
- public function canonicalUrl() {
1109
- static $canonicalUrl = '';
1110
- if ( $canonicalUrl ) {
1111
- return $canonicalUrl;
1112
- }
1113
-
1114
- $metaData = [];
1115
- $post = $this->getPost();
1116
- if ( $post ) {
1117
- $metaData = aioseo()->meta->metaData->getMetaData( $post );
1118
- }
1119
-
1120
- if ( is_category() || is_tag() || is_tax() ) {
1121
- $metaData = aioseo()->meta->metaData->getMetaData( get_queried_object() );
1122
- }
1123
-
1124
- if ( $metaData && ! empty( $metaData->canonical_url ) ) {
1125
- return $metaData->canonical_url;
1126
- }
1127
-
1128
- $url = $this->getUrl( true );
1129
- if ( aioseo()->options->searchAppearance->advanced->noPaginationForCanonical && 1 < $this->getPageNumber() ) {
1130
- $url = preg_replace( '#(\d+\/|(?<=\/)page\/\d+\/)$#', '', $url );
1131
- }
1132
-
1133
- $url = $this->maybeRemoveTrailingSlash( $url );
1134
-
1135
- // Get rid of /amp at the end of the URL.
1136
- if ( ! apply_filters( 'aioseo_disable_canonical_url_amp', false ) ) {
1137
- $url = preg_replace( '/\/amp$/', '', $url );
1138
- $url = preg_replace( '/\/amp\/$/', '/', $url );
1139
- }
1140
-
1141
- $searchTerm = get_query_var( 's' );
1142
- if ( is_search() && ! empty( $searchTerm ) ) {
1143
- $url = add_query_arg( 's', $searchTerm, $url );
1144
- }
1145
-
1146
- return apply_filters( 'aioseo_canonical_url', $url );
1147
- }
1148
-
1149
- /**
1150
- * Remove trailing slashes if not set in the permalink structure.
1151
- *
1152
- * @since 4.0.0
1153
- *
1154
- * @param string $url The original URL.
1155
- * @return string The adjusted URL.
1156
- */
1157
- public function maybeRemoveTrailingSlash( $url ) {
1158
- $permalinks = get_option( 'permalink_structure' );
1159
- if ( $permalinks && ( ! is_home() || ! is_front_page() ) ) {
1160
- $trailing = substr( $permalinks, -1 );
1161
- if ( '/' !== $trailing ) {
1162
- $url = untrailingslashit( $url );
1163
- }
1164
- }
1165
-
1166
- // Don't slash urls with query args.
1167
- if ( false !== strpos( $url, '?' ) ) {
1168
- $url = untrailingslashit( $url );
1169
- }
1170
-
1171
- return $url;
1172
- }
1173
-
1174
- /**
1175
- * Returns the page number of the current page.
1176
- *
1177
- * @since 4.0.0
1178
- *
1179
- * @return int The page number.
1180
- */
1181
- public function getPageNumber() {
1182
- $page = get_query_var( 'page' );
1183
- $paged = get_query_var( 'paged' );
1184
- return ! empty( $page )
1185
- ? $page
1186
- : (
1187
- ! empty( $paged )
1188
- ? $paged
1189
- : 1
1190
- );
1191
- }
1192
-
1193
- /**
1194
- * Request the remote URL via wp_remote_post and return a json decoded response.
1195
- *
1196
- * @since 4.0.0
1197
- *
1198
- * @param array $body The content to retrieve from the remote URL.
1199
- * @param array $headers The headers to send to the remote URL.
1200
- *
1201
- * @return string|bool Json decoded response on success, false on failure.
1202
- */
1203
- public function sendRequest( $url, $body = [], $headers = [] ) {
1204
- $body = wp_json_encode( $body );
1205
-
1206
- // Build the headers of the request.
1207
- $headers = wp_parse_args(
1208
- $headers,
1209
- [
1210
- 'Content-Type' => 'application/json'
1211
- ]
1212
- );
1213
-
1214
- // Setup variable for wp_remote_post.
1215
- $post = [
1216
- 'headers' => $headers,
1217
- 'body' => $body,
1218
- 'sslverify' => $this->isDev() ? false : true,
1219
- 'timeout' => 20
1220
- ];
1221
-
1222
- // Perform the query and retrieve the response.
1223
- $response = wp_remote_post( $url, $post );
1224
- $responseBody = wp_remote_retrieve_body( $response );
1225
-
1226
- // Bail out early if there are any errors.
1227
- if ( is_wp_error( $responseBody ) ) {
1228
- return false;
1229
- }
1230
-
1231
- // Return the json decoded content.
1232
- return json_decode( $responseBody );
1233
- }
1234
-
1235
- /**
1236
- * Get the class name for the Score button.
1237
- * Depending on the score the button should have different color.
1238
- *
1239
- * @since 4.0.0
1240
- *
1241
- * @param int $score The content to retrieve from the remote URL.
1242
- *
1243
- * @return string The class name for Score button.
1244
- */
1245
- public function getScoreClass( $score ) {
1246
- $scoreClass = 50 < $score ? 'score-orange' : 'score-red';
1247
- if ( 0 === $score ) {
1248
- $scoreClass = 'score-none';
1249
- }
1250
- if ( $score >= 80 ) {
1251
- $scoreClass = 'score-green';
1252
- }
1253
- return $scoreClass;
1254
- }
1255
-
1256
- /**
1257
- * Returns the ID of the site logo if it exists.
1258
- *
1259
- * @since 4.0.0
1260
- *
1261
- * @return int
1262
- */
1263
- public function getSiteLogoId() {
1264
- if ( ! get_theme_support( 'custom-logo' ) ) {
1265
- return false;
1266
- }
1267
- return get_theme_mod( 'custom_logo' );
1268
- }
1269
-
1270
- /**
1271
- * Returns the URL of the site logo if it exists.
1272
- *
1273
- * @since 4.0.0
1274
- *
1275
- * @return string
1276
- */
1277
- public function getSiteLogoUrl() {
1278
- $id = $this->getSiteLogoId();
1279
- if ( ! $id ) {
1280
- return false;
1281
- }
1282
-
1283
- $image = wp_get_attachment_image_src( $id, 'full' );
1284
- if ( empty( $image ) ) {
1285
- return false;
1286
- }
1287
- return $image[0];
1288
- }
1289
-
1290
- /**
1291
- * Compares two (multidimensional) arrays to see if they're different.
1292
- *
1293
- * @since 4.0.0
1294
- *
1295
- * @param array $array1 The first array.
1296
- * @param array $array2 The second array.
1297
- * @return boolean Whether the arrays are different.
1298
- */
1299
- public function arraysDifferent( $array1, $array2 ) {
1300
- foreach ( $array1 as $key => $value ) {
1301
- // Check for non-existing values.
1302
- if ( ! isset( $array2[ $key ] ) ) {
1303
- return true;
1304
- }
1305
- if ( is_array( $value ) ) {
1306
- if ( $this->arraysDifferent( $value, $array2[ $key ] ) ) {
1307
- return true;
1308
- };
1309
- } else {
1310
- if ( $value !== $array2[ $key ] ) {
1311
- return true;
1312
- }
1313
- }
1314
- }
1315
- return false;
1316
- }
1317
-
1318
- /**
1319
- * Returns the filesystem object if we have access to it.
1320
- *
1321
- * @since 4.0.0
1322
- *
1323
- * @param array $args The connection args.
1324
- * @return WP_Filesystem The filesystem object.
1325
- */
1326
- public function wpfs( $args = [] ) {
1327
- require_once( ABSPATH . 'wp-admin/includes/file.php' );
1328
- WP_Filesystem( $args );
1329
-
1330
- global $wp_filesystem;
1331
- if ( is_object( $wp_filesystem ) ) {
1332
- return $wp_filesystem;
1333
- }
1334
- return false;
1335
- }
1336
-
1337
- /**
1338
- * Internationalize.
1339
- *
1340
- * @since 4.0.0
1341
- *
1342
- * @param $in
1343
- * @return mixed|void
1344
- */
1345
- public function internationalize( $in ) {
1346
- if ( function_exists( 'langswitch_filter_langs_with_message' ) ) {
1347
- $in = langswitch_filter_langs_with_message( $in );
1348
- }
1349
-
1350
- if ( function_exists( 'polyglot_filter' ) ) {
1351
- $in = polyglot_filter( $in );
1352
- }
1353
-
1354
- if ( function_exists( 'qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) ) {
1355
- $in = qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage( $in );
1356
- } elseif ( function_exists( 'ppqtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) ) {
1357
- $in = ppqtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage( $in );
1358
- } elseif ( function_exists( 'qtranxf_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) ) {
1359
- $in = qtranxf_useCurrentLanguageIfNotFoundUseDefaultLanguage( $in );
1360
- }
1361
-
1362
- return apply_filters( 'localization', $in );
1363
- }
1364
-
1365
- /**
1366
- * Truncates a given string.
1367
- *
1368
- * @since 4.0.0
1369
- *
1370
- * @param string $string The string.
1371
- * @param int $maxCharacters The max. amount of characters.
1372
- * @param boolean $shouldHaveEllipsis Whether the string should have a trailing ellipsis (defaults to true).
1373
- * @return string $string The string.
1374
- */
1375
- public function truncate( $string, $maxCharacters, $shouldHaveEllipsis = true ) {
1376
- $length = strlen( $string );
1377
- $excessLength = $length - $maxCharacters;
1378
- if ( 0 < $excessLength ) {
1379
- // If the string is longer than 65535 characters, we first need to shorten it due to the character limit of the regex pattern quantifier.
1380
- if ( 65535 < $length ) {
1381
- $string = substr( $string, 0, 65534 );
1382
- }
1383
- $string = preg_replace( "#[^\pZ\pP]*.{{$excessLength}}$#", '', $string );
1384
- if ( $shouldHaveEllipsis ) {
1385
- $string = $string . ' ...';
1386
- }
1387
- }
1388
- return $string;
1389
- }
1390
-
1391
- /**
1392
- * Removes image dimensions from the slug of a URL.
1393
- *
1394
- * @since 4.0.0
1395
- *
1396
- * @param string $url The image URL.
1397
- * @return string The formatted image URL.
1398
- */
1399
- public function removeImageDimensions( $url ) {
1400
- return $this->isValidAttachment( $url ) ? preg_replace( '#(-[0-9]*x[0-9]*)#', '', $url ) : $url;
1401
- }
1402
-
1403
- /**
1404
- * Returns the URLs of the pages that WooCommerce noindexes on its own.
1405
- *
1406
- * @since 4.0.0
1407
- *
1408
- * @return array The URLs of the noindexed pages.
1409
- */
1410
- public function getNoindexedWooCommercePages() {
1411
- if ( ! $this->isWooCommerceActive() ) {
1412
- return [];
1413
- }
1414
- return [
1415
- wc_get_cart_url(),
1416
- wc_get_checkout_url(),
1417
- wc_get_page_permalink( 'myaccount' )
1418
- ];
1419
- }
1420
-
1421
- /**
1422
- * Checks if the server is running on Apache.
1423
- *
1424
- * @since 4.0.0
1425
- *
1426
- * @return boolean Whether or not it is on apache.
1427
- */
1428
- public function isApache() {
1429
- if ( ! isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
1430
- return false;
1431
- }
1432
-
1433
- return stripos( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ), 'apache' ) !== false;
1434
- }
1435
-
1436
- /**
1437
- * Checks if the server is running on nginx.
1438
- *
1439
- * @since 4.0.0
1440
- *
1441
- * @return boolean Whether or not it is on apache.
1442
- */
1443
- public function isNginx() {
1444
- if ( ! isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
1445
- return false;
1446
- }
1447
-
1448
- $server = sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) );
1449
-
1450
- if (
1451
- stripos( $server, 'Flywheel' ) !== false ||
1452
- stripos( $server, 'nginx' ) !== false
1453
- ) {
1454
- return true;
1455
- }
1456
-
1457
- return false;
1458
- }
1459
-
1460
- /**
1461
- * Get Network ID
1462
- *
1463
- * @since 4.0.0
1464
- *
1465
- * @return int The integer of the blog/site id.
1466
- */
1467
- public function getNetworkId() {
1468
- if ( is_multisite() ) {
1469
- return get_network()->site_id;
1470
- }
1471
- return get_current_blog_id();
1472
- }
1473
-
1474
- /**
1475
- * Validate IP addresses.
1476
- *
1477
- * @since 4.0.0
1478
- *
1479
- * @param string $ip The IP address to validate.
1480
- * @return boolean If the IP address is valid or not.
1481
- */
1482
- public function validateIp( $ip ) {
1483
- if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
1484
- // Valid IPV4.
1485
- return true;
1486
- }
1487
-
1488
- if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
1489
- // Valid IPV6.
1490
- return true;
1491
- }
1492
-
1493
- // Doesn't seem to be a valid IP.
1494
- return false;
1495
- }
1496
-
1497
- /**
1498
- * Convert bytes to readable format.
1499
- *
1500
- * @since 4.0.0
1501
- *
1502
- * @param integer $bytes The size of the file.
1503
- * @return string The size as a string.
1504
- */
1505
- public function convertFileSize( $bytes ) {
1506
- if ( empty( $bytes ) ) {
1507
- return [
1508
- 'original' => 0,
1509
- 'readable' => '0 B'
1510
- ];
1511
- }
1512
- $i = floor( log( $bytes ) / log( 1024 ) );
1513
- $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ];
1514
- return [
1515
- 'original' => $bytes,
1516
- 'readable' => sprintf( '%.02F', $bytes / pow( 1024, $i ) ) * 1 . ' ' . $sizes[ $i ]
1517
- ];
1518
- }
1519
-
1520
- /**
1521
- * Get timezone offset.
1522
- * We use the code from `wp_timezone_string()`
1523
- * which became available in WP 5.3+
1524
- *
1525
- * @since 4.0.0
1526
- *
1527
- * @return string
1528
- */
1529
- public function getTimeZoneOffset() {
1530
- // The code below is basically a copy-paste from that function.
1531
- $timezoneString = get_option( 'timezone_string' );
1532
-
1533
- if ( $timezoneString ) {
1534
- return $timezoneString;
1535
- }
1536
-
1537
- $offset = (float) get_option( 'gmt_offset' );
1538
- $hours = (int) $offset;
1539
- $minutes = ( $offset - $hours );
1540
- $sign = ( $offset < 0 ) ? '-' : '+';
1541
- $absHour = abs( $hours );
1542
- $absMins = abs( $minutes * 60 );
1543
- $tzOffset = sprintf( '%s%02d:%02d', $sign, $absHour, $absMins );
1544
-
1545
- return $tzOffset;
1546
- }
1547
-
1548
- /**
1549
- * Returns the current post object.
1550
- *
1551
- * @since 4.0.0
1552
- *
1553
- * @param int $postId The post ID.
1554
- * @return WP_Post The post object.
1555
- */
1556
- public function getPost( $postId = false ) {
1557
- static $showOnFront = null;
1558
- static $pageOnFront = null;
1559
- static $pageForPosts = null;
1560
-
1561
- if ( aioseo()->helpers->isWooCommerceShopPage() ) {
1562
- return get_post( wc_get_page_id( 'shop' ) );
1563
- }
1564
-
1565
- if ( is_front_page() || is_home() ) {
1566
- $showOnFront = $showOnFront ? $showOnFront : 'page' === get_option( 'show_on_front' );
1567
- if ( $showOnFront ) {
1568
- if ( is_front_page() ) {
1569
- $pageOnFront = $pageOnFront ? $pageOnFront : (int) get_option( 'page_on_front' );
1570
- return get_post( $pageOnFront );
1571
- } elseif ( is_home() ) {
1572
- $pageForPosts = $pageForPosts ? $pageForPosts : (int) get_option( 'page_for_posts' );
1573
- return get_post( $pageForPosts );
1574
- }
1575
- }
1576
-
1577
- return get_post();
1578
- }
1579
-
1580
- if (
1581
- $this->isScreenBase( 'post' ) ||
1582
- $postId ||
1583
- is_singular()
1584
- ) {
1585
- return get_post( $postId );
1586
- }
1587
- }
1588
-
1589
- /**
1590
- * Get Queried Object.
1591
- *
1592
- * @since 4.0.0
1593
- *
1594
- * @return null|\WP_Post Current WP object queried.
1595
- */
1596
- public function getQueriedObject() {
1597
- global $wp_query, $post;
1598
-
1599
- if ( is_object( $post ) ) {
1600
- return $post;
1601
- } else {
1602
- if ( ! $wp_query ) {
1603
- return null;
1604
- }
1605
- return $wp_query->get_queried_object();
1606
- }
1607
- }
1608
-
1609
- /**
1610
- * Returns the page content.
1611
- *
1612
- * @since 4.0.0
1613
- *
1614
- * @param WP_Post|int $post The post.
1615
- * @return string The content.
1616
- */
1617
- public function getContent( $post = null ) {
1618
- $post = ( $post && is_object( $post ) ) ? $post : $post = $this->getPost( $post );
1619
-
1620
- static $content = [];
1621
- if ( isset( $content[ $post->ID ] ) ) {
1622
- return $content[ $post->ID ];
1623
- }
1624
-
1625
- if ( empty( $post->post_content ) ) {
1626
- return $post->post_content;
1627
- }
1628
-
1629
- $postContent = $post->post_content;
1630
- if (
1631
- ! in_array( 'runShortcodesInDescription', aioseo()->internalOptions->deprecatedOptions, true ) ||
1632
- aioseo()->options->deprecated->searchAppearance->advanced->runShortcodesInDescription
1633
- ) {
1634
- $postContent = $this->doShortcodes( $postContent );
1635
- }
1636
-
1637
- $postContent = wp_trim_words( $postContent, 55, apply_filters( 'excerpt_more', ' ' . '[&hellip;]' ) );
1638
- $postContent = str_replace( ']]>', ']]&gt;', $postContent );
1639
- $postContent = preg_replace( '#(<figure.*\/figure>|<img.*\/>)#', '', $postContent );
1640
- $content[ $post->ID ] = trim( wp_strip_all_tags( strip_shortcodes( $postContent ) ) );
1641
- return $content[ $post->ID ];
1642
- }
1643
-
1644
- /**
1645
- * Returns custom fields as a string.
1646
- *
1647
- * @since 4.0.6
1648
- *
1649
- * @param WP_Post|int $post The post.
1650
- * @param array $keys The post meta_keys to check for values.
1651
- * @return string The custom field content.
1652
- */
1653
- public function getCustomFieldsContent( $post = null, $keys = [] ) {
1654
- $post = ( $post && is_object( $post ) ) ? $post : $this->getPost( $post );
1655
-
1656
- $customFieldContent = '';
1657
-
1658
- $acfFields = $this->getAcfContent( $post );
1659
- $acfFieldsKeys = [];
1660
-
1661
- if ( ! empty( $acfFields ) ) {
1662
- foreach ( $acfFields as $acfField => $acfValue ) {
1663
- if ( in_array( $acfField, $keys, true ) ) {
1664
- $customFieldContent .= "{$acfValue} ";
1665
- $acfFieldsKeys[] = $acfField;
1666
- }
1667
- }
1668
- }
1669
-
1670
- foreach ( $keys as $key ) {
1671
- if ( in_array( $key, $acfFieldsKeys, true ) ) {
1672
- continue;
1673
- }
1674
-
1675
- $value = get_post_meta( $post->ID, $key, true );
1676
-
1677
- if ( $value ) {
1678
- $customFieldContent .= "{$value} ";
1679
- }
1680
- }
1681
-
1682
- return $customFieldContent;
1683
- }
1684
-
1685
- /**
1686
- * Returns acf fields as an array of meta keys and values.
1687
- *
1688
- * @since 4.0.6
1689
- *
1690
- * @param WP_Post|int $post The post.
1691
- * @param array $allowedTypes A whitelist of ACF field types.
1692
- * @return array An array of meta keys and values.
1693
- */
1694
- public function getAcfContent( $post = null, $types = [] ) {
1695
- $post = ( $post && is_object( $post ) ) ? $post : $this->getPost( $post );
1696
-
1697
- if ( ! class_exists( 'ACF' ) || ! function_exists( 'get_field_objects' ) ) {
1698
- return [];
1699
- }
1700
-
1701
- if ( defined( 'ACF_VERSION' ) && version_compare( ACF_VERSION, '5.7.0', '<' ) ) {
1702
- return [];
1703
- }
1704
-
1705
- // Set defaults.
1706
- $allowedTypes = [
1707
- 'text',
1708
- 'textarea',
1709
- 'email',
1710
- 'url',
1711
- 'wysiwyg',
1712
- 'image',
1713
- 'gallery',
1714
- // 'link',
1715
- // 'taxonomy',
1716
- ];
1717
-
1718
- $types = wp_parse_args( $types, $allowedTypes );
1719
- $acfFields = [];
1720
-
1721
- $fieldObjects = get_field_objects( $post->ID );
1722
- if ( ! empty( $fieldObjects ) ) {
1723
- foreach ( $fieldObjects as $field ) {
1724
- if ( empty( $field['value'] ) ) {
1725
- continue;
1726
- }
1727
-
1728
- if ( ! in_array( $field['type'], $types, true ) ) {
1729
- continue;
1730
- }
1731
-
1732
- if ( 'url' === $field['type'] ) {
1733
- // Url field
1734
- $value = "<a href='{$field['value']}'>{$field['value']}</a>";
1735
- } elseif ( 'image' === $field['type'] ) {
1736
- // Image field
1737
- $value = "<img src='{$field['value']['url']}'>";
1738
- } elseif ( 'gallery' === $field['type'] ) {
1739
- // Image field
1740
- $value = "<img src='{$field['value'][0]['url']}'>";
1741
- } else {
1742
- // Other fields
1743
- $value = $field['value'];
1744
- }
1745
-
1746
- if ( $value ) {
1747
- $acfFields[ $field['name'] ] = $value;
1748
- }
1749
- }
1750
- }
1751
-
1752
- return $acfFields;
1753
- }
1754
-
1755
- /**
1756
- * Returns the posts custom fields.
1757
- *
1758
- * @since 4.0.6
1759
- *
1760
- * @param WP_Post|int $post The post.
1761
- * @return string The custom field content.
1762
- */
1763
- public function getAnalysisContent( $post = null ) {
1764
- $post = ( $post && is_object( $post ) ) ? $post : $this->getPost( $post );
1765
- $customFieldKeys = aioseo()->options->searchAppearance->dynamic->postTypes->{$post->post_type}->customFields;
1766
-
1767
- if ( empty( $customFieldKeys ) ) {
1768
- return get_post_field( 'post_content', $post->ID );
1769
  }
1770
 
1771
- $customFieldKeys = explode( ' ', sanitize_text_field( $customFieldKeys ) );
1772
- $customFieldContent = $this->getCustomFieldsContent( $post->ID, $customFieldKeys );
1773
- $analysisContent = $post->post_content . apply_filters( 'aioseo_analysis_content', $customFieldContent );
1774
-
1775
- return sanitize_post_field( 'post_content', $analysisContent, $post->ID, 'display' );
1776
  }
1777
 
1778
  /**
1779
- * Returns the string after it is encoded with htmlspecialchars().
1780
  *
1781
- * @since 4.0.0
1782
  *
1783
- * @param string $string The string to encode.
1784
- * @return string The encoded string.
1785
  */
1786
- public function encodeOutputHtml( $string ) {
1787
- return htmlspecialchars( $string, ENT_COMPAT | ENT_HTML401, get_option( 'blog_charset' ), false );
1788
  }
1789
 
1790
  /**
1791
- * Returns the string after all HTML entities have been decoded.
1792
  *
1793
  * @since 4.0.0
1794
  *
1795
- * @param string $string The string to decode.
1796
- * @return string The decoded string.
 
 
1797
  */
1798
- public function decodeHtmlEntities( $string ) {
1799
- return html_entity_decode( (string) $string, ENT_QUOTES );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1800
  }
1801
 
1802
  /**
1803
- * Returns if the page is a special type one (WooCommerce pages, Privacy page).
1804
  *
1805
  * @since 4.0.0
1806
  *
1807
- * @param int $postId The post ID.
1808
- * @return boolean If the page is special or not.
1809
  */
1810
- public function isSpecialPage( $postId = false ) {
1811
- if (
1812
- (int) get_option( 'page_for_posts' ) === (int) $postId ||
1813
- (int) get_option( 'wp_page_for_privacy_policy' ) === (int) $postId ||
1814
- $this->isBuddyPressPage( $postId ) ||
1815
- $this->isWooCommercePage( $postId )
1816
- ) {
1817
- return true;
1818
  }
1819
 
1820
- return false;
1821
  }
1822
 
1823
  /**
1824
- * Returns if the page is a WooCommerce page (Cart, Checkout, ...).
1825
  *
1826
  * @since 4.0.0
1827
  *
1828
- * @param int $postId The post ID.
1829
- * @return boolean If the page is a WooCommerce page or not.
1830
  */
1831
- public function isWooCommercePage( $postId = false ) {
1832
- if ( ! $this->isWooCommerceActive() ) {
1833
  return false;
1834
  }
1835
 
1836
- static $cartPageId;
1837
- if ( ! $cartPageId ) {
1838
- $cartPageId = (int) get_option( 'woocommerce_cart_page_id' );
1839
- }
1840
- static $checkoutPageId;
1841
- if ( ! $checkoutPageId ) {
1842
- $checkoutPageId = (int) get_option( 'woocommerce_checkout_page_id' );
1843
- }
1844
- static $myAccountPageId;
1845
- if ( ! $myAccountPageId ) {
1846
- $myAccountPageId = (int) get_option( 'woocommerce_myaccount_page_id' );
1847
- }
1848
- static $termsPageId;
1849
- if ( ! $termsPageId ) {
1850
- $termsPageId = (int) get_option( 'woocommerce_terms_page_id' );
1851
- }
1852
  if (
1853
- $cartPageId === (int) $postId ||
1854
- $checkoutPageId === (int) $postId ||
1855
- $myAccountPageId === (int) $postId ||
1856
- $termsPageId === (int) $postId
1857
  ) {
1858
  return true;
1859
  }
@@ -1862,41 +158,47 @@ class Helpers {
1862
  }
1863
 
1864
  /**
1865
- * Returns if the page is a BuddyPress page (Activity, Members, Groups).
1866
  *
1867
  * @since 4.0.0
1868
  *
1869
- * @param int $postId The post ID.
1870
- * @return boolean If the page is a BuddyPress page or not.
1871
  */
1872
- public function isBuddyPressPage( $postId = false ) {
1873
- $bpPages = get_option( 'bp-pages' );
1874
-
1875
- if ( empty( $bpPages ) ) {
1876
- return false;
1877
  }
1878
 
1879
- foreach ( $bpPages as $page ) {
1880
- if ( (int) $page === (int) $postId ) {
1881
- return true;
1882
- }
1883
  }
1884
 
 
1885
  return false;
1886
  }
1887
 
1888
  /**
1889
- * Get's the estimated reading time for a string.
1890
  *
1891
  * @since 4.0.0
1892
  *
1893
- * @param string $string The string to count.
1894
- * @return integer The estimated reading time as an integer.
1895
  */
1896
- public function getReadingTime( $string ) {
1897
- $wpm = 250;
1898
- $word = str_word_count( wp_strip_all_tags( $string ) );
1899
- return round( $word / $wpm );
 
 
 
 
 
 
 
 
 
1900
  }
1901
 
1902
  /**
@@ -1931,287 +233,6 @@ class Helpers {
1931
  }
1932
  }
1933
 
1934
- /**
1935
- * Checks if WPML is active.
1936
- *
1937
- * @since 4.0.0
1938
- *
1939
- * @return bool True if it is, false if not.
1940
- */
1941
- public function isWpmlActive() {
1942
- return class_exists( 'SitePress' );
1943
- }
1944
-
1945
- /**
1946
- * Check if the post passed in is a valid post, not a revision or autosave.
1947
- *
1948
- * @since 4.0.5
1949
- *
1950
- * @param WP_Post $post The Post object to check.
1951
- * @return bool True if valid, false if not.
1952
- */
1953
- public function isValidPost( $post ) {
1954
- if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
1955
- return false;
1956
- }
1957
-
1958
- if ( ! is_object( $post ) ) {
1959
- $post = get_post( $post );
1960
- }
1961
-
1962
- // In order to prevent recursion, we are skipping scheduled-action posts.
1963
- if (
1964
- empty( $post ) ||
1965
- 'scheduled-action' === $post->post_type ||
1966
- 'revision' === $post->post_type ||
1967
- 'publish' !== $post->post_status
1968
- ) {
1969
- return false;
1970
- }
1971
-
1972
- return true;
1973
- }
1974
-
1975
- /**
1976
- * Returns the URL for the WP content folder.
1977
- *
1978
- * @since 4.0.5
1979
- *
1980
- * @return string The URL.
1981
- */
1982
- public function getWpContentUrl() {
1983
- $info = wp_get_upload_dir();
1984
- return isset( $info['baseurl'] ) ? $info['baseurl'] : '';
1985
- }
1986
-
1987
- /**
1988
- * Checks whether the given URL is a valid attachment.
1989
- *
1990
- * @since 4.0.13
1991
- *
1992
- * @param string $url The URL.
1993
- * @return boolean Whether the URL is a valid attachment.
1994
- */
1995
- public function isValidAttachment( $url ) {
1996
- $uploadDirUrl = aioseo()->helpers->escapeRegex( $this->getWpContentUrl() );
1997
- return preg_match( "/$uploadDirUrl.*/", $url );
1998
- }
1999
-
2000
- /**
2001
- * Escapes special regex characters.
2002
- *
2003
- * @since 4.0.5
2004
- *
2005
- * @param string $string The string.
2006
- * @return string The escaped string.
2007
- */
2008
- public function escapeRegex( $string ) {
2009
- return preg_quote( $string, '/' );
2010
- }
2011
-
2012
- /**
2013
- * Escapes special regex characters inside the replacement string.
2014
- *
2015
- * @since 4.0.7
2016
- *
2017
- * @param string $string The string.
2018
- * @return string The escaped string.
2019
- */
2020
- public function escapeRegexReplacement( $string ) {
2021
- return str_replace( '$', '\$', $string );
2022
- }
2023
-
2024
- /**
2025
- * preg_replace but with the replacement escaped.
2026
- *
2027
- * @since 4.0.10
2028
- *
2029
- * @param string $pattern The pattern to search for.
2030
- * @param string $replacement The replacement string.
2031
- * @param string $subject The subject to search in.
2032
- * @return string The subject with matches replaced.
2033
- */
2034
- public function pregReplace( $pattern, $replacement, $subject ) {
2035
- $replacement = $this->escapeRegexReplacement( $replacement );
2036
- return preg_replace( $pattern, $replacement, $subject );
2037
- }
2038
-
2039
- /**
2040
- * Checks whether we're on the given screen.
2041
- *
2042
- * @since 4.0.7
2043
- *
2044
- * @param string $screenName The screen name.
2045
- * @return boolean Whether we're on the given screen.
2046
- */
2047
- public function isScreenBase( $screenName ) {
2048
- $screen = $this->getCurrentScreen();
2049
- if ( ! $screen || ! isset( $screen->base ) ) {
2050
- return false;
2051
- }
2052
- return $screen->base === $screenName;
2053
- }
2054
-
2055
- /**
2056
- * Returns if current screen is of a post type
2057
- *
2058
- * @since 4.0.17
2059
- *
2060
- * @param string $postType Post type slug
2061
- *
2062
- * @return bool
2063
- */
2064
- public function isScreenPostType( $postType ) {
2065
- $screen = $this->getCurrentScreen();
2066
- if ( ! $screen || ! isset( $screen->post_type ) ) {
2067
- return false;
2068
- }
2069
- return $screen->post_type === $postType;
2070
- }
2071
-
2072
- /**
2073
- * Gets current admin screen
2074
- *
2075
- * @since 4.0.17
2076
- *
2077
- * @return false|\WP_Screen|null
2078
- */
2079
- public function getCurrentScreen() {
2080
- if ( ! is_admin() || ! function_exists( 'get_current_screen' ) ) {
2081
- return false;
2082
- }
2083
-
2084
- return get_current_screen();
2085
- }
2086
-
2087
- /**
2088
- * Extracts existing sitemap URLs from the robots.txt file.
2089
- *
2090
- * We need this in case users have existing sitemap directives added to their robots.txt file.
2091
- *
2092
- * @since 4.0.10
2093
- *
2094
- * @return array An array with robots.txt sitemap directives.
2095
- */
2096
- private function extractSitemapUrlsFromRobotsTxt() {
2097
- // First, we need to remove our filter, so that it doesn't run unintentionally.
2098
- remove_filter( 'robots_txt', [ aioseo()->robotsTxt, 'buildRules' ], 10000 );
2099
- $robotsTxt = apply_filters( 'robots_txt', '', true );
2100
- add_filter( 'robots_txt', [ aioseo()->robotsTxt, 'buildRules' ], 10000, 2 );
2101
-
2102
- if ( ! $robotsTxt ) {
2103
- return [];
2104
- }
2105
-
2106
- $lines = explode( "\n", $robotsTxt );
2107
- if ( ! is_array( $lines ) || ! count( $lines ) ) {
2108
- return [];
2109
- }
2110
-
2111
- return aioseo()->robotsTxt->extractSitemapUrls( explode( "\n", $robotsTxt ) );
2112
- }
2113
-
2114
- /**
2115
- * Tries to convert an attachment URL into a post ID.
2116
- *
2117
- * This our own optimized version of attachment_url_to_postid().
2118
- *
2119
- * @since 4.0.13
2120
- *
2121
- * @param string $url The attachment URL.
2122
- * @return int|boolean The attachment ID or false if no attachment could be found.
2123
- */
2124
- public function attachmentUrlToPostId( $url ) {
2125
- $cacheName = "aioseo_attachment_url_to_post_id_$url";
2126
-
2127
- $cachedId = wp_cache_get( $cacheName, 'aioseo' );
2128
- if ( $cachedId ) {
2129
- return 'none' !== $cachedId && is_numeric( $cachedId ) ? (int) $cachedId : false;
2130
- }
2131
-
2132
- $path = $url;
2133
- $uploadDirInfo = wp_get_upload_dir();
2134
-
2135
- $siteUrl = wp_parse_url( $uploadDirInfo['url'] );
2136
- $imagePath = wp_parse_url( $path );
2137
-
2138
- // Force the protocols to match if needed.
2139
- if ( isset( $imagePath['scheme'] ) && ( $imagePath['scheme'] !== $siteUrl['scheme'] ) ) {
2140
- $path = str_replace( $imagePath['scheme'], $siteUrl['scheme'], $path );
2141
- }
2142
-
2143
- if ( ! $this->isValidAttachment( $path ) ) {
2144
- wp_cache_set( $cacheName, 'none', 'aioseo', DAY_IN_SECONDS );
2145
- return false;
2146
- }
2147
-
2148
- if ( 0 === strpos( $path, $uploadDirInfo['baseurl'] . '/' ) ) {
2149
- $path = substr( $path, strlen( $uploadDirInfo['baseurl'] . '/' ) );
2150
- }
2151
-
2152
- $results = aioseo()->db->start( 'postmeta' )
2153
- ->select( 'post_id' )
2154
- ->where( 'meta_key', '_wp_attached_file' )
2155
- ->where( 'meta_value', $path )
2156
- ->limit( 1 )
2157
- ->run()
2158
- ->result();
2159
-
2160
- if ( empty( $results[0]->post_id ) ) {
2161
- wp_cache_set( $cacheName, 'none', 'aioseo', DAY_IN_SECONDS );
2162
- return false;
2163
- }
2164
-
2165
- wp_cache_set( $cacheName, $results[0]->post_id, 'aioseo', DAY_IN_SECONDS );
2166
- return $results[0]->post_id;
2167
- }
2168
-
2169
- /**
2170
- * Checks if we are in a dev environment or not.
2171
- *
2172
- * @since 4.1.0
2173
- *
2174
- * @return boolean True if we are, false if not.
2175
- */
2176
- public function isDev() {
2177
- return defined( 'AIOSEO_DEV_VERSION' ) || isset( $_REQUEST['aioseo-dev'] ); // phpcs:ignore HM.Security.NonceVerification.Recommended
2178
- }
2179
-
2180
- /**
2181
- * Returns the given JSON formatted data tags as a comma separated list with their values instead.
2182
- *
2183
- * @since 4.1.0
2184
- *
2185
- * @param string $tags The JSON formatted data tags.
2186
- * @return string The comma separated values.
2187
- */
2188
- public function jsonTagsToCommaSeparatedList( $tags ) {
2189
- $tags = json_decode( $tags );
2190
-
2191
- $values = [];
2192
- foreach ( $tags as $k => $tag ) {
2193
- $values[ $k ] = $tag->value;
2194
- }
2195
- return implode( ',', $values );
2196
- }
2197
-
2198
- /**
2199
- * Encodes a number of exceptions before we strip tags.
2200
- * We need this function to allow certain character (combinations) in the title/description.
2201
- *
2202
- * @since 4.1.1
2203
- *
2204
- * @param string $string The string.
2205
- * @return string $string The string with exceptions encoded.
2206
- */
2207
- public function encodeExceptions( $string ) {
2208
- $exceptions = [ '<3' ];
2209
- foreach ( $exceptions as $exception ) {
2210
- $string = preg_replace( "/$exception/", $this->encodeOutputHtml( $exception ), $string );
2211
- }
2212
- return $string;
2213
- }
2214
-
2215
  /**
2216
  * Checks if the given string is serialized, and if so, unserializes it.
2217
  * If the serialized string contains an object, we abort to prevent PHP object injection.
@@ -2235,37 +256,4 @@ class Helpers {
2235
  }
2236
  return $string;
2237
  }
2238
-
2239
- /**
2240
- * Validates a URL.
2241
- *
2242
- * @since 4.1.2
2243
- *
2244
- * @param string $url The url.
2245
- * @return bool Is it a valid/safe url.
2246
- */
2247
- public function isUrl( $url ) {
2248
- return esc_url_raw( $url ) === $url;
2249
- }
2250
-
2251
- /**
2252
- * Returns true if the request is a non-legacy REST API request.
2253
- * This function was copied from WooCommerce and improved.
2254
- *
2255
- * @since 4.1.2
2256
- *
2257
- * @return bool True if this is a REST API request.
2258
- */
2259
- public function isRestApiRequest() {
2260
- if ( empty( $_SERVER['REQUEST_URI'] ) ) {
2261
- return false;
2262
- }
2263
-
2264
- $restUrl = wp_parse_url( get_rest_url() );
2265
- $restUrl = $restUrl['path'] . ( ! empty( $restUrl['query'] ) ? '?' . $restUrl['query'] : '' );
2266
-
2267
- $isRestApiRequest = ( 0 === strpos( $_SERVER['REQUEST_URI'], $restUrl ) );
2268
-
2269
- return apply_filters( 'aioseo_is_rest_api_request', $isRestApiRequest );
2270
- }
2271
  }
6
  exit;
7
  }
8
 
 
 
9
  use AIOSEO\Plugin\Common\Traits\Helpers as TraitHelpers;
10
 
11
  /**
15
  */
16
  class Helpers {
17
  use TraitHelpers\ActionScheduler;
18
+ use TraitHelpers\Arrays;
19
  use TraitHelpers\Constants;
20
  use TraitHelpers\DateTime;
21
+ use TraitHelpers\Language;
22
  use TraitHelpers\Shortcodes;
23
  use TraitHelpers\Strings;
24
+ use TraitHelpers\Svg;
25
+ use TraitHelpers\ThirdParty;
26
+ use TraitHelpers\Vue;
27
+ use TraitHelpers\Wp;
28
+ use TraitHelpers\WpContext;
29
+ use TraitHelpers\WpUri;
 
 
 
30
 
31
  /**
32
  * Generate a UTM URL from the url and medium/content passed in.
55
  'utm_medium' => $medium
56
  ];
57
 
58
+ // Content is not used by default.
59
+ if ( $content ) {
60
+ $args['utm_content'] = $content;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
 
63
+ // Return the new URL.
64
+ $url = add_query_arg( $args, $url );
65
+ return $esc ? esc_url( $url ) : $url;
 
 
66
  }
67
 
68
  /**
69
+ * Checks if we are in a dev environment or not.
70
  *
71
+ * @since 4.1.0
72
  *
73
+ * @return boolean True if we are, false if not.
 
74
  */
75
+ public function isDev() {
76
+ return defined( 'AIOSEO_DEV_VERSION' ) || isset( $_REQUEST['aioseo-dev'] ); // phpcs:ignore HM.Security.NonceVerification.Recommended
77
  }
78
 
79
  /**
80
+ * Request the remote URL via wp_remote_post and return a json decoded response.
81
  *
82
  * @since 4.0.0
83
  *
84
+ * @param array $body The content to retrieve from the remote URL.
85
+ * @param array $headers The headers to send to the remote URL.
86
+ *
87
+ * @return string|bool Json decoded response on success, false on failure.
88
  */
89
+ public function sendRequest( $url, $body = [], $headers = [] ) {
90
+ $body = wp_json_encode( $body );
91
+
92
+ // Build the headers of the request.
93
+ $headers = wp_parse_args(
94
+ $headers,
95
+ [
96
+ 'Content-Type' => 'application/json'
97
+ ]
98
+ );
99
+
100
+ // Setup variable for wp_remote_post.
101
+ $post = [
102
+ 'headers' => $headers,
103
+ 'body' => $body,
104
+ 'sslverify' => $this->isDev() ? false : true,
105
+ 'timeout' => 20
106
+ ];
107
+
108
+ // Perform the query and retrieve the response.
109
+ $response = wp_remote_post( $url, $post );
110
+ $responseBody = wp_remote_retrieve_body( $response );
111
+
112
+ // Bail out early if there are any errors.
113
+ if ( is_wp_error( $responseBody ) ) {
114
+ return false;
115
+ }
116
+
117
+ // Return the json decoded content.
118
+ return json_decode( $responseBody );
119
  }
120
 
121
  /**
122
+ * Checks if the server is running on Apache.
123
  *
124
  * @since 4.0.0
125
  *
126
+ * @return boolean Whether or not it is on apache.
 
127
  */
128
+ public function isApache() {
129
+ if ( ! isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
130
+ return false;
 
 
 
 
 
131
  }
132
 
133
+ return stripos( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ), 'apache' ) !== false;
134
  }
135
 
136
  /**
137
+ * Checks if the server is running on nginx.
138
  *
139
  * @since 4.0.0
140
  *
141
+ * @return boolean Whether or not it is on apache.
 
142
  */
143
+ public function isNginx() {
144
+ if ( ! isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
145
  return false;
146
  }
147
 
148
+ $server = sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) );
149
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  if (
151
+ stripos( $server, 'Flywheel' ) !== false ||
152
+ stripos( $server, 'nginx' ) !== false
 
 
153
  ) {
154
  return true;
155
  }
158
  }
159
 
160
  /**
161
+ * Validate IP addresses.
162
  *
163
  * @since 4.0.0
164
  *
165
+ * @param string $ip The IP address to validate.
166
+ * @return boolean If the IP address is valid or not.
167
  */
168
+ public function validateIp( $ip ) {
169
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
170
+ return true;
 
 
171
  }
172
 
173
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
174
+ return true;
 
 
175
  }
176
 
177
+ // Doesn't seem to be a valid IP.
178
  return false;
179
  }
180
 
181
  /**
182
+ * Convert bytes to readable format.
183
  *
184
  * @since 4.0.0
185
  *
186
+ * @param integer $bytes The size of the file.
187
+ * @return string The size as a string.
188
  */
189
+ public function convertFileSize( $bytes ) {
190
+ if ( empty( $bytes ) ) {
191
+ return [
192
+ 'original' => 0,
193
+ 'readable' => '0 B'
194
+ ];
195
+ }
196
+ $i = floor( log( $bytes ) / log( 1024 ) );
197
+ $sizes = [ 'B', 'KB', 'MB', 'GB', 'TB' ];
198
+ return [
199
+ 'original' => $bytes,
200
+ 'readable' => sprintf( '%.02F', $bytes / pow( 1024, $i ) ) * 1 . ' ' . $sizes[ $i ]
201
+ ];
202
  }
203
 
204
  /**
233
  }
234
  }
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  /**
237
  * Checks if the given string is serialized, and if so, unserializes it.
238
  * If the serialized string contains an object, we abort to prevent PHP object injection.
256
  }
257
  return $string;
258
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  }
app/Common/Utils/Templates.php CHANGED
@@ -82,10 +82,10 @@ class Templates {
82
  * Includes a template if the file exists.
83
  *
84
  * @param string $templateName The template path/name.php to be included.
85
- * @param null $args Args passed down to the template.
86
  * @return void
87
  */
88
- public function getTemplate( $templateName, $args = null ) {
89
  $template = $this->locateTemplate( $templateName );
90
  if ( ! empty( $template ) and file_exists( $template ) ) {
91
  include $template;
82
  * Includes a template if the file exists.
83
  *
84
  * @param string $templateName The template path/name.php to be included.
85
+ * @param null $data Data passed down to the template.
86
  * @return void
87
  */
88
+ public function getTemplate( $templateName, $data = null ) {
89
  $template = $this->locateTemplate( $templateName );
90
  if ( ! empty( $template ) and file_exists( $template ) ) {
91
  include $template;
app/Common/Utils/VueSettings.php CHANGED
@@ -61,7 +61,6 @@ class VueSettings {
61
  'rssSitemapSettings' => true,
62
  'rssAdditionalPages' => true,
63
  'rssAdvancedSettings' => true,
64
- 'htmlSitemap' => true,
65
  'additionalPages' => true,
66
  'advancedSettings' => true,
67
  'videoSitemapSettings' => true,
@@ -93,6 +92,8 @@ class VueSettings {
93
  'localBusinessOpeningHours' => true,
94
  'locationsSettings' => true,
95
  'advancedLocationsSettings' => true,
 
 
96
  'robotsEditor' => true,
97
  'badBotBlocker' => true,
98
  'databaseTools' => true,
@@ -105,7 +106,10 @@ class VueSettings {
105
  'fullSiteRedirectsRelocate' => true,
106
  'fullSiteRedirectsAliases' => true,
107
  'fullSiteRedirectsCanonical' => true,
108
- 'fullSiteRedirectsHttpHeaders' => true
 
 
 
109
  ],
110
  'toggledRadio' => [
111
  'locationsShowOnWebsite' => 'widget',
@@ -176,7 +180,7 @@ class VueSettings {
176
  }
177
 
178
  /**
179
- * Retrieve an settings or null if missing.
180
  *
181
  * @since 4.0.0
182
  *
@@ -185,11 +189,12 @@ class VueSettings {
185
  * @return mixed The value from the settings or default/null.
186
  */
187
  public function __call( $name, $arguments = [] ) {
188
- return isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : ( ! empty( $arguments[0] ) ? $arguments[0] : $this->getDefault( $name ) );
 
189
  }
190
 
191
  /**
192
- * Retrieve an settings or null if missing.
193
  *
194
  * @since 4.0.0
195
  *
@@ -197,7 +202,8 @@ class VueSettings {
197
  * @return mixed The value from the settings or default/null.
198
  */
199
  public function __get( $name ) {
200
- return isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : $this->getDefault( $name );
 
201
  }
202
 
203
  /**
61
  'rssSitemapSettings' => true,
62
  'rssAdditionalPages' => true,
63
  'rssAdvancedSettings' => true,
 
64
  'additionalPages' => true,
65
  'advancedSettings' => true,
66
  'videoSitemapSettings' => true,
92
  'localBusinessOpeningHours' => true,
93
  'locationsSettings' => true,
94
  'advancedLocationsSettings' => true,
95
+ 'localBusinessMapsApiKey' => true,
96
+ 'localBusinessMapsSettings' => true,
97
  'robotsEditor' => true,
98
  'badBotBlocker' => true,
99
  'databaseTools' => true,
106
  'fullSiteRedirectsRelocate' => true,
107
  'fullSiteRedirectsAliases' => true,
108
  'fullSiteRedirectsCanonical' => true,
109
+ 'fullSiteRedirectsHttpHeaders' => true,
110
+ 'htmlSitemap' => true,
111
+ 'htmlSitemapSettings' => true,
112
+ 'htmlSitemapAdvancedSettings' => true
113
  ],
114
  'toggledRadio' => [
115
  'locationsShowOnWebsite' => 'widget',
180
  }
181
 
182
  /**
183
+ * Retrieve a setting or null if missing.
184
  *
185
  * @since 4.0.0
186
  *
189
  * @return mixed The value from the settings or default/null.
190
  */
191
  public function __call( $name, $arguments = [] ) {
192
+ $value = isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : ( ! empty( $arguments[0] ) ? $arguments[0] : $this->getDefault( $name ) );
193
+ return $value;
194
  }
195
 
196
  /**
197
+ * Retrieve a setting or null if missing.
198
  *
199
  * @since 4.0.0
200
  *
202
  * @return mixed The value from the settings or default/null.
203
  */
204
  public function __get( $name ) {
205
+ $value = isset( $this->settings[ $name ] ) ? $this->settings[ $name ] : $this->getDefault( $name );
206
+ return $value;
207
  }
208
 
209
  /**
app/Common/Views/admin/posts/columns.php CHANGED
@@ -13,4 +13,6 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
14
  ?>
15
 
16
- <div id="<?php echo esc_attr( $columnName ); ?>-<?php echo esc_attr( $postId ); ?>"></div>
 
 
13
  // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
14
  ?>
15
 
16
+ <div id="<?php echo esc_attr( $columnName ); ?>-<?php echo esc_attr( $postId ); ?>">
17
+ <?php require( AIOSEO_DIR . '/app/Common/Views/parts/loader.php' ); ?>
18
+ </div>
app/Common/Views/main/meta.php CHANGED
@@ -20,10 +20,10 @@ $canonical = aioseo()->helpers->canonicalUrl();
20
  $links = $this->links->getLinks();
21
  ?>
22
  <?php if ( $description ) : ?>
23
- <meta name="description" content="<?php echo esc_attr( $description ); ?>"/>
24
  <?php endif; ?>
25
  <?php if ( $robots ) : ?>
26
- <meta name="robots" content="<?php echo esc_html( $robots ); ?>"/>
27
  <?php endif; ?>
28
  <?php
29
  // Adds the site verification meta for webmaster tools.
20
  $links = $this->links->getLinks();
21
  ?>
22
  <?php if ( $description ) : ?>
23
+ <meta name="description" content="<?php echo esc_attr( $description ); ?>" />
24
  <?php endif; ?>
25
  <?php if ( $robots ) : ?>
26
+ <meta name="robots" content="<?php echo esc_html( $robots ); ?>" />
27
  <?php endif; ?>
28
  <?php
29
  // Adds the site verification meta for webmaster tools.
app/Common/Views/sitemap/html/compact-archive.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
3
+ // phpcs:disable Generic.ControlStructures.InlineControlStructure.NotAllowed
4
+ ?>
5
+ <div class="aioseo-html-sitemap">
6
+ <div class="aioseo-html-sitemap-compact-archive">
7
+ <?php if ( empty( $data['dateArchives'] ) ) esc_html_e( 'No date archives could be found.', 'all-in-one-seo-pack' ); ?>
8
+
9
+ <?php if ( ! empty( $data['lines'] ) ) : ?>
10
+ <ul>
11
+ <?php echo $data['lines']; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
12
+ </ul>
13
+ <?php endif; ?>
14
+
15
+ </div>
16
+ </div>
app/Common/Views/sitemap/html/widget-options.php ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
3
+ ?>
4
+
5
+ <div class="aioseo-html-sitemap">
6
+ <p>
7
+ <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" class="aioseo-title">
8
+ <?php esc_html_e( 'Title', 'all-in-one-seo-pack' ); ?>
9
+ </label>
10
+ <input
11
+ type="text"
12
+ id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
13
+ name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
14
+ value="<?php echo esc_attr( $instance['title'] ); ?>"
15
+ class="widefat"
16
+ />
17
+ </p>
18
+ <p>
19
+ <label for="<?php echo esc_attr( $this->get_field_id( 'archives' ) ); ?>">
20
+ <input
21
+ type="checkbox"
22
+ id="<?php echo esc_attr( $this->get_field_id( 'archives' ) ); ?>"
23
+ name="<?php echo esc_attr( $this->get_field_name( 'archives' ) ); ?>"
24
+ <?php
25
+ if ( 'on' === $instance['archives'] ) {
26
+ echo 'checked="checked"';
27
+ }
28
+ ?>
29
+ class="widefat"
30
+ />
31
+ <?php esc_html_e( 'Compact Archives', 'all-in-one-seo-pack' ); ?>
32
+ </label>
33
+ </p>
34
+ <p>
35
+ <label for="<?php echo esc_attr( $this->get_field_id( 'show_label' ) ); ?>">
36
+ <input
37
+ type="checkbox"
38
+ id="<?php echo esc_attr( $this->get_field_id( 'show_label' ) ); ?>"
39
+ name="<?php echo esc_attr( $this->get_field_name( 'show_label' ) ); ?>"
40
+ <?php
41
+ if ( 'on' === $instance['show_label'] ) {
42
+ echo 'checked="checked"';
43
+ }
44
+ ?>
45
+ class="widefat"
46
+ />
47
+ <?php esc_html_e( 'Show Labels', 'all-in-one-seo-pack' ); ?>
48
+ </label>
49
+ </p>
50
+ <p>
51
+ <label for="<?php echo esc_attr( $this->get_field_id( 'publication_date' ) ); ?>">
52
+ <input
53
+ type="checkbox"
54
+ id="<?php echo esc_attr( $this->get_field_id( 'publication_date' ) ); ?>"
55
+ name="<?php echo esc_attr( $this->get_field_name( 'publication_date' ) ); ?>"
56
+ <?php
57
+ if ( 'on' === $instance['publication_date'] ) {
58
+ echo 'checked="checked"';
59
+ }
60
+ ?>
61
+ class="widefat"
62
+ />
63
+ <?php esc_html_e( 'Show Publication Date', 'all-in-one-seo-pack' ); ?>
64
+ </label>
65
+ </p>
66
+
67
+ <p>
68
+ <label for="<?php echo esc_attr( $this->get_field_id( 'post_types' ) ); ?>" class="aioseo-title">
69
+ <?php esc_html_e( 'Post Types', 'all-in-one-seo-pack' ); ?>
70
+ </label>
71
+
72
+ <div class="aioseo-columns">
73
+ <?php foreach ( $postTypeObjects as $i => $postTypeObject ) : ?>
74
+ <div>
75
+ <label>
76
+ <input
77
+ type="checkbox"
78
+ name="<?php echo esc_attr( $this->get_field_name( 'post_types' ) ); ?>[]"
79
+ id="<?php echo esc_attr( $this->get_field_id( 'post_types' . $i ) ); ?>"
80
+ <?php checked( in_array( $postTypeObject['name'], $instance['post_types'], true ) ); ?>
81
+ value="<?php echo esc_html( $i ); ?>"
82
+ />
83
+ <?php echo esc_html( $postTypeObject['label'] ); ?>
84
+ </label>
85
+ </div>
86
+ <?php endforeach ?>
87
+ </div>
88
+ </p>
89
+
90
+ <p>
91
+ <label for="<?php echo esc_attr( $this->get_field_id( 'taxonomies' ) ); ?>" class="aioseo-title">
92
+ <?php esc_html_e( 'Taxonomies', 'all-in-one-seo-pack' ); ?>
93
+ </label>
94
+
95
+ <div class="aioseo-columns">
96
+ <?php foreach ( $taxonomyObjects as $i => $taxonomyObject ) : ?>
97
+ <div>
98
+ <label>
99
+ <input
100
+ type="checkbox"
101
+ name="<?php echo esc_attr( $this->get_field_name( 'taxonomies' ) ); ?>[]"
102
+ id="<?php echo esc_attr( $this->get_field_id( 'taxonomies' . $i ) ); ?>"
103
+ <?php checked( in_array( $taxonomyObject['name'], $instance['taxonomies'], true ) ); ?>
104
+ value="<?php echo esc_html( $i ); ?>"
105
+ />
106
+ <?php echo esc_html( $taxonomyObject['label'] ); ?>
107
+ </label>
108
+ </div>
109
+ <?php endforeach ?>
110
+ </div>
111
+ </p>
112
+
113
+ <p>
114
+ <label for="<?php echo esc_attr( $this->get_field_id( 'order_by' ) ); ?>" class="aioseo-title">
115
+ <?php esc_html_e( 'Sort Order', 'all-in-one-seo-pack' ); ?>
116
+ </label>
117
+ <select name="<?php echo esc_attr( $this->get_field_name( 'order_by' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'order_by' ) ); ?>" class="widefat">
118
+ <option value="publish_date"<?php selected( 'publish_date', $instance['order_by'], true ); ?>>
119
+ <?php esc_html_e( 'Publish Date', 'all-in-one-seo-pack' ); ?>
120
+ </option>
121
+ <option value="last_updated"<?php selected( 'last_updated', $instance['order_by'], true ); ?>>
122
+ <?php esc_html_e( 'Last Updated', 'all-in-one-seo-pack' ); ?>
123
+ </option>
124
+ <option value="alphabetical"<?php selected( 'alphabetical', $instance['order_by'], true ); ?>>
125
+ <?php esc_html_e( 'Alphabetical', 'all-in-one-seo-pack' ); ?>
126
+ </option>
127
+ <option value="id"<?php selected( 'id', $instance['order_by'], true ); ?>>
128
+ <?php esc_html_e( 'ID', 'all-in-one-seo-pack' ); ?>
129
+ </option>
130
+ </select>
131
+ </p>
132
+ <p>
133
+ <label for="<?php echo esc_attr( $this->get_field_id( 'order' ) ); ?>" class="aioseo-title">
134
+ <?php esc_html_e( 'Sort Direction', 'all-in-one-seo-pack' ); ?>
135
+ </label>
136
+ <select name="<?php echo esc_attr( $this->get_field_name( 'order' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'order' ) ); ?>" class="widefat">
137
+ <option value="asc"<?php echo ( 'asc' === $instance['order'] ) ? ' selected="selected"' : '' ?>><?php esc_html_e( 'Ascending', 'all-in-one-seo-pack' ); ?></option>
138
+ <option value="desc"<?php echo ( 'desc' === $instance['order'] ) ? ' selected="selected"' : '' ?>"><?php esc_html_e( 'Descending', 'all-in-one-seo-pack' ); ?></option>
139
+ </select>
140
+ </p>
141
+
142
+ <p>
143
+ <label for="<?php echo esc_attr( $this->get_field_id( 'excluded_posts' ) ); ?>" class="aioseo-title">
144
+ <?php esc_html_e( 'Exclude Posts / Pages', 'all-in-one-seo-pack' ); ?>
145
+ </label>
146
+ <input
147
+ type="text"
148
+ value="<?php echo esc_attr( $instance['excluded_posts'] ); ?>"
149
+ name="<?php echo esc_attr( $this->get_field_name( 'excluded_posts' ) ); ?>"
150
+ id="<?php echo esc_attr( $this->get_field_id( 'excluded_posts' ) ); ?>"
151
+ class="widefat"
152
+ />
153
+ <p class="aioseo-description"><?php esc_html_e( 'Enter a comma-separated list of post IDs.', 'all-in-one-seo-pack' ); ?></p>
154
+ </p>
155
+
156
+ <p>
157
+ <label for="<?php echo esc_attr( $this->get_field_id( 'excluded_terms' ) ); ?>" class="aioseo-title">
158
+ <?php esc_html_e( 'Exclude Terms', 'all-in-one-seo-pack' ); ?>
159
+ </label>
160
+ <input
161
+ type="text"
162
+ value="<?php echo esc_attr( $instance['excluded_terms'] ); ?>"
163
+ name="<?php echo esc_attr( $this->get_field_name( 'excluded_terms' ) ); ?>"
164
+ id="<?php echo esc_attr( $this->get_field_id( 'excluded_terms' ) ); ?>"
165
+ class="widefat"
166
+ />
167
+ <p class="aioseo-description"><?php esc_html_e( 'Enter a comma-separated list of term IDs.', 'all-in-one-seo-pack' ); ?></p>
168
+ </p>
169
+ </div>
170
+
171
+ <style>
172
+ .aioseo-html-sitemap label.aioseo-title,
173
+ .aioseo-html-sitemap label.aioseo-title select {
174
+ color: #141B38 !important;
175
+ font-weight: bold !important;
176
+ }
177
+ .aioseo-html-sitemap .aioseo-description {
178
+ margin-top: -5px;
179
+ font-style: italic;
180
+ font-size: 13px;
181
+ }
182
+ .aioseo-html-sitemap select, .aioseo-html-sitemap input[type=text] {
183
+ margin-top: 8px;
184
+ }
185
+ .aioseo-html-sitemap .aioseo-columns {
186
+ display: flex;
187
+ flex-wrap: wrap;
188
+ }
189
+ .aioseo-html-sitemap .aioseo-columns div {
190
+ flex: 0 0 50%;
191
+ }
192
+ </style>
app/Lite/Admin/Admin.php CHANGED
@@ -36,7 +36,7 @@ class Admin extends CommonAdmin\Admin {
36
  */
37
  protected function addAdminBarMenuItems() {
38
  // Add an upsell to Pro.
39
- if ( current_user_can( 'update_plugins' ) ) {
40
  $this->adminBarMenuItems['aioseo-pro-upgrade'] = [
41
  'parent' => 'aioseo-main',
42
  'title' => '<span class="aioseo-menu-highlight">' . __( 'Upgrade to Pro', 'all-in-one-seo-pack' ) . '</span>',
@@ -59,12 +59,14 @@ class Admin extends CommonAdmin\Admin {
59
  public function addMenu() {
60
  parent::addMenu();
61
 
 
 
62
  // We use the global submenu, because we are adding an external link here.
63
- if ( current_user_can( 'aioseo_manage_seo' ) ) {
64
  global $submenu;
65
  $submenu[ $this->pageSlug ][] = [
66
  '<span class="aioseo-menu-highlight">' . esc_html__( 'Upgrade to Pro', 'all-in-one-seo-pack' ) . '</span>',
67
- apply_filters( 'aioseo_manage_seo', 'aioseo_manage_seo' ),
68
  apply_filters( 'aioseo_upgrade_link', aioseo()->helpers->utmUrl( AIOSEO_MARKETING_URL . 'lite-upgrade/', 'admin-menu', null, false ) )
69
  ];
70
  }
36
  */
37
  protected function addAdminBarMenuItems() {
38
  // Add an upsell to Pro.
39
+ if ( current_user_can( $this->getPageRequiredCapability( '' ) ) ) {
40
  $this->adminBarMenuItems['aioseo-pro-upgrade'] = [
41
  'parent' => 'aioseo-main',
42
  'title' => '<span class="aioseo-menu-highlight">' . __( 'Upgrade to Pro', 'all-in-one-seo-pack' ) . '</span>',
59
  public function addMenu() {
60
  parent::addMenu();
61
 
62
+ $capability = $this->getPageRequiredCapability( '' );
63
+
64
  // We use the global submenu, because we are adding an external link here.
65
+ if ( current_user_can( $capability ) ) {
66
  global $submenu;
67
  $submenu[ $this->pageSlug ][] = [
68
  '<span class="aioseo-menu-highlight">' . esc_html__( 'Upgrade to Pro', 'all-in-one-seo-pack' ) . '</span>',
69
+ $capability,
70
  apply_filters( 'aioseo_upgrade_link', aioseo()->helpers->utmUrl( AIOSEO_MARKETING_URL . 'lite-upgrade/', 'admin-menu', null, false ) )
71
  ];
72
  }
app/Lite/Admin/Connect.php CHANGED
@@ -73,7 +73,8 @@ class Connect {
73
  remove_action( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' );
74
 
75
  if ( 'aioseo-connect-pro' === wp_unslash( $_GET['page'] ) ) { // phpcs:ignore HM.Security.ValidatedSanitizedInput.InputNotSanitized
76
- return $this->loadConnectPro();
 
77
  }
78
 
79
  $this->loadConnect();
73
  remove_action( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' );
74
 
75
  if ( 'aioseo-connect-pro' === wp_unslash( $_GET['page'] ) ) { // phpcs:ignore HM.Security.ValidatedSanitizedInput.InputNotSanitized
76
+ $this->loadConnectPro();
77
+ return;
78
  }
79
 
80
  $this->loadConnect();
app/Lite/Main/Updates.php DELETED
@@ -1,44 +0,0 @@
1
- <?php
2
- namespace AIOSEO\Plugin\Lite\Main;
3
-
4
- // Exit if accessed directly.
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- }
8
-
9
- use AIOSEO\Plugin\Common\Main as CommonMain;
10
-
11
- /**
12
- * Common class with methods that are called.
13
- *
14
- * @since 4.0.0
15
- */
16
- class Updates extends CommonMain\Updates {
17
- /**
18
- * Run our version updates here.
19
- *
20
- * @since 4.0.0
21
- *
22
- * @param string $oldVersion The old version number to compare against.
23
- * @return void
24
- */
25
- protected function doVersionUpdates( $oldVersion ) {
26
- parent::doVersionUpdates( $oldVersion );
27
-
28
- if ( version_compare( $oldVersion, '2.3.3', '<' ) ) {
29
- $this->badBots201603();
30
- }
31
-
32
- if ( version_compare( $oldVersion, '2.3.4.1', '<' ) ) {
33
- $this->badBotsRemoveYandex201604();
34
- }
35
-
36
- if ( version_compare( $oldVersion, '2.3.9', '<' ) ) {
37
- $this->badBotsRemoveSeznambot201608();
38
- }
39
-
40
- if ( version_compare( $oldVersion, '2.9', '<' ) ) {
41
- $this->badBotsRemoveSemrush201810();
42
- }
43
- }
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Lite/Meta/Main.php DELETED
@@ -1,26 +0,0 @@
1
- <?php
2
- namespace AIOSEO\Plugin\Lite\Meta;
3
-
4
- // Exit if accessed directly.
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- }
8
-
9
- use \AIOSEO\Plugin\Common\Meta as CommonMeta;
10
-
11
- /**
12
- * Handles our ouput in the document head.
13
- *
14
- * @since 4.0.0
15
- */
16
- class Main extends CommonMeta\Main {
17
- /**
18
- * Class constructor.
19
- *
20
- * @since 4.0.0
21
- */
22
- public function __construct() {
23
- parent::__construct();
24
- $this->included = new CommonMeta\Included();
25
- }
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Lite/Options/InternalOptions.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Lite\Options;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ use AIOSEO\Plugin\Common\Options as CommonOptions;
10
+ use AIOSEO\Plugin\Lite\Traits;
11
+
12
+ /**
13
+ * Class that holds all internal options for AIOSEO.
14
+ *
15
+ * @since 4.0.0
16
+ */
17
+ class InternalOptions extends CommonOptions\InternalOptions {
18
+ use Traits\Options;
19
+
20
+ /**
21
+ * Defaults options for Lite.
22
+ *
23
+ * @since 4.0.0
24
+ *
25
+ * @var array
26
+ */
27
+ private $liteDefaults = [
28
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
29
+ 'internal' => [
30
+ 'activated' => [ 'type' => 'number', 'default' => 0 ],
31
+ 'firstActivated' => [ 'type' => 'number', 'default' => 0 ],
32
+ 'installed' => [ 'type' => 'number', 'default' => 0 ],
33
+ 'connect' => [
34
+ 'key' => [ 'type' => 'string' ],
35
+ 'time' => [ 'type' => 'number', 'default' => 0 ],
36
+ 'network' => [ 'type' => 'boolean', 'default' => false ],
37
+ 'token' => [ 'type' => 'string' ]
38
+ ]
39
+ ]
40
+ // phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
41
+ ];
42
+ }
app/Lite/Options/Options.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Lite\Options;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ use AIOSEO\Plugin\Common\Options as CommonOptions;
10
+ use AIOSEO\Plugin\Lite\Traits;
11
+
12
+ /**
13
+ * Class that holds all options for AIOSEO.
14
+ *
15
+ * @since 4.0.0
16
+ */
17
+ class Options extends CommonOptions\Options {
18
+ use Traits\Options;
19
+
20
+ /**
21
+ * Defaults options for Lite.
22
+ *
23
+ * @since 4.0.0
24
+ *
25
+ * @var array
26
+ */
27
+ private $liteDefaults = [
28
+ // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
29
+ 'advanced' => [
30
+ 'usageTracking' => [ 'type' => 'boolean', 'default' => false ]
31
+ ]
32
+ // phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
33
+ ];
34
+ }
app/Lite/Traits/Options.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace AIOSEO\Plugin\Lite\Traits;
3
+
4
+ // Exit if accessed directly.
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Options trait.
11
+ *
12
+ * @since 4.0.0
13
+ */
14
+ trait Options {
15
+ /**
16
+ * Initialize the options.
17
+ *
18
+ * @since 4.1.4
19
+ *
20
+ * @return void
21
+ */
22
+ protected function init() {
23
+ parent::init();
24
+
25
+ $dbOptions = $this->getDbOptions( $this->optionsName . '_lite' );
26
+
27
+ // Refactor options.
28
+ $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->liteDefaults );
29
+
30
+ $mergedDefaults = array_replace_recursive(
31
+ $this->liteDefaults,
32
+ $this->addValueToValuesArray( $this->liteDefaults, $dbOptions )
33
+ );
34
+
35
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
36
+ $dbOptions = array_replace_recursive(
37
+ $cachedOptions,
38
+ $mergedDefaults
39
+ );
40
+
41
+ aioseo()->optionsCache->setOptions( $this->optionsName, $dbOptions );
42
+ }
43
+
44
+ /**
45
+ * Merge defaults with liteDefaults.
46
+ *
47
+ * @since 4.1.4
48
+ *
49
+ * @return array An array of dafults.
50
+ */
51
+ public function getDefaults() {
52
+ return array_replace_recursive( parent::getDefaults(), $this->liteDefaults );
53
+ }
54
+
55
+ /**
56
+ * Updates the options in the database.
57
+ *
58
+ * @since 4.1.4
59
+ *
60
+ * @param string $optionsName An optional option name to update.
61
+ * @param string $defaults The defaults to filter the options by.
62
+ * @param array|null $options An optional options array.
63
+ * @return void
64
+ */
65
+ public function update( $optionsName = null, $defaults = null, $options = null ) {
66
+ $optionsName = empty( $optionsName ) ? $this->optionsName . '_lite' : $optionsName;
67
+ $defaults = empty( $defaults ) ? $this->liteDefaults : $defaults;
68
+
69
+ // We're creating a new array here because it was setting it by reference.
70
+ $cachedOptions = aioseo()->optionsCache->getOptions( $this->optionsName );
71
+ $optionsBefore = json_decode( wp_json_encode( $cachedOptions ), true );
72
+
73
+ parent::update( $this->optionsName, $options );
74
+ parent::update( $optionsName, $defaults, $optionsBefore );
75
+ }
76
+
77
+ /**
78
+ * Updates the options in the database.
79
+ *
80
+ * @since 4.1.4
81
+ *
82
+ * @param boolean $force Whether or not to force an immediate save.
83
+ * @param string $optionsName An optional option name to update.
84
+ * @param string $defaults The defaults to filter the options by.
85
+ * @return void
86
+ */
87
+ public function save( $force = false, $optionsName = null, $defaults = null ) {
88
+ if ( ! $this->shouldSave && ! $force ) {
89
+ return;
90
+ }
91
+
92
+ $optionsName = empty( $optionsName ) ? $this->optionsName . '_lite' : $optionsName;
93
+ $defaults = empty( $defaults ) ? $this->liteDefaults : $defaults;
94
+
95
+ parent::save( $force, $this->optionsName );
96
+ parent::save( $force, $optionsName, $defaults );
97
+ }
98
+ }
app/Lite/Utils/InternalOptions.php DELETED
@@ -1,102 +0,0 @@
1
- <?php
2
- namespace AIOSEO\Plugin\Lite\Utils;
3
-
4
- // Exit if accessed directly.
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- }
8
-
9
- use AIOSEO\Plugin\Common\Utils as CommonUtils;
10
-
11
- /**
12
- * Class that holds all internal options for AIOSEO.
13
- *
14
- * @since 4.0.0
15
- */
16
- class InternalOptions extends CommonUtils\InternalOptions {
17
- /**
18
- * Defaults options for Lite.
19
- *
20
- * @since 4.0.0
21
- *
22
- * @var array
23
- */
24
- private $liteDefaults = [
25
- // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
26
- 'internal' => [
27
- 'activated' => [ 'type' => 'number', 'default' => 0 ],
28
- 'firstActivated' => [ 'type' => 'number', 'default' => 0 ],
29
- 'installed' => [ 'type' => 'number', 'default' => 0 ],
30
- 'connect' => [
31
- 'key' => [ 'type' => 'string' ],
32
- 'time' => [ 'type' => 'number', 'default' => 0 ],
33
- 'network' => [ 'type' => 'boolean', 'default' => false ],
34
- 'token' => [ 'type' => 'string' ]
35
- ]
36
- ]
37
- // phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
38
- ];
39
-
40
- /**
41
- * Class constructor
42
- *
43
- * @since 4.0.0
44
- */
45
- public function __construct( $optionsName = 'aioseo_options_internal' ) {
46
- parent::__construct( $optionsName );
47
-
48
- $this->init();
49
- }
50
-
51
- /**
52
- * Initializes the options.
53
- *
54
- * @since 4.0.0
55
- *
56
- * @return void
57
- */
58
- protected function init() {
59
- parent::init();
60
-
61
- $dbOptions = json_decode( get_option( $this->optionsName . '_lite' ), true );
62
- if ( empty( $dbOptions ) ) {
63
- $dbOptions = [];
64
- }
65
-
66
- // Refactor options.
67
- $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->liteDefaults );
68
-
69
- $options = array_replace_recursive(
70
- $this->options,
71
- $this->addValueToValuesArray( $this->options, $dbOptions )
72
- );
73
-
74
- $this->options = apply_filters( 'aioseo_get_options_internal_lite', $options );
75
- }
76
-
77
- /**
78
- * Updates the options in the database.
79
- *
80
- * @since 4.0.0
81
- *
82
- * @param array|null $options An optional options array.
83
- * @return void
84
- */
85
- public function update( $options = null ) {
86
- $optionsBefore = $this->options;
87
- parent::update( $options );
88
- $this->options = $optionsBefore;
89
-
90
- // First, we need to filter our options.
91
- $options = $this->filterOptions( $this->liteDefaults );
92
-
93
- // Refactor options.
94
- $refactored = $this->convertOptionsToValues( $options );
95
-
96
- $this->resetGroups();
97
-
98
- update_option( $this->optionsName . '_lite', wp_json_encode( $refactored ) );
99
-
100
- $this->init();
101
- }
102
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Lite/Utils/Options.php DELETED
@@ -1,107 +0,0 @@
1
- <?php
2
- namespace AIOSEO\Plugin\Lite\Utils;
3
-
4
- // Exit if accessed directly.
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- }
8
-
9
- use AIOSEO\Plugin\Common\Utils as CommonUtils;
10
-
11
- /**
12
- * Class that holds all options for AIOSEO.
13
- *
14
- * @since 4.0.0
15
- */
16
- class Options extends CommonUtils\Options {
17
- /**
18
- * Defaults options for Lite.
19
- *
20
- * @since 4.0.0
21
- *
22
- * @var array
23
- */
24
- private $liteDefaults = [
25
- // phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
26
- 'advanced' => [
27
- 'usageTracking' => [ 'type' => 'boolean', 'default' => false ]
28
- ]
29
- // phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
30
- ];
31
-
32
- /**
33
- * Class constructor
34
- *
35
- * @since 4.0.0
36
- */
37
- public function __construct( $optionsName = 'aioseo_options' ) {
38
- parent::__construct( $optionsName );
39
-
40
- $this->init();
41
- }
42
-
43
- /**
44
- * Initializes the options.
45
- *
46
- * @since 4.0.0
47
- *
48
- * @param boolean $resetKeys Whether or not to reset keys after init.
49
- * @return void
50
- */
51
- protected function init( $resetKeys = false ) {
52
- if ( $resetKeys ) {
53
- $originalGroupKey = $this->groupKey;
54
- $originalSubGroups = $this->subGroups;
55
- }
56
-
57
- parent::init();
58
-
59
- $dbOptions = json_decode( get_option( $this->optionsName . '_lite' ), true );
60
- if ( empty( $dbOptions ) ) {
61
- $dbOptions = [];
62
- }
63
-
64
- // Refactor options.
65
- $this->defaultsMerged = array_replace_recursive( $this->defaults, $this->liteDefaults );
66
-
67
- $options = array_replace_recursive(
68
- $this->options,
69
- $this->addValueToValuesArray( $this->options, $dbOptions )
70
- );
71
-
72
- $this->options = apply_filters( 'aioseo_get_options_lite', $options );
73
-
74
- if ( $resetKeys ) {
75
- $this->groupKey = $originalGroupKey;
76
- $this->subGroups = $originalSubGroups;
77
- }
78
- }
79
-
80
- /**
81
- * Updates the options in the database.
82
- *
83
- * @since 4.0.0
84
- *
85
- * @param array|null $options An optional options array.
86
- * @return void
87
- */
88
- public function update( $options = null ) {
89
- $optionsBefore = $this->options;
90
- parent::update( $options );
91
- $this->options = $optionsBefore;
92
-
93
- // First, we need to filter our options.
94
- $options = $this->filterOptions( $this->liteDefaults );
95
-
96
- // Refactor options.
97
- $refactored = $this->convertOptionsToValues( $options );
98
-
99
- $this->resetGroups();
100
-
101
- update_option( $this->optionsName . '_lite', wp_json_encode( $refactored ) );
102
-
103
- if ( ! $this->needsUpdate ) {
104
- $this->init();
105
- }
106
- }
107
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dist/Lite/assets/css/aioseo-admin-bar.css CHANGED
@@ -1,3 +1,3 @@
1
- /*! ! built on Wednesday, July 14th 2021, 4:06:18 pm */
2
- #wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{float:left;width:26px;height:30px;background-repeat:no-repeat;background-position:0 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iI2ZmZiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGFzcz0iYWlvc2VvLWdlYXIiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS45ODU0MiAxOS45NzA4QzE1LjUwMDIgMTkuOTcwOCAxOS45NzA4IDE1LjUwMDIgMTkuOTcwOCA5Ljk4NTQyQzE5Ljk3MDggNC40NzA2MyAxNS41MDAyIDAgOS45ODU0MiAwQzQuNDcwNjMgMCAwIDQuNDcwNjMgMCA5Ljk4NTQyQzAgMTUuNTAwMiA0LjQ3MDYzIDE5Ljk3MDggOS45ODU0MiAxOS45NzA4Wk04LjM5NTQxIDMuNjU0NjRDOC4yNjAxNiAzLjQ0ODUgOC4wMDk2IDMuMzUyMTEgNy43Nzk4NSAzLjQzMzI3QzcuNTE4MTYgMy41MjU3MiA3LjI2MjE4IDMuNjM0NDUgNy4wMTM0OSAzLjc1ODhDNi43OTUxOSAzLjg2Nzk2IDYuNjg1NjYgNC4xMTczMSA2LjczMzcyIDQuMzYwNDlMNi45MDQ5MyA1LjIyNjk0QzYuOTQ5IDUuNDQ5OTYgNi44NTggNS42NzYzIDYuNjg1MjIgNS44MjAwOUM2LjQxMjE2IDYuMDQ3MzQgNi4xNjAwNyA2LjMwNDI2IDUuOTM0MjEgNi41ODg2NEM1Ljc5MzgzIDYuNzY1MzkgNS41NzIzMyA2Ljg1OTA3IDUuMzUzNjEgNi44MTQ4OUw0LjUwNDI0IDYuNjQzM0M0LjI2NTY0IDYuNTk1MSA0LjAyMTU3IDYuNzA3ODggMy45MTU0NCA2LjkzMTIxQzMuODU1NDkgNy4wNTczOCAzLjc5ODg5IDcuMTg2MiAzLjc0NTgzIDcuMzE3NThDMy42OTI3NiA3LjQ0ODk2IDMuNjQzOTcgNy41ODEwNSAzLjU5OTM4IDcuNzEzNjlDMy41MjA0OCA3Ljk0ODQ3IDMuNjE1NzkgOC4yMDM5OCAzLjgxODM5IDguMzQxMzNMNC41Mzk1OCA4LjgzMDI3QzQuNzI1MjkgOC45NTYxNyA0LjgxNzc4IDkuMTgxOSA0Ljc5NTM0IDkuNDA4MjZDNC43NTkyNSA5Ljc3MjQ0IDQuNzYwNzIgMTAuMTM2IDQuNzk3NTYgMTAuNDkzNkM0LjgyMDg3IDEwLjcxOTggNC43MjkxNSAxMC45NDU5IDQuNTQzODggMTEuMDcyNEwzLjgyNDA4IDExLjU2NDJDMy42MjIwNSAxMS43MDIyIDMuNTI3NTkgMTEuOTU3OSAzLjYwNzEzIDEyLjE5MjNDMy42OTc3NCAxMi40NTkzIDMuODA0MyAxMi43MjA1IDMuOTI2MTUgMTIuOTc0M0M0LjAzMzEzIDEzLjE5NzEgNC4yNzc0OSAxMy4zMDg4IDQuNTE1ODEgMTMuMjU5OEw1LjM2NDk1IDEzLjA4NTFDNS41ODM1IDEzLjA0MDEgNS44MDUzMyAxMy4xMzMgNS45NDYyMyAxMy4zMDkzQzYuMTY4OTMgMTMuNTg3OSA2LjQyMDcxIDEzLjg0NTEgNi42OTk0IDE0LjA3NTZDNi44NzI2MSAxNC4yMTg4IDYuOTY0NDIgMTQuNDQ0OCA2LjkyMTEyIDE0LjY2OEw2Ljc1Mjk2IDE1LjUzNDhDNi43MDU3MiAxNS43NzgyIDYuODE2MjUgMTYuMDI3MyA3LjAzNTExIDE2LjEzNTZDNy4xNTg3NiAxNi4xOTY3IDcuMjg1IDE2LjI1NDUgNy40MTM3NSAxNi4zMDg2QzcuNTQyNTEgMTYuMzYyOCA3LjY3MTk2IDE2LjQxMjYgNy44MDE5NSAxNi40NTgxQzguMTgyMjQgMTYuNTkxMiA4LjcxNDQ5IDE2LjExNDcgOS4xMDggMTUuNzYyNUM5LjMwMjA1IDE1LjU4ODggOS40MjE3NCAxNS4zNDMgOS40MjMwMSAxNS4wNzk4QzkuNDIzMDEgMTUuMDc4NCA5LjQyMzAyIDE1LjA3NyA5LjQyMzAyIDE1LjA3NTZMOS40MjMwMSAxMy42MjYzQzkuNDIzMDEgMTMuNjEwOSA5LjQyMzYgMTMuNTk1NyA5LjQyNDc2IDEzLjU4MDZDOC4yNjI0OCAxMy4yOTcxIDcuMzk4MzggMTIuMjMwMSA3LjM5ODM4IDEwLjk1NzJWOS40MTgyM0M3LjM5ODM4IDkuMzAxMjUgNy40OTEzMSA5LjIwNjQyIDcuNjA1OTYgOS4yMDY0Mkg4LjMyNTg0VjcuNjkyMkM4LjMyNTg0IDcuNDgzMTIgOC40OTE5MyA3LjMxMzY0IDguNjk2ODMgNy4zMTM2NEM4LjkwMTcxIDcuMzEzNjQgOS4wNjc4MSA3LjQ4MzEyIDkuMDY3ODEgNy42OTIyVjkuMjA2NDJIMTEuMDE1NVY3LjY5MjJDMTEuMDE1NSA3LjQ4MzEyIDExLjE4MTYgNy4zMTM2NCAxMS4zODY1IDcuMzEzNjRDMTEuNTkxNCA3LjMxMzY0IDExLjc1NzUgNy40ODMxMiAxMS43NTc1IDcuNjkyMlY5LjIwNjQySDEyLjQ3NzNDMTIuNTkyIDkuMjA2NDIgMTIuNjg0OSA5LjMwMTI1IDEyLjY4NDkgOS40MTgyM1YxMC45NTcyQzEyLjY4NDkgMTIuMjcwNCAxMS43NjUzIDEzLjM2NDMgMTAuNTQ3NCAxMy42MDUxQzEwLjU0NzcgMTMuNjEyMSAxMC41NDc4IDEzLjYxOTIgMTAuNTQ3OCAxMy42MjYzTDEwLjU0NzggMTUuMDY5NEMxMC41NDc4IDE1LjMzNzcgMTAuNjcxMSAxNS41ODc5IDEwLjg3MSAxNS43NjIyQzExLjI3MTUgMTYuMTExNSAxMS44MTI5IDE2LjU4MzcgMTIuMTkxIDE2LjQ1MDJDMTIuNDUyNyAxNi4zNTc3IDEyLjcwODYgMTYuMjQ5IDEyLjk1NzMgMTYuMTI0NkMxMy4xNzU2IDE2LjAxNTUgMTMuMjg1MiAxNS43NjYxIDEzLjIzNzEgMTUuNTIyOUwxMy4wNjU5IDE0LjY1NjVDMTMuMDIxOCAxNC40MzM0IDEzLjExMjggMTQuMjA3MSAxMy4yODU2IDE0LjA2MzNDMTMuNTU4NyAxMy44MzYxIDEzLjgxMDcgMTMuNTc5MiAxNC4wMzY2IDEzLjI5NDhDMTQuMTc3IDEzLjExOCAxNC4zOTg1IDEzLjAyNDQgMTQuNjE3MiAxMy4wNjg1TDE1LjQ2NjYgMTMuMjQwMUMxNS43MDUyIDEzLjI4ODMgMTUuOTQ5MyAxMy4xNzU2IDE2LjA1NTQgMTIuOTUyMkMxNi4xMTUzIDEyLjgyNjEgMTYuMTcxOSAxMi42OTcyIDE2LjIyNSAxMi41NjU5QzE2LjI3ODEgMTIuNDM0NSAxNi4zMjY5IDEyLjMwMjQgMTYuMzcxNCAxMi4xNjk4QzE2LjQ1MDMgMTEuOTM1IDE2LjM1NSAxMS42Nzk1IDE2LjE1MjQgMTEuNTQyMUwxNS40MzEyIDExLjA1MzJDMTUuMjQ1NSAxMC45MjczIDE1LjE1MyAxMC43MDE1IDE1LjE3NTUgMTAuNDc1MkMxNS4yMTE2IDEwLjExMSAxNS4yMTAxIDkuNzQ3NDQgMTUuMTczMyA5LjM4OTg2QzE1LjE0OTkgOS4xNjM2MSAxNS4yNDE3IDguOTM3NTcgMTUuNDI2OSA4LjgxMUwxNi4xNDY3IDguMzE5MjdDMTYuMzQ4OCA4LjE4MTI2IDE2LjQ0MzIgNy45MjU1OCAxNi4zNjM3IDcuNjkxMTVDMTYuMjczMSA3LjQyNDExIDE2LjE2NjUgNy4xNjI5MiAxNi4wNDQ3IDYuOTA5MTVDMTUuOTM3NyA2LjY4NjM4IDE1LjY5MzMgNi41NzQ2MiAxNS40NTUgNi42MjM2NkwxNC42MDU5IDYuNzk4MzdDMTQuMzg3MyA2Ljg0MzM0IDE0LjE2NTUgNi43NTA0OCAxNC4wMjQ2IDYuNTc0MThDMTMuODAxOSA2LjI5NTU0IDEzLjU1MDEgNi4wMzgzMiAxMy4yNzE0IDUuODA3ODRDMTMuMDk4MiA1LjY2NDYgMTMuMDA2NCA1LjQzODU4IDEzLjA0OTcgNS4yMTU0TDEzLjIxNzkgNC4zNDg2OEMxMy4yNjUxIDQuMTA1MjEgMTMuMTU0NiAzLjg1NjE2IDEyLjkzNTcgMy43NDc4N0MxMi44MTIxIDMuNjg2NjkgMTIuNjg1OCAzLjYyODk1IDEyLjU1NzEgMy41NzQ4QzEyLjQyODMgMy41MjA2NSAxMi4yOTg5IDMuNDcwODYgMTIuMTY4OSAzLjQyNTM3QzExLjkzODggMy4zNDQ4NSAxMS42ODg0IDMuNDQyMTEgMTEuNTUzOCAzLjY0ODg0TDExLjA3NDYgNC4zODQ3NUMxMC45NTEzIDQuNTc0MjUgMTAuNzMgNC42Njg2MiAxMC41MDgyIDQuNjQ1NzNDMTAuMTUxMyA0LjYwODkgOS43OTUwMiA0LjYxMDM5IDkuNDQ0NTkgNC42NDc5OUM5LjIyMjg2IDQuNjcxNzcgOS4wMDEzNCA0LjU3ODE4IDguODc3MzEgNC4zODkxM0w4LjM5NTQxIDMuNjU0NjRaIiBmaWxsPSIjZmZmIiAvPjwvc3ZnPg==") !important}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a{background-color:#1DA867;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a span{font-weight:600}#wpadminbar #wp-admin-bar-aioseo-pro-license a{background-color:#DF2A4A;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-license a span{font-weight:600}#wpadminbar .aioseo-menu-notification-counter{display:inline-flex;vertical-align:top;box-sizing:border-box;margin:7px 0 0 5px;padding:0;min-width:18px;height:18px;border-radius:9px;background-color:#ca4a1f;color:#fff;font-size:11px;line-height:1.6;text-align:center;justify-content:center}#wpadminbar .aioseo-menu-notification-counter span{line-height:1;font-size:11px}#wpadminbar .aioseo-menu-notification-indicator{float:right;margin:10px 0 0;width:8px;height:8px;border-radius:50%;background-color:#ca4a1f;line-height:1.6;animation:aioseo-menu-notification-indicator-pulse 1.5s infinite}@keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0px rgba(202,74,31,0.5)}100%{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@media screen and (max-width: 782px){#wpadminbar #wp-admin-bar-aioseo-main{display:block;position:static}#wpadminbar #wp-admin-bar-aioseo-main .ab-item .text{display:none}#wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}}
3
 
1
+ /*! ! built on Thursday, September 9th 2021, 7:47:13 pm */
2
+ #wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{float:left;width:26px;height:30px;background-repeat:no-repeat;background-position:0 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iI2ZmZiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGFzcz0iYWlvc2VvLWdlYXIiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS45ODU0MiAxOS45NzA4QzE1LjUwMDIgMTkuOTcwOCAxOS45NzA4IDE1LjUwMDIgMTkuOTcwOCA5Ljk4NTQyQzE5Ljk3MDggNC40NzA2MyAxNS41MDAyIDAgOS45ODU0MiAwQzQuNDcwNjMgMCAwIDQuNDcwNjMgMCA5Ljk4NTQyQzAgMTUuNTAwMiA0LjQ3MDYzIDE5Ljk3MDggOS45ODU0MiAxOS45NzA4Wk04LjM5NTQxIDMuNjU0NjRDOC4yNjAxNiAzLjQ0ODUgOC4wMDk2IDMuMzUyMTEgNy43Nzk4NSAzLjQzMzI3QzcuNTE4MTYgMy41MjU3MiA3LjI2MjE4IDMuNjM0NDUgNy4wMTM0OSAzLjc1ODhDNi43OTUxOSAzLjg2Nzk2IDYuNjg1NjYgNC4xMTczMSA2LjczMzcyIDQuMzYwNDlMNi45MDQ5MyA1LjIyNjk0QzYuOTQ5IDUuNDQ5OTYgNi44NTggNS42NzYzIDYuNjg1MjIgNS44MjAwOUM2LjQxMjE2IDYuMDQ3MzQgNi4xNjAwNyA2LjMwNDI2IDUuOTM0MjEgNi41ODg2NEM1Ljc5MzgzIDYuNzY1MzkgNS41NzIzMyA2Ljg1OTA3IDUuMzUzNjEgNi44MTQ4OUw0LjUwNDI0IDYuNjQzM0M0LjI2NTY0IDYuNTk1MSA0LjAyMTU3IDYuNzA3ODggMy45MTU0NCA2LjkzMTIxQzMuODU1NDkgNy4wNTczOCAzLjc5ODg5IDcuMTg2MiAzLjc0NTgzIDcuMzE3NThDMy42OTI3NiA3LjQ0ODk2IDMuNjQzOTcgNy41ODEwNSAzLjU5OTM4IDcuNzEzNjlDMy41MjA0OCA3Ljk0ODQ3IDMuNjE1NzkgOC4yMDM5OCAzLjgxODM5IDguMzQxMzNMNC41Mzk1OCA4LjgzMDI3QzQuNzI1MjkgOC45NTYxNyA0LjgxNzc4IDkuMTgxOSA0Ljc5NTM0IDkuNDA4MjZDNC43NTkyNSA5Ljc3MjQ0IDQuNzYwNzIgMTAuMTM2IDQuNzk3NTYgMTAuNDkzNkM0LjgyMDg3IDEwLjcxOTggNC43MjkxNSAxMC45NDU5IDQuNTQzODggMTEuMDcyNEwzLjgyNDA4IDExLjU2NDJDMy42MjIwNSAxMS43MDIyIDMuNTI3NTkgMTEuOTU3OSAzLjYwNzEzIDEyLjE5MjNDMy42OTc3NCAxMi40NTkzIDMuODA0MyAxMi43MjA1IDMuOTI2MTUgMTIuOTc0M0M0LjAzMzEzIDEzLjE5NzEgNC4yNzc0OSAxMy4zMDg4IDQuNTE1ODEgMTMuMjU5OEw1LjM2NDk1IDEzLjA4NTFDNS41ODM1IDEzLjA0MDEgNS44MDUzMyAxMy4xMzMgNS45NDYyMyAxMy4zMDkzQzYuMTY4OTMgMTMuNTg3OSA2LjQyMDcxIDEzLjg0NTEgNi42OTk0IDE0LjA3NTZDNi44NzI2MSAxNC4yMTg4IDYuOTY0NDIgMTQuNDQ0OCA2LjkyMTEyIDE0LjY2OEw2Ljc1Mjk2IDE1LjUzNDhDNi43MDU3MiAxNS43NzgyIDYuODE2MjUgMTYuMDI3MyA3LjAzNTExIDE2LjEzNTZDNy4xNTg3NiAxNi4xOTY3IDcuMjg1IDE2LjI1NDUgNy40MTM3NSAxNi4zMDg2QzcuNTQyNTEgMTYuMzYyOCA3LjY3MTk2IDE2LjQxMjYgNy44MDE5NSAxNi40NTgxQzguMTgyMjQgMTYuNTkxMiA4LjcxNDQ5IDE2LjExNDcgOS4xMDggMTUuNzYyNUM5LjMwMjA1IDE1LjU4ODggOS40MjE3NCAxNS4zNDMgOS40MjMwMSAxNS4wNzk4QzkuNDIzMDEgMTUuMDc4NCA5LjQyMzAyIDE1LjA3NyA5LjQyMzAyIDE1LjA3NTZMOS40MjMwMSAxMy42MjYzQzkuNDIzMDEgMTMuNjEwOSA5LjQyMzYgMTMuNTk1NyA5LjQyNDc2IDEzLjU4MDZDOC4yNjI0OCAxMy4yOTcxIDcuMzk4MzggMTIuMjMwMSA3LjM5ODM4IDEwLjk1NzJWOS40MTgyM0M3LjM5ODM4IDkuMzAxMjUgNy40OTEzMSA5LjIwNjQyIDcuNjA1OTYgOS4yMDY0Mkg4LjMyNTg0VjcuNjkyMkM4LjMyNTg0IDcuNDgzMTIgOC40OTE5MyA3LjMxMzY0IDguNjk2ODMgNy4zMTM2NEM4LjkwMTcxIDcuMzEzNjQgOS4wNjc4MSA3LjQ4MzEyIDkuMDY3ODEgNy42OTIyVjkuMjA2NDJIMTEuMDE1NVY3LjY5MjJDMTEuMDE1NSA3LjQ4MzEyIDExLjE4MTYgNy4zMTM2NCAxMS4zODY1IDcuMzEzNjRDMTEuNTkxNCA3LjMxMzY0IDExLjc1NzUgNy40ODMxMiAxMS43NTc1IDcuNjkyMlY5LjIwNjQySDEyLjQ3NzNDMTIuNTkyIDkuMjA2NDIgMTIuNjg0OSA5LjMwMTI1IDEyLjY4NDkgOS40MTgyM1YxMC45NTcyQzEyLjY4NDkgMTIuMjcwNCAxMS43NjUzIDEzLjM2NDMgMTAuNTQ3NCAxMy42MDUxQzEwLjU0NzcgMTMuNjEyMSAxMC41NDc4IDEzLjYxOTIgMTAuNTQ3OCAxMy42MjYzTDEwLjU0NzggMTUuMDY5NEMxMC41NDc4IDE1LjMzNzcgMTAuNjcxMSAxNS41ODc5IDEwLjg3MSAxNS43NjIyQzExLjI3MTUgMTYuMTExNSAxMS44MTI5IDE2LjU4MzcgMTIuMTkxIDE2LjQ1MDJDMTIuNDUyNyAxNi4zNTc3IDEyLjcwODYgMTYuMjQ5IDEyLjk1NzMgMTYuMTI0NkMxMy4xNzU2IDE2LjAxNTUgMTMuMjg1MiAxNS43NjYxIDEzLjIzNzEgMTUuNTIyOUwxMy4wNjU5IDE0LjY1NjVDMTMuMDIxOCAxNC40MzM0IDEzLjExMjggMTQuMjA3MSAxMy4yODU2IDE0LjA2MzNDMTMuNTU4NyAxMy44MzYxIDEzLjgxMDcgMTMuNTc5MiAxNC4wMzY2IDEzLjI5NDhDMTQuMTc3IDEzLjExOCAxNC4zOTg1IDEzLjAyNDQgMTQuNjE3MiAxMy4wNjg1TDE1LjQ2NjYgMTMuMjQwMUMxNS43MDUyIDEzLjI4ODMgMTUuOTQ5MyAxMy4xNzU2IDE2LjA1NTQgMTIuOTUyMkMxNi4xMTUzIDEyLjgyNjEgMTYuMTcxOSAxMi42OTcyIDE2LjIyNSAxMi41NjU5QzE2LjI3ODEgMTIuNDM0NSAxNi4zMjY5IDEyLjMwMjQgMTYuMzcxNCAxMi4xNjk4QzE2LjQ1MDMgMTEuOTM1IDE2LjM1NSAxMS42Nzk1IDE2LjE1MjQgMTEuNTQyMUwxNS40MzEyIDExLjA1MzJDMTUuMjQ1NSAxMC45MjczIDE1LjE1MyAxMC43MDE1IDE1LjE3NTUgMTAuNDc1MkMxNS4yMTE2IDEwLjExMSAxNS4yMTAxIDkuNzQ3NDQgMTUuMTczMyA5LjM4OTg2QzE1LjE0OTkgOS4xNjM2MSAxNS4yNDE3IDguOTM3NTcgMTUuNDI2OSA4LjgxMUwxNi4xNDY3IDguMzE5MjdDMTYuMzQ4OCA4LjE4MTI2IDE2LjQ0MzIgNy45MjU1OCAxNi4zNjM3IDcuNjkxMTVDMTYuMjczMSA3LjQyNDExIDE2LjE2NjUgNy4xNjI5MiAxNi4wNDQ3IDYuOTA5MTVDMTUuOTM3NyA2LjY4NjM4IDE1LjY5MzMgNi41NzQ2MiAxNS40NTUgNi42MjM2NkwxNC42MDU5IDYuNzk4MzdDMTQuMzg3MyA2Ljg0MzM0IDE0LjE2NTUgNi43NTA0OCAxNC4wMjQ2IDYuNTc0MThDMTMuODAxOSA2LjI5NTU0IDEzLjU1MDEgNi4wMzgzMiAxMy4yNzE0IDUuODA3ODRDMTMuMDk4MiA1LjY2NDYgMTMuMDA2NCA1LjQzODU4IDEzLjA0OTcgNS4yMTU0TDEzLjIxNzkgNC4zNDg2OEMxMy4yNjUxIDQuMTA1MjEgMTMuMTU0NiAzLjg1NjE2IDEyLjkzNTcgMy43NDc4N0MxMi44MTIxIDMuNjg2NjkgMTIuNjg1OCAzLjYyODk1IDEyLjU1NzEgMy41NzQ4QzEyLjQyODMgMy41MjA2NSAxMi4yOTg5IDMuNDcwODYgMTIuMTY4OSAzLjQyNTM3QzExLjkzODggMy4zNDQ4NSAxMS42ODg0IDMuNDQyMTEgMTEuNTUzOCAzLjY0ODg0TDExLjA3NDYgNC4zODQ3NUMxMC45NTEzIDQuNTc0MjUgMTAuNzMgNC42Njg2MiAxMC41MDgyIDQuNjQ1NzNDMTAuMTUxMyA0LjYwODkgOS43OTUwMiA0LjYxMDM5IDkuNDQ0NTkgNC42NDc5OUM5LjIyMjg2IDQuNjcxNzcgOS4wMDEzNCA0LjU3ODE4IDguODc3MzEgNC4zODkxM0w4LjM5NTQxIDMuNjU0NjRaIiBmaWxsPSIjZmZmIiAvPjwvc3ZnPg==") !important}#wpadminbar #wp-admin-bar-aioseo-main.new-notifications>.ab-item{background:#2c3338;color:#72aee6}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a{background-color:#1DA867;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a span{font-weight:600}#wpadminbar #wp-admin-bar-aioseo-pro-license a{background-color:#DF2A4A;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-license a span{font-weight:600}#wpadminbar .aioseo-menu-notification-counter{display:inline-flex;vertical-align:top;box-sizing:border-box;margin:7px 0 0 5px;padding:0;min-width:18px;height:18px;border-radius:9px;background-color:#ca4a1f;color:#fff;font-size:11px;line-height:1.6;text-align:center;justify-content:center}#wpadminbar .aioseo-menu-notification-counter span{line-height:1;font-size:11px}#wpadminbar .aioseo-menu-notification-indicator{float:right;margin:10px 0 0;width:8px;height:8px;border-radius:50%;background-color:#ca4a1f;line-height:1.6;animation:aioseo-menu-notification-indicator-pulse 1.5s infinite}#toplevel_page_aioseo .aioseo-menu-notification-indicator{float:right;margin:6px 0 0;width:8px;height:8px;border-radius:50%;background-color:#ca4a1f;line-height:1.6;animation:aioseo-menu-notification-indicator-pulse 1.5s infinite}@keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0px rgba(202,74,31,0.5)}100%{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@media screen and (max-width: 782px){#wpadminbar #wp-admin-bar-aioseo-main{display:block;position:static}#wpadminbar #wp-admin-bar-aioseo-main .ab-item .text{display:none}#wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}}
3
 
dist/Lite/assets/css/aioseo-admin-bar.css.gz CHANGED
Binary file
dist/Lite/assets/css/app.css CHANGED
@@ -1 +1 @@
1
- #wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{float:left;width:26px;height:30px;background-repeat:no-repeat;background-position:0 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iI2ZmZiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGFzcz0iYWlvc2VvLWdlYXIiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS45ODUgMTkuOTdjNS41MTUgMCA5Ljk4Ni00LjQ3IDkuOTg2LTkuOTg1QzE5Ljk3IDQuNDcxIDE1LjUgMCA5Ljk4NSAwIDQuNDcxIDAgMCA0LjQ3IDAgOS45ODVzNC40NyA5Ljk4NiA5Ljk4NSA5Ljk4NnpNOC4zOTUgMy42NTZhLjUyOC41MjggMCAwMC0uNjE1LS4yMjIgNi43MTYgNi43MTYgMCAwMC0uNzY3LjMyNi41NDguNTQ4IDAgMDAtLjI4LjYwMWwuMTcyLjg2N2EuNjIxLjYyMSAwIDAxLS4yMi41OTMgNS4yMzcgNS4yMzcgMCAwMC0uNzUuNzY5LjU5Ni41OTYgMCAwMS0uNTgxLjIyNmwtLjg1LS4xNzJhLjUzLjUzIDAgMDAtLjU4OS4yODggNy4wNjQgNy4wNjQgMCAwMC0uMzE2Ljc4My41NS41NSAwIDAwLjIyLjYyN2wuNzIuNDlhLjYyLjYyIDAgMDEuMjU2LjU3N2MtLjAzNi4zNjQtLjAzNC43MjguMDAzIDEuMDg2YS42Mi42MiAwIDAxLS4yNTQuNTc4bC0uNzIuNDkyYS41NS41NSAwIDAwLS4yMTcuNjI4Yy4wOS4yNjcuMTk3LjUyOC4zMi43ODJhLjUzLjUzIDAgMDAuNTg5LjI4NmwuODQ5LS4xNzVhLjU5Ni41OTYgMCAwMS41ODEuMjI0Yy4yMjMuMjc5LjQ3NS41MzYuNzUzLjc2N2EuNjIuNjIgMCAwMS4yMjIuNTkybC0uMTY4Ljg2N2EuNTQ4LjU0OCAwIDAwLjI4Mi42IDYuODA4IDYuODA4IDAgMDAuNzY3LjMyM2MuMzguMTMzLjkxMi0uMzQzIDEuMzA2LS42OTVhLjkyNi45MjYgMCAwMC4zMTUtLjY4M3YtMS40NTRjMC0uMDE1IDAtLjAzLjAwMi0uMDQ1LTEuMTYzLS4yODQtMi4wMjctMS4zNS0yLjAyNy0yLjYyNHYtMS41NGEuMjEuMjEgMCAwMS4yMDgtLjIxMmguNzJWNy42OTJjMC0uMjA5LjE2Ni0uMzc4LjM3LS4zNzguMjA2IDAgLjM3Mi4xNy4zNzIuMzc4djEuNTE0aDEuOTQ3VjcuNjkyYzAtLjIwOS4xNjctLjM3OC4zNzEtLjM3OC4yMDUgMCAuMzcyLjE3LjM3Mi4zNzh2MS41MTRoLjcyYS4yMS4yMSAwIDAxLjIwNy4yMTJ2MS41NGMwIDEuMzEyLS45MiAyLjQwNi0yLjEzOCAyLjY0N3YxLjQ2NGMwIC4yNjkuMTI0LjUxOS4zMjQuNjkzLjQuMzUuOTQyLjgyMiAxLjMyLjY4OC4yNjItLjA5Mi41MTgtLjIwMS43NjYtLjMyNWEuNTQ4LjU0OCAwIDAwLjI4LS42MDJsLS4xNzEtLjg2N2EuNjIuNjIgMCAwMS4yMi0uNTkzYy4yNzMtLjIyNy41MjUtLjQ4NC43NS0uNzY4YS41OTYuNTk2IDAgMDEuNTgxLS4yMjZsLjg1LjE3MWEuNTMuNTMgMCAwMC41ODgtLjI4OCA3LjEzNSA3LjEzNSAwIDAwLjMxNi0uNzgyLjU1LjU1IDAgMDAtLjIxOS0uNjI4bC0uNzItLjQ4OWEuNjIuNjIgMCAwMS0uMjU3LS41NzggNS4zOTkgNS4zOTkgMCAwMC0uMDAyLTEuMDg1LjYyLjYyIDAgMDEuMjU0LS41NzlsLjcyLS40OTJhLjU1LjU1IDAgMDAuMjE3LS42MjggNy4wMiA3LjAyIDAgMDAtLjMyLS43ODIuNTMuNTMgMCAwMC0uNTg5LS4yODVsLS44NS4xNzRhLjU5Ni41OTYgMCAwMS0uNTgtLjIyNCA1LjIzNiA1LjIzNiAwIDAwLS43NTQtLjc2Ni42MjEuNjIxIDAgMDEtLjIyMS0uNTkzbC4xNjgtLjg2NmEuNTQ4LjU0OCAwIDAwLS4yODItLjYwMSA2Ljc4NiA2Ljc4NiAwIDAwLS43NjctLjMyMy41MjguNTI4IDAgMDAtLjYxNS4yMjRsLS40OC43MzZhLjU5OC41OTggMCAwMS0uNTY2LjI2IDUuMDggNS4wOCAwIDAwLTEuMDYzLjAwMy41OTcuNTk3IDAgMDEtLjU2OC0uMjU5bC0uNDgyLS43MzR6Ii8+PC9zdmc+")!important}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a{background-color:#1da867;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a span{font-weight:600}#wpadminbar #wp-admin-bar-aioseo-pro-license a{background-color:#df2a4a;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-license a span{font-weight:600}#wpadminbar .aioseo-menu-notification-counter{display:inline-flex;vertical-align:top;box-sizing:border-box;margin:7px 0 0 5px;padding:0;min-width:18px;height:18px;border-radius:9px;background-color:#ca4a1f;color:#fff;font-size:11px;line-height:1.6;text-align:center;justify-content:center}#wpadminbar .aioseo-menu-notification-counter span{line-height:1;font-size:11px}#wpadminbar .aioseo-menu-notification-indicator{float:right;margin:10px 0 0;width:8px;height:8px;border-radius:50%;background-color:#ca4a1f;line-height:1.6;-webkit-animation:aioseo-menu-notification-indicator-pulse 1.5s infinite;animation:aioseo-menu-notification-indicator-pulse 1.5s infinite}@-webkit-keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@media screen and (max-width:782px){#wpadminbar #wp-admin-bar-aioseo-main{display:block;position:static}#wpadminbar #wp-admin-bar-aioseo-main .ab-item .text{display:none}#wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}}.aioseo-plugin-row .plugin-update-tr p:first-child:before{content:"\f348"}.aioseo-plugin-row .plugin-update-tr p:not(:first-child){padding-left:20px}.aioseo-plugin-row .plugin-update-tr p:not(:first-child):before{content:" "}.aioseo-plugin-row .proupgrade a{color:#1da867;font-weight:600}body #most-recent-results{margin-top:0!important}body #wp-link .query-results{position:static}body #wp-link .query-results ul{max-height:200px;overflow:scroll}body #wp-link-wrap #link-selector{overflow:auto}@media (max-width:782px){body #wp-link-wrap{top:30%}body #wp-link .link-target label{line-height:30px}}.aioseo-menu-highlight{color:#fff}#toplevel_page_aioseo .aioseo-submenu-highlight{background-color:#1da867}#toplevel_page_aioseo .aioseo-submenu-highlight.red{background-color:#df2a4a}#toplevel_page_aioseo .aioseo-submenu-highlight a{color:#fff;font-weight:600}label[for=aioseo_contact_methods_header]{font-size:1.2em}#aioseo_contact_methods_header{display:none}.edit-post-meta-boxes-area #aioseo-settings h2.hndle{border-bottom:none}#aioseo-local-settings .inside,#aioseo-settings .inside{padding:0;margin-top:0}#aioseo-local-settings .aioseo-tab-content .aioseo-settings-row:last-of-type,#aioseo-settings .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}#aioseo-tabbed .handlediv{position:absolute;top:0;right:0}#aioseo-tabbed>.inside{min-height:40px}#aioseo-tabbed .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}body.block-editor-page #aioseo-settings .inside{border:1px solid #e8e8eb;border-top:none}body.block-editor-page .edit-post-sidebar .aioseo-app textarea{font-size:16px}#aioseo-post-settings-sidebar-button{display:flex;flex-direction:row;align-items:center;border-radius:3px;height:36px;min-width:36px;margin:-7px;padding:5px;font-weight:700;color:#fff}#aioseo-post-settings-sidebar-button #aioseo-post-score-disabled{color:#434960;margin-left:10px}#aioseo-post-settings-sidebar-button.score-green{color:#00aa63;border:1px solid #00aa63}#aioseo-post-settings-sidebar-button.score-green #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-orange{color:#f18200;border:1px solid #f18200}#aioseo-post-settings-sidebar-button.score-orange #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-none,#aioseo-post-settings-sidebar-button.score-red{color:#df2a4a;border:1px solid #df2a4a}#aioseo-post-settings-sidebar-button.score-none #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-red #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button svg{margin-right:10px;fill:currentColor}#aioseo-post-settings-sidebar-button svg *{fill:currentColor}#aioseo-post-settings-sidebar-button.score-disabled{color:#434960;border:1px solid #434960}#aioseo-post-settings-sidebar-button.score-disabled svg{margin-right:0;width:24px;height:24px}#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-disabled span{display:none}button[aria-label=AIOSEO],button[aria-label=AIOSEO]:hover{background:none!important;box-shadow:none!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-green,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-green{color:#fff;background-color:#00aa63}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-orange,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-orange{color:#fff;background-color:#f18200}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-red,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-red{color:#fff;background-color:#df2a4a}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled{color:#fff;background:#434960!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled{color:#fff!important}button[aria-label=AIOSEO].components-icon-button>div svg,button[aria-label=AIOSEO].components-icon-button>div svg *,button[aria-label=AIOSEO].is-toggled>div svg,button[aria-label=AIOSEO].is-toggled>div svg *,button[aria-label=AIOSEO]:hover.components-icon-button>div svg,button[aria-label=AIOSEO]:hover.components-icon-button>div svg *,button[aria-label=AIOSEO]:hover.is-toggled>div svg,button[aria-label=AIOSEO]:hover.is-toggled>div svg *{fill:#fff!important;stroke:transparent!important}button[aria-label=AIOSEO].components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO].is-toggled>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-toggled>div #aioseo-post-score-disabled{color:#fff!important}
1
+ #wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{float:left;width:26px;height:30px;background-repeat:no-repeat;background-position:0 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iI2ZmZiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGFzcz0iYWlvc2VvLWdlYXIiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS45ODUgMTkuOTdjNS41MTUgMCA5Ljk4Ni00LjQ3IDkuOTg2LTkuOTg1QzE5Ljk3IDQuNDcxIDE1LjUgMCA5Ljk4NSAwIDQuNDcxIDAgMCA0LjQ3IDAgOS45ODVzNC40NyA5Ljk4NiA5Ljk4NSA5Ljk4NnpNOC4zOTUgMy42NTZhLjUyOC41MjggMCAwMC0uNjE1LS4yMjIgNi43MTYgNi43MTYgMCAwMC0uNzY3LjMyNi41NDguNTQ4IDAgMDAtLjI4LjYwMWwuMTcyLjg2N2EuNjIxLjYyMSAwIDAxLS4yMi41OTMgNS4yMzcgNS4yMzcgMCAwMC0uNzUuNzY5LjU5Ni41OTYgMCAwMS0uNTgxLjIyNmwtLjg1LS4xNzJhLjUzLjUzIDAgMDAtLjU4OS4yODggNy4wNjQgNy4wNjQgMCAwMC0uMzE2Ljc4My41NS41NSAwIDAwLjIyLjYyN2wuNzIuNDlhLjYyLjYyIDAgMDEuMjU2LjU3N2MtLjAzNi4zNjQtLjAzNC43MjguMDAzIDEuMDg2YS42Mi42MiAwIDAxLS4yNTQuNTc4bC0uNzIuNDkyYS41NS41NSAwIDAwLS4yMTcuNjI4Yy4wOS4yNjcuMTk3LjUyOC4zMi43ODJhLjUzLjUzIDAgMDAuNTg5LjI4NmwuODQ5LS4xNzVhLjU5Ni41OTYgMCAwMS41ODEuMjI0Yy4yMjMuMjc5LjQ3NS41MzYuNzUzLjc2N2EuNjIuNjIgMCAwMS4yMjIuNTkybC0uMTY4Ljg2N2EuNTQ4LjU0OCAwIDAwLjI4Mi42IDYuODA4IDYuODA4IDAgMDAuNzY3LjMyM2MuMzguMTMzLjkxMi0uMzQzIDEuMzA2LS42OTVhLjkyNi45MjYgMCAwMC4zMTUtLjY4M3YtMS40NTRjMC0uMDE1IDAtLjAzLjAwMi0uMDQ1LTEuMTYzLS4yODQtMi4wMjctMS4zNS0yLjAyNy0yLjYyNHYtMS41NGEuMjEuMjEgMCAwMS4yMDgtLjIxMmguNzJWNy42OTJjMC0uMjA5LjE2Ni0uMzc4LjM3LS4zNzguMjA2IDAgLjM3Mi4xNy4zNzIuMzc4djEuNTE0aDEuOTQ3VjcuNjkyYzAtLjIwOS4xNjctLjM3OC4zNzEtLjM3OC4yMDUgMCAuMzcyLjE3LjM3Mi4zNzh2MS41MTRoLjcyYS4yMS4yMSAwIDAxLjIwNy4yMTJ2MS41NGMwIDEuMzEyLS45MiAyLjQwNi0yLjEzOCAyLjY0N3YxLjQ2NGMwIC4yNjkuMTI0LjUxOS4zMjQuNjkzLjQuMzUuOTQyLjgyMiAxLjMyLjY4OC4yNjItLjA5Mi41MTgtLjIwMS43NjYtLjMyNWEuNTQ4LjU0OCAwIDAwLjI4LS42MDJsLS4xNzEtLjg2N2EuNjIuNjIgMCAwMS4yMi0uNTkzYy4yNzMtLjIyNy41MjUtLjQ4NC43NS0uNzY4YS41OTYuNTk2IDAgMDEuNTgxLS4yMjZsLjg1LjE3MWEuNTMuNTMgMCAwMC41ODgtLjI4OCA3LjEzNSA3LjEzNSAwIDAwLjMxNi0uNzgyLjU1LjU1IDAgMDAtLjIxOS0uNjI4bC0uNzItLjQ4OWEuNjIuNjIgMCAwMS0uMjU3LS41NzggNS4zOTkgNS4zOTkgMCAwMC0uMDAyLTEuMDg1LjYyLjYyIDAgMDEuMjU0LS41NzlsLjcyLS40OTJhLjU1LjU1IDAgMDAuMjE3LS42MjggNy4wMiA3LjAyIDAgMDAtLjMyLS43ODIuNTMuNTMgMCAwMC0uNTg5LS4yODVsLS44NS4xNzRhLjU5Ni41OTYgMCAwMS0uNTgtLjIyNCA1LjIzNiA1LjIzNiAwIDAwLS43NTQtLjc2Ni42MjEuNjIxIDAgMDEtLjIyMS0uNTkzbC4xNjgtLjg2NmEuNTQ4LjU0OCAwIDAwLS4yODItLjYwMSA2Ljc4NiA2Ljc4NiAwIDAwLS43NjctLjMyMy41MjguNTI4IDAgMDAtLjYxNS4yMjRsLS40OC43MzZhLjU5OC41OTggMCAwMS0uNTY2LjI2IDUuMDggNS4wOCAwIDAwLTEuMDYzLjAwMy41OTcuNTk3IDAgMDEtLjU2OC0uMjU5bC0uNDgyLS43MzR6Ii8+PC9zdmc+")!important}#wpadminbar #wp-admin-bar-aioseo-main.new-notifications>.ab-item{background:#2c3338;color:#72aee6}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a{background-color:#1da867;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a span{font-weight:600}#wpadminbar #wp-admin-bar-aioseo-pro-license a{background-color:#df2a4a;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-license a span{font-weight:600}#wpadminbar .aioseo-menu-notification-counter{display:inline-flex;vertical-align:top;box-sizing:border-box;margin:7px 0 0 5px;padding:0;min-width:18px;height:18px;border-radius:9px;background-color:#ca4a1f;color:#fff;font-size:11px;line-height:1.6;text-align:center;justify-content:center}#wpadminbar .aioseo-menu-notification-counter span{line-height:1;font-size:11px}#wpadminbar .aioseo-menu-notification-indicator{margin:10px 0 0}#toplevel_page_aioseo .aioseo-menu-notification-indicator,#wpadminbar .aioseo-menu-notification-indicator{float:right;width:8px;height:8px;border-radius:50%;background-color:#ca4a1f;line-height:1.6;-webkit-animation:aioseo-menu-notification-indicator-pulse 1.5s infinite;animation:aioseo-menu-notification-indicator-pulse 1.5s infinite}#toplevel_page_aioseo .aioseo-menu-notification-indicator{margin:6px 0 0}@-webkit-keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@media screen and (max-width:782px){#wpadminbar #wp-admin-bar-aioseo-main{display:block;position:static}#wpadminbar #wp-admin-bar-aioseo-main .ab-item .text{display:none}#wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}}.aioseo-plugin-row .plugin-update-tr p:first-child:before{content:"\f348"}.aioseo-plugin-row .plugin-update-tr p:not(:first-child){padding-left:20px}.aioseo-plugin-row .plugin-update-tr p:not(:first-child):before{content:" "}.aioseo-plugin-row .proupgrade a{color:#1da867;font-weight:600}body #most-recent-results{margin-top:0!important}body #wp-link .query-results{position:static}body #wp-link .query-results ul{max-height:200px;overflow:scroll}body #wp-link-wrap #link-selector{overflow:auto}@media (max-width:782px){body #wp-link-wrap{top:30%}body #wp-link .link-target label{line-height:30px}}.aioseo-menu-highlight{color:#fff}#toplevel_page_aioseo .aioseo-submenu-highlight{background-color:#1da867}#toplevel_page_aioseo .aioseo-submenu-highlight.red{background-color:#df2a4a}#toplevel_page_aioseo .aioseo-submenu-highlight a{color:#fff;font-weight:600}label[for=aioseo_contact_methods_header]{font-size:1.2em}#aioseo_contact_methods_header{display:none}.edit-post-meta-boxes-area #aioseo-settings h2.hndle{border-bottom:none}#aioseo-local-settings .inside,#aioseo-settings .inside{padding:0;margin-top:0}#aioseo-local-settings .aioseo-tab-content .aioseo-settings-row:last-of-type,#aioseo-settings .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}#aioseo-tabbed .handlediv{position:absolute;top:0;right:0}#aioseo-tabbed>.inside{min-height:40px}#aioseo-tabbed .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}body.block-editor-page #aioseo-settings .inside{border:1px solid #e8e8eb;border-top:none}body.block-editor-page .edit-post-sidebar .aioseo-app textarea{font-size:16px}#aioseo-post-settings-sidebar-button{display:flex;flex-direction:row;align-items:center;border-radius:3px;height:36px;min-width:36px;margin:-7px;padding:5px;font-weight:700;color:#fff}#aioseo-post-settings-sidebar-button #aioseo-post-score-disabled{color:#434960;margin-left:10px}#aioseo-post-settings-sidebar-button.score-green{color:#00aa63;border:1px solid #00aa63}#aioseo-post-settings-sidebar-button.score-green #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-orange{color:#f18200;border:1px solid #f18200}#aioseo-post-settings-sidebar-button.score-orange #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-none,#aioseo-post-settings-sidebar-button.score-red{color:#df2a4a;border:1px solid #df2a4a}#aioseo-post-settings-sidebar-button.score-none #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-red #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button svg{margin-right:10px;fill:currentColor}#aioseo-post-settings-sidebar-button svg *{fill:currentColor}#aioseo-post-settings-sidebar-button.score-disabled{color:#434960;border:1px solid #434960}#aioseo-post-settings-sidebar-button.score-disabled svg{margin-right:0;width:24px;height:24px}#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-disabled span{display:none}button[aria-label=AIOSEO],button[aria-label=AIOSEO]:hover{background:none!important;box-shadow:none!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-green,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-green{color:#fff;background-color:#00aa63}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-orange,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-orange{color:#fff;background-color:#f18200}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-red,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-red{color:#fff;background-color:#df2a4a}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled{color:#fff;background:#434960!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled{color:#fff!important}button[aria-label=AIOSEO].components-icon-button>div svg,button[aria-label=AIOSEO].components-icon-button>div svg *,button[aria-label=AIOSEO].is-toggled>div svg,button[aria-label=AIOSEO].is-toggled>div svg *,button[aria-label=AIOSEO]:hover.components-icon-button>div svg,button[aria-label=AIOSEO]:hover.components-icon-button>div svg *,button[aria-label=AIOSEO]:hover.is-toggled>div svg,button[aria-label=AIOSEO]:hover.is-toggled>div svg *{fill:#fff!important;stroke:transparent!important}button[aria-label=AIOSEO].components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO].is-toggled>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-toggled>div #aioseo-post-score-disabled{color:#fff!important}
dist/Lite/assets/css/app.rtl.css CHANGED
@@ -1 +1 @@
1
- #wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{float:right;width:26px;height:30px;background-repeat:no-repeat;background-position:100% 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iI2ZmZiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGFzcz0iYWlvc2VvLWdlYXIiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS45ODUgMTkuOTdjNS41MTUgMCA5Ljk4Ni00LjQ3IDkuOTg2LTkuOTg1QzE5Ljk3IDQuNDcxIDE1LjUgMCA5Ljk4NSAwIDQuNDcxIDAgMCA0LjQ3IDAgOS45ODVzNC40NyA5Ljk4NiA5Ljk4NSA5Ljk4NnpNOC4zOTUgMy42NTZhLjUyOC41MjggMCAwMC0uNjE1LS4yMjIgNi43MTYgNi43MTYgMCAwMC0uNzY3LjMyNi41NDguNTQ4IDAgMDAtLjI4LjYwMWwuMTcyLjg2N2EuNjIxLjYyMSAwIDAxLS4yMi41OTMgNS4yMzcgNS4yMzcgMCAwMC0uNzUuNzY5LjU5Ni41OTYgMCAwMS0uNTgxLjIyNmwtLjg1LS4xNzJhLjUzLjUzIDAgMDAtLjU4OS4yODggNy4wNjQgNy4wNjQgMCAwMC0uMzE2Ljc4My41NS41NSAwIDAwLjIyLjYyN2wuNzIuNDlhLjYyLjYyIDAgMDEuMjU2LjU3N2MtLjAzNi4zNjQtLjAzNC43MjguMDAzIDEuMDg2YS42Mi42MiAwIDAxLS4yNTQuNTc4bC0uNzIuNDkyYS41NS41NSAwIDAwLS4yMTcuNjI4Yy4wOS4yNjcuMTk3LjUyOC4zMi43ODJhLjUzLjUzIDAgMDAuNTg5LjI4NmwuODQ5LS4xNzVhLjU5Ni41OTYgMCAwMS41ODEuMjI0Yy4yMjMuMjc5LjQ3NS41MzYuNzUzLjc2N2EuNjIuNjIgMCAwMS4yMjIuNTkybC0uMTY4Ljg2N2EuNTQ4LjU0OCAwIDAwLjI4Mi42IDYuODA4IDYuODA4IDAgMDAuNzY3LjMyM2MuMzguMTMzLjkxMi0uMzQzIDEuMzA2LS42OTVhLjkyNi45MjYgMCAwMC4zMTUtLjY4M3YtMS40NTRjMC0uMDE1IDAtLjAzLjAwMi0uMDQ1LTEuMTYzLS4yODQtMi4wMjctMS4zNS0yLjAyNy0yLjYyNHYtMS41NGEuMjEuMjEgMCAwMS4yMDgtLjIxMmguNzJWNy42OTJjMC0uMjA5LjE2Ni0uMzc4LjM3LS4zNzguMjA2IDAgLjM3Mi4xNy4zNzIuMzc4djEuNTE0aDEuOTQ3VjcuNjkyYzAtLjIwOS4xNjctLjM3OC4zNzEtLjM3OC4yMDUgMCAuMzcyLjE3LjM3Mi4zNzh2MS41MTRoLjcyYS4yMS4yMSAwIDAxLjIwNy4yMTJ2MS41NGMwIDEuMzEyLS45MiAyLjQwNi0yLjEzOCAyLjY0N3YxLjQ2NGMwIC4yNjkuMTI0LjUxOS4zMjQuNjkzLjQuMzUuOTQyLjgyMiAxLjMyLjY4OC4yNjItLjA5Mi41MTgtLjIwMS43NjYtLjMyNWEuNTQ4LjU0OCAwIDAwLjI4LS42MDJsLS4xNzEtLjg2N2EuNjIuNjIgMCAwMS4yMi0uNTkzYy4yNzMtLjIyNy41MjUtLjQ4NC43NS0uNzY4YS41OTYuNTk2IDAgMDEuNTgxLS4yMjZsLjg1LjE3MWEuNTMuNTMgMCAwMC41ODgtLjI4OCA3LjEzNSA3LjEzNSAwIDAwLjMxNi0uNzgyLjU1LjU1IDAgMDAtLjIxOS0uNjI4bC0uNzItLjQ4OWEuNjIuNjIgMCAwMS0uMjU3LS41NzggNS4zOTkgNS4zOTkgMCAwMC0uMDAyLTEuMDg1LjYyLjYyIDAgMDEuMjU0LS41NzlsLjcyLS40OTJhLjU1LjU1IDAgMDAuMjE3LS42MjggNy4wMiA3LjAyIDAgMDAtLjMyLS43ODIuNTMuNTMgMCAwMC0uNTg5LS4yODVsLS44NS4xNzRhLjU5Ni41OTYgMCAwMS0uNTgtLjIyNCA1LjIzNiA1LjIzNiAwIDAwLS43NTQtLjc2Ni42MjEuNjIxIDAgMDEtLjIyMS0uNTkzbC4xNjgtLjg2NmEuNTQ4LjU0OCAwIDAwLS4yODItLjYwMSA2Ljc4NiA2Ljc4NiAwIDAwLS43NjctLjMyMy41MjguNTI4IDAgMDAtLjYxNS4yMjRsLS40OC43MzZhLjU5OC41OTggMCAwMS0uNTY2LjI2IDUuMDggNS4wOCAwIDAwLTEuMDYzLjAwMy41OTcuNTk3IDAgMDEtLjU2OC0uMjU5bC0uNDgyLS43MzR6Ii8+PC9zdmc+")!important}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a{background-color:#1da867;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a span{font-weight:600}#wpadminbar #wp-admin-bar-aioseo-pro-license a{background-color:#df2a4a;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-license a span{font-weight:600}#wpadminbar .aioseo-menu-notification-counter{display:inline-flex;vertical-align:top;box-sizing:border-box;margin:7px 5px 0 0;padding:0;min-width:18px;height:18px;border-radius:9px;background-color:#ca4a1f;color:#fff;font-size:11px;line-height:1.6;text-align:center;justify-content:center}#wpadminbar .aioseo-menu-notification-counter span{line-height:1;font-size:11px}#wpadminbar .aioseo-menu-notification-indicator{float:left;margin:10px 0 0;width:8px;height:8px;border-radius:50%;background-color:#ca4a1f;line-height:1.6;-webkit-animation:aioseo-menu-notification-indicator-pulse 1.5s infinite;animation:aioseo-menu-notification-indicator-pulse 1.5s infinite}@-webkit-keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@media screen and (max-width:782px){#wpadminbar #wp-admin-bar-aioseo-main{display:block;position:static}#wpadminbar #wp-admin-bar-aioseo-main .ab-item .text{display:none}#wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}}.aioseo-plugin-row .plugin-update-tr p:first-child:before{content:"\f348"}.aioseo-plugin-row .plugin-update-tr p:not(:first-child){padding-right:20px}.aioseo-plugin-row .plugin-update-tr p:not(:first-child):before{content:" "}.aioseo-plugin-row .proupgrade a{color:#1da867;font-weight:600}body #most-recent-results{margin-top:0!important}body #wp-link .query-results{position:static}body #wp-link .query-results ul{max-height:200px;overflow:scroll}body #wp-link-wrap #link-selector{overflow:auto}@media (max-width:782px){body #wp-link-wrap{top:30%}body #wp-link .link-target label{line-height:30px}}.aioseo-menu-highlight{color:#fff}#toplevel_page_aioseo .aioseo-submenu-highlight{background-color:#1da867}#toplevel_page_aioseo .aioseo-submenu-highlight.red{background-color:#df2a4a}#toplevel_page_aioseo .aioseo-submenu-highlight a{color:#fff;font-weight:600}label[for=aioseo_contact_methods_header]{font-size:1.2em}#aioseo_contact_methods_header{display:none}.edit-post-meta-boxes-area #aioseo-settings h2.hndle{border-bottom:none}#aioseo-local-settings .inside,#aioseo-settings .inside{padding:0;margin-top:0}#aioseo-local-settings .aioseo-tab-content .aioseo-settings-row:last-of-type,#aioseo-settings .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}#aioseo-tabbed .handlediv{position:absolute;top:0;left:0}#aioseo-tabbed>.inside{min-height:40px}#aioseo-tabbed .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}body.block-editor-page #aioseo-settings .inside{border:1px solid #e8e8eb;border-top:none}body.block-editor-page .edit-post-sidebar .aioseo-app textarea{font-size:16px}#aioseo-post-settings-sidebar-button{display:flex;flex-direction:row;align-items:center;border-radius:3px;height:36px;min-width:36px;margin:-7px;padding:5px;font-weight:700;color:#fff}#aioseo-post-settings-sidebar-button #aioseo-post-score-disabled{color:#434960;margin-right:10px}#aioseo-post-settings-sidebar-button.score-green{color:#00aa63;border:1px solid #00aa63}#aioseo-post-settings-sidebar-button.score-green #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-orange{color:#f18200;border:1px solid #f18200}#aioseo-post-settings-sidebar-button.score-orange #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-none,#aioseo-post-settings-sidebar-button.score-red{color:#df2a4a;border:1px solid #df2a4a}#aioseo-post-settings-sidebar-button.score-none #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-red #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button svg{margin-left:10px;fill:currentColor}#aioseo-post-settings-sidebar-button svg *{fill:currentColor}#aioseo-post-settings-sidebar-button.score-disabled{color:#434960;border:1px solid #434960}#aioseo-post-settings-sidebar-button.score-disabled svg{margin-left:0;width:24px;height:24px}#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-disabled span{display:none}button[aria-label=AIOSEO],button[aria-label=AIOSEO]:hover{background:none!important;box-shadow:none!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-green,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-green{color:#fff;background-color:#00aa63}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-orange,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-orange{color:#fff;background-color:#f18200}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-red,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-red{color:#fff;background-color:#df2a4a}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled{color:#fff;background:#434960!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled{color:#fff!important}button[aria-label=AIOSEO].components-icon-button>div svg,button[aria-label=AIOSEO].components-icon-button>div svg *,button[aria-label=AIOSEO].is-toggled>div svg,button[aria-label=AIOSEO].is-toggled>div svg *,button[aria-label=AIOSEO]:hover.components-icon-button>div svg,button[aria-label=AIOSEO]:hover.components-icon-button>div svg *,button[aria-label=AIOSEO]:hover.is-toggled>div svg,button[aria-label=AIOSEO]:hover.is-toggled>div svg *{fill:#fff!important;stroke:transparent!important}button[aria-label=AIOSEO].components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO].is-toggled>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-toggled>div #aioseo-post-score-disabled{color:#fff!important}
1
+ #wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{float:right;width:26px;height:30px;background-repeat:no-repeat;background-position:100% 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iI2ZmZiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGFzcz0iYWlvc2VvLWdlYXIiPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOS45ODUgMTkuOTdjNS41MTUgMCA5Ljk4Ni00LjQ3IDkuOTg2LTkuOTg1QzE5Ljk3IDQuNDcxIDE1LjUgMCA5Ljk4NSAwIDQuNDcxIDAgMCA0LjQ3IDAgOS45ODVzNC40NyA5Ljk4NiA5Ljk4NSA5Ljk4NnpNOC4zOTUgMy42NTZhLjUyOC41MjggMCAwMC0uNjE1LS4yMjIgNi43MTYgNi43MTYgMCAwMC0uNzY3LjMyNi41NDguNTQ4IDAgMDAtLjI4LjYwMWwuMTcyLjg2N2EuNjIxLjYyMSAwIDAxLS4yMi41OTMgNS4yMzcgNS4yMzcgMCAwMC0uNzUuNzY5LjU5Ni41OTYgMCAwMS0uNTgxLjIyNmwtLjg1LS4xNzJhLjUzLjUzIDAgMDAtLjU4OS4yODggNy4wNjQgNy4wNjQgMCAwMC0uMzE2Ljc4My41NS41NSAwIDAwLjIyLjYyN2wuNzIuNDlhLjYyLjYyIDAgMDEuMjU2LjU3N2MtLjAzNi4zNjQtLjAzNC43MjguMDAzIDEuMDg2YS42Mi42MiAwIDAxLS4yNTQuNTc4bC0uNzIuNDkyYS41NS41NSAwIDAwLS4yMTcuNjI4Yy4wOS4yNjcuMTk3LjUyOC4zMi43ODJhLjUzLjUzIDAgMDAuNTg5LjI4NmwuODQ5LS4xNzVhLjU5Ni41OTYgMCAwMS41ODEuMjI0Yy4yMjMuMjc5LjQ3NS41MzYuNzUzLjc2N2EuNjIuNjIgMCAwMS4yMjIuNTkybC0uMTY4Ljg2N2EuNTQ4LjU0OCAwIDAwLjI4Mi42IDYuODA4IDYuODA4IDAgMDAuNzY3LjMyM2MuMzguMTMzLjkxMi0uMzQzIDEuMzA2LS42OTVhLjkyNi45MjYgMCAwMC4zMTUtLjY4M3YtMS40NTRjMC0uMDE1IDAtLjAzLjAwMi0uMDQ1LTEuMTYzLS4yODQtMi4wMjctMS4zNS0yLjAyNy0yLjYyNHYtMS41NGEuMjEuMjEgMCAwMS4yMDgtLjIxMmguNzJWNy42OTJjMC0uMjA5LjE2Ni0uMzc4LjM3LS4zNzguMjA2IDAgLjM3Mi4xNy4zNzIuMzc4djEuNTE0aDEuOTQ3VjcuNjkyYzAtLjIwOS4xNjctLjM3OC4zNzEtLjM3OC4yMDUgMCAuMzcyLjE3LjM3Mi4zNzh2MS41MTRoLjcyYS4yMS4yMSAwIDAxLjIwNy4yMTJ2MS41NGMwIDEuMzEyLS45MiAyLjQwNi0yLjEzOCAyLjY0N3YxLjQ2NGMwIC4yNjkuMTI0LjUxOS4zMjQuNjkzLjQuMzUuOTQyLjgyMiAxLjMyLjY4OC4yNjItLjA5Mi41MTgtLjIwMS43NjYtLjMyNWEuNTQ4LjU0OCAwIDAwLjI4LS42MDJsLS4xNzEtLjg2N2EuNjIuNjIgMCAwMS4yMi0uNTkzYy4yNzMtLjIyNy41MjUtLjQ4NC43NS0uNzY4YS41OTYuNTk2IDAgMDEuNTgxLS4yMjZsLjg1LjE3MWEuNTMuNTMgMCAwMC41ODgtLjI4OCA3LjEzNSA3LjEzNSAwIDAwLjMxNi0uNzgyLjU1LjU1IDAgMDAtLjIxOS0uNjI4bC0uNzItLjQ4OWEuNjIuNjIgMCAwMS0uMjU3LS41NzggNS4zOTkgNS4zOTkgMCAwMC0uMDAyLTEuMDg1LjYyLjYyIDAgMDEuMjU0LS41NzlsLjcyLS40OTJhLjU1LjU1IDAgMDAuMjE3LS42MjggNy4wMiA3LjAyIDAgMDAtLjMyLS43ODIuNTMuNTMgMCAwMC0uNTg5LS4yODVsLS44NS4xNzRhLjU5Ni41OTYgMCAwMS0uNTgtLjIyNCA1LjIzNiA1LjIzNiAwIDAwLS43NTQtLjc2Ni42MjEuNjIxIDAgMDEtLjIyMS0uNTkzbC4xNjgtLjg2NmEuNTQ4LjU0OCAwIDAwLS4yODItLjYwMSA2Ljc4NiA2Ljc4NiAwIDAwLS43NjctLjMyMy41MjguNTI4IDAgMDAtLjYxNS4yMjRsLS40OC43MzZhLjU5OC41OTggMCAwMS0uNTY2LjI2IDUuMDggNS4wOCAwIDAwLTEuMDYzLjAwMy41OTcuNTk3IDAgMDEtLjU2OC0uMjU5bC0uNDgyLS43MzR6Ii8+PC9zdmc+")!important}#wpadminbar #wp-admin-bar-aioseo-main.new-notifications>.ab-item{background:#2c3338;color:#72aee6}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a{background-color:#1da867;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-upgrade a span{font-weight:600}#wpadminbar #wp-admin-bar-aioseo-pro-license a{background-color:#df2a4a;padding-bottom:5px}#wpadminbar #wp-admin-bar-aioseo-pro-license a span{font-weight:600}#wpadminbar .aioseo-menu-notification-counter{display:inline-flex;vertical-align:top;box-sizing:border-box;margin:7px 5px 0 0;padding:0;min-width:18px;height:18px;border-radius:9px;background-color:#ca4a1f;color:#fff;font-size:11px;line-height:1.6;text-align:center;justify-content:center}#wpadminbar .aioseo-menu-notification-counter span{line-height:1;font-size:11px}#wpadminbar .aioseo-menu-notification-indicator{margin:10px 0 0}#toplevel_page_aioseo .aioseo-menu-notification-indicator,#wpadminbar .aioseo-menu-notification-indicator{float:left;width:8px;height:8px;border-radius:50%;background-color:#ca4a1f;line-height:1.6;-webkit-animation:aioseo-menu-notification-indicator-pulse 1.5s infinite;animation:aioseo-menu-notification-indicator-pulse 1.5s infinite}#toplevel_page_aioseo .aioseo-menu-notification-indicator{margin:6px 0 0}@-webkit-keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@keyframes aioseo-menu-notification-indicator-pulse{0%{box-shadow:0 0 0 0 rgba(202,74,31,.5)}to{box-shadow:0 0 0 10px rgba(202,74,31,0)}}@media screen and (max-width:782px){#wpadminbar #wp-admin-bar-aioseo-main{display:block;position:static}#wpadminbar #wp-admin-bar-aioseo-main .ab-item .text{display:none}#wpadminbar #wp-admin-bar-aioseo-main .aioseo-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}}.aioseo-plugin-row .plugin-update-tr p:first-child:before{content:"\f348"}.aioseo-plugin-row .plugin-update-tr p:not(:first-child){padding-right:20px}.aioseo-plugin-row .plugin-update-tr p:not(:first-child):before{content:" "}.aioseo-plugin-row .proupgrade a{color:#1da867;font-weight:600}body #most-recent-results{margin-top:0!important}body #wp-link .query-results{position:static}body #wp-link .query-results ul{max-height:200px;overflow:scroll}body #wp-link-wrap #link-selector{overflow:auto}@media (max-width:782px){body #wp-link-wrap{top:30%}body #wp-link .link-target label{line-height:30px}}.aioseo-menu-highlight{color:#fff}#toplevel_page_aioseo .aioseo-submenu-highlight{background-color:#1da867}#toplevel_page_aioseo .aioseo-submenu-highlight.red{background-color:#df2a4a}#toplevel_page_aioseo .aioseo-submenu-highlight a{color:#fff;font-weight:600}label[for=aioseo_contact_methods_header]{font-size:1.2em}#aioseo_contact_methods_header{display:none}.edit-post-meta-boxes-area #aioseo-settings h2.hndle{border-bottom:none}#aioseo-local-settings .inside,#aioseo-settings .inside{padding:0;margin-top:0}#aioseo-local-settings .aioseo-tab-content .aioseo-settings-row:last-of-type,#aioseo-settings .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}#aioseo-tabbed .handlediv{position:absolute;top:0;left:0}#aioseo-tabbed>.inside{min-height:40px}#aioseo-tabbed .aioseo-tab-content .aioseo-settings-row:last-of-type{border-bottom:0;margin-bottom:0;padding-bottom:0}body.block-editor-page #aioseo-settings .inside{border:1px solid #e8e8eb;border-top:none}body.block-editor-page .edit-post-sidebar .aioseo-app textarea{font-size:16px}#aioseo-post-settings-sidebar-button{display:flex;flex-direction:row;align-items:center;border-radius:3px;height:36px;min-width:36px;margin:-7px;padding:5px;font-weight:700;color:#fff}#aioseo-post-settings-sidebar-button #aioseo-post-score-disabled{color:#434960;margin-right:10px}#aioseo-post-settings-sidebar-button.score-green{color:#00aa63;border:1px solid #00aa63}#aioseo-post-settings-sidebar-button.score-green #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-orange{color:#f18200;border:1px solid #f18200}#aioseo-post-settings-sidebar-button.score-orange #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button.score-none,#aioseo-post-settings-sidebar-button.score-red{color:#df2a4a;border:1px solid #df2a4a}#aioseo-post-settings-sidebar-button.score-none #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-red #aioseo-post-score-disabled{display:none}#aioseo-post-settings-sidebar-button svg{margin-left:10px;fill:currentColor}#aioseo-post-settings-sidebar-button svg *{fill:currentColor}#aioseo-post-settings-sidebar-button.score-disabled{color:#434960;border:1px solid #434960}#aioseo-post-settings-sidebar-button.score-disabled svg{margin-left:0;width:24px;height:24px}#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,#aioseo-post-settings-sidebar-button.score-disabled span{display:none}button[aria-label=AIOSEO],button[aria-label=AIOSEO]:hover{background:none!important;box-shadow:none!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-green,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-green{color:#fff;background-color:#00aa63}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-orange,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-orange{color:#fff;background-color:#f18200}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-red,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-none,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-red{color:#fff;background-color:#df2a4a}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled{color:#fff;background:#434960!important}button[aria-label=AIOSEO].is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-pressed>#aioseo-post-settings-sidebar-button.score-disabled #aioseo-post-score-disabled{color:#fff!important}button[aria-label=AIOSEO].components-icon-button>div svg,button[aria-label=AIOSEO].components-icon-button>div svg *,button[aria-label=AIOSEO].is-toggled>div svg,button[aria-label=AIOSEO].is-toggled>div svg *,button[aria-label=AIOSEO]:hover.components-icon-button>div svg,button[aria-label=AIOSEO]:hover.components-icon-button>div svg *,button[aria-label=AIOSEO]:hover.is-toggled>div svg,button[aria-label=AIOSEO]:hover.is-toggled>div svg *{fill:#fff!important;stroke:transparent!important}button[aria-label=AIOSEO].components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO].is-toggled>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.components-icon-button>div #aioseo-post-score-disabled,button[aria-label=AIOSEO]:hover.is-toggled>div #aioseo-post-score-disabled{color:#fff!important}
dist/Lite/assets/css/chunk-common.css CHANGED
@@ -1 +1 @@
1
- .aioseo-app .aioseo-cta{margin-top:30px;background:#fff;width:100%;padding:40px;box-shadow:0 2px 5px rgba(0,0,0,.05);border:1px solid #e8e8eb}.aioseo-app .aioseo-cta.floating{margin-top:0;position:absolute;max-width:850px;left:50%;top:50%;transform:translateX(-50%) translateY(-50%);box-shadow:0 5px 20px rgba(0,0,0,.1);border-radius:3px}.aioseo-app .aioseo-cta .header-text{line-height:1.4;font-weight:600;font-size:24px;text-align:center;color:#141b38}.aioseo-app .aioseo-cta .header-text span.large{line-height:1.4;font-size:32px}.aioseo-app .aioseo-cta .description{margin:30px 0 50px;width:100%;max-width:600px;text-align:center;font-size:16px;color:#141b38;line-height:1.4}.aioseo-app .aioseo-cta .description .aioseo-alert{margin-bottom:30px;text-align:left}.aioseo-app .aioseo-cta .feature-list{color:#141b38;font-size:16px;width:100%;max-width:500px;margin-bottom:50px}.aioseo-app .aioseo-cta .feature-list .aioseo-col{display:flex;align-items:flex-start}.aioseo-app .aioseo-cta .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:18px;min-width:18px;min-height:18px;margin-right:10px}.aioseo-app .aioseo-cta a.learn-more{margin-top:20px;color:#8c8f9a;font-size:14px}.aioseo-app .aioseo-cta .type-1{display:flex;flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2{margin:30px 0 30px 50px;display:flex}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:left}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-2>div{margin-right:20px;flex:0 0 50%}.aioseo-app .aioseo-cta .type-2 .featured-image{max-height:540px;border:1px solid #e8e8eb;flex:1;overflow:hidden;margin-right:-41px;margin-bottom:-71px;border-radius:5px 0 0}.aioseo-app .aioseo-cta .type-2 .featured-image img{max-height:600px}@media only screen and (max-width:912px){.aioseo-app .aioseo-cta .type-2{flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:center}.aioseo-app .aioseo-cta .type-2>div{text-align:center;margin-right:0;margin-bottom:30px;flex:1 0 100%;width:100%}.aioseo-app .aioseo-cta .type-2 .featured-image{margin:0 -10px -41px;border-radius:5px 5px 0 0;max-height:300px}}.aioseo-app .aioseo-cta .type-3 .sub-header{line-height:1.4;font-size:16px;font-weight:600;color:#005ae0;margin-bottom:5px}.aioseo-app .aioseo-cta .type-3 .header-text{text-align:left}.aioseo-app .aioseo-cta .type-3 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-3 .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:21px;min-width:21px;min-height:21px;margin-right:5px}.aioseo-app .aioseo-cta .type-3 .aioseo-button{margin-right:12px}.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:calc(200px + 1em)}@media only screen and (max-width:48em){.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:100%}}.aioseo-box-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-box-toggle input:checked+label{background-color:#fff;box-shadow:0 5px 10px rgba(0,90,224,.1);border:2px solid #005ae0;font-weight:600}.aioseo-box-toggle label{background-color:#f9f9fa;color:#141b38;font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;border:1px solid #f9f9fa;transition:all .1s ease-in-out;border-radius:3px;height:165px;position:relative}.aioseo-box-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-box-toggle label:hover{cursor:pointer}.aioseo-button{flex-shrink:0;line-height:1;display:inline-flex;align-items:center;justify-content:center;font-size:16px;font-weight:600;padding:0 24px;border-radius:4px;-webkit-appearance:none;cursor:pointer;height:48px;transition:background-color .2s ease;position:relative;overflow:hidden;text-decoration:none;color:#141b38;white-space:nowrap}.aioseo-button.small{height:30px;font-size:14px;padding:0 12px}.aioseo-button.small .loading-spinner{width:25px;height:25px}.aioseo-button.medium{height:40px;font-size:14px;padding:0 18px}.aioseo-button.medium .loading-spinner{width:35px;height:35px}.aioseo-button.xl{height:66px;border-radius:4px;font-size:18px;padding:0 48px}.aioseo-button.gray{border:1px solid #dcdde1;background-color:#f3f4f5}.aioseo-button.gray:hover{background-color:#fff;color:#141b38}.aioseo-button.gray:active{background-color:#f3f4f5}.aioseo-button.green{border:none;background-color:#00aa63;color:#fff}.aioseo-button.green:hover{background-color:#07c575}.aioseo-button.green:active{background-color:#15955f}.aioseo-button.blue{border:none;background-color:#005ae0;color:#fff}.aioseo-button.blue:hover{background-color:#1a82ea}.aioseo-button.blue:active{background-color:#004f9d}.aioseo-button.wp-blue{border:1px solid #005ae0;background-color:#f3f5f6;color:#005ae0}.aioseo-button.wp-blue:hover{background-color:#1a82ea;border-color:#1a82ea;color:#fff}.aioseo-button.wp-blue:active{background-color:#004f9d;border-color:#004f9d;color:#fff}.aioseo-button.black{border:none;background-color:#434960;color:#fff}.aioseo-button.black:hover{background-color:#2c324c}.aioseo-button.black:active{background-color:#141b38}.aioseo-button.red{border:1px solid #df2a4a;background-color:#fff;color:#df2a4a}.aioseo-button.red:hover{background-color:#df2a4a;color:#fff}.aioseo-button.red:active{background-color:#ab2039}.aioseo-button.loading.blue,.aioseo-button.loading.blue:hover{background-color:#004f9d;color:#004f9d}.aioseo-button.loading.green,.aioseo-button.loading.green:hover{background-color:#15955f;color:#15955f}.aioseo-button.loading.gray,.aioseo-button.loading.gray:hover{background-color:#f3f4f5;color:#f3f4f5}.aioseo-button.loading.black,.aioseo-button.loading.black:hover{background-color:#141b38;color:#141b38}.aioseo-button:disabled{color:#8c8f9a;background-color:#f3f4f5;cursor:default}.aioseo-button:disabled.gray:hover{color:#8c8f9a}.aioseo-button:disabled.wp-blue{border-color:#ddd;background-color:#f7f7f7}.aioseo-button:disabled.wp-blue:hover{border-color:#ddd;color:#8c8f9a}.aioseo-button:disabled:hover{background-color:#f3f4f5}.aioseo-checkbox{display:inline-flex;align-items:center}.aioseo-checkbox.disabled,.aioseo-checkbox.disabled .form-checkbox .fancy-checkbox,.aioseo-checkbox.no-clicks,.aioseo-checkbox.no-clicks .form-checkbox .fancy-checkbox{cursor:default}.aioseo-checkbox .form-checkbox-wrapper{margin-right:10px;display:flex}.aioseo-checkbox.medium .form-checkbox{width:20px;height:20px}.aioseo-checkbox.medium .form-checkbox .fancy-checkbox svg{width:12px;height:12px}.aioseo-checkbox.medium .form-checkbox span:before{height:18px;width:18px;line-height:20px}.aioseo-checkbox.round .form-checkbox span,.aioseo-checkbox.round .form-checkbox span:before{border-radius:50%}.aioseo-checkbox .form-checkbox{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-checkbox .form-checkbox input{display:none}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.blue{background:#005ae0}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.green{background:#00aa63}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox:before{background:transparent}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox{background:#e8e8eb!important;border:1px solid #d0d1d7;cursor:default}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox svg{color:#8c8f9a}.aioseo-checkbox .form-checkbox input:not(:checked):disabled+.fancy-checkbox:before{left:0;bottom:0;background:#e8e8eb}.aioseo-checkbox .form-checkbox .fancy-checkbox svg{color:#fff;width:16px;height:16px}.aioseo-checkbox .form-checkbox span{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#d0d1d7;transition:.2s;border-radius:3px;display:flex;align-items:center;justify-content:center}.aioseo-checkbox .form-checkbox span:before{position:absolute;content:"";height:26px;width:26px;left:1px;bottom:1px;background-color:#fff;transition:.2s;font-size:18px;line-height:28px;border-radius:2px}.aioseo-date-picker.vue-daterange-picker{width:100%}.aioseo-date-picker.vue-daterange-picker .form-control{display:flex;align-items:center;color:#141b38;font-size:16px;height:48px;border-radius:3px;border:1px solid #d0d1d7;position:relative}.aioseo-date-picker.vue-daterange-picker .form-control svg.aioseo-circle-close{position:absolute;right:10px;color:#434960;width:15px;height:15px}.aioseo-date-picker.vue-daterange-picker.small .form-control{height:30px}.aioseo-date-picker.vue-daterange-picker.medium .form-control{height:40px}body[class*=all-in-one-seo_page] .daterangepicker .yearselect{width:75px}.aioseo-editor{position:relative}.aioseo-editor .aioseo-editor-description .ql-editor{min-height:100px}.aioseo-editor .aioseo-editor-line-numbers .ql-editor{padding:15px 15px 15px 45px}.aioseo-editor .aioseo-editor-single .ql-editor{padding:8px 10px}.aioseo-editor .aioseo-editor-single.aioseo-editor-line-numbers .ql-editor{padding:8px 10px 8px 45px}.aioseo-editor .aioseo-editor-monospace .ql-editor{font-family:monospace}.aioseo-editor .aioseo-line-numbers{background:#f7f6f7;position:absolute;text-align:right;top:1px;width:29px;left:1px;border-radius:3px 0 0 3px;padding:15px 9px 0 0;display:flex;height:calc(100% - 2px);flex-direction:column;overflow:hidden}.aioseo-editor .aioseo-line-numbers div{min-height:25px;color:#8c8f9a;font-size:12px;line-height:1.9}.aioseo-editor .ql-disabled{pointer-events:none;background-color:#f9f9fa}.aioseo-editor .ql-editor{padding:15px;border-radius:3px;font-size:16px;color:#141b38;border:1px solid #d0d1d7}.aioseo-editor .ql-editor:focus{border:1px solid #005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-editor .ql-editor .mention .ql-mention-denotation-char{display:none}.aioseo-editor .ql-editor .mention .aioseo-tag{height:25px;margin:0 1px;color:#434960;font-weight:600;font-size:14px;padding:3px 25px 3px 10px;background-color:#f3f4f5;border-radius:3px;cursor:pointer;position:relative;display:inline-flex;align-items:center}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle{display:inline-flex;align-items:center;background-color:#e8e8eb;position:absolute;top:0;right:0;bottom:0;border-radius:0 3px 3px 0}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret{width:18px;height:18px;transition:transform .3s}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret.rotated{transform:rotate(180deg)}.aioseo-editor .ql-mention-list-container{color:#141b38;background-color:#fff;max-width:250px;width:100%;margin-top:3px;border:1px solid #d0d1d7;border-radius:3px;box-shadow:0 3px 15px rgba(0,0,0,.1);z-index:9001}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom,.aioseo-editor .ql-mention-list-container .aioseo-tag-search{padding:12px;border-bottom:1px solid #e8e8eb}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom{display:none}.aioseo-editor .ql-mention-list-container .ql-mention-list{list-style:none;margin:0;padding:0;max-height:210px;overflow:auto}.aioseo-editor .ql-mention-list-container .ql-mention-list li{color:#141b38;margin:0;background-color:transparent;border-bottom:1px solid #e8e8eb;padding:15px;cursor:pointer;font-size:14px}.aioseo-editor .ql-mention-list-container .ql-mention-list li:last-child{border-bottom:0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover{color:#005ae0;background-color:#f2f7fd}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected .aioseo-tag-description,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover .aioseo-tag-description{color:initial}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item{display:flex}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item>div:first-child{margin-right:10px}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item .aioseo-tag-title{font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match{cursor:default;padding:12px;font-size:16px;font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match.highlight,.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match:hover{color:initial;background-color:transparent}.aioseo-editor .ql-toolbar{display:none}.aioseo-editor .ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.aioseo-editor .ql-snow .ql-hidden{display:none}.aioseo-editor .ql-container.ql-snow{border:none}.aioseo-editor .ql-container p{font-size:16px;margin:0;line-height:25px}.aioseo-highlight-toggle{border:1px solid #e8e8eb;border-radius:3px;min-height:48px;display:flex;align-items:center;padding:5px 10px;cursor:pointer}.aioseo-highlight-toggle>*{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-highlight-toggle.active{border-color:#005ae0;box-shadow:0 5px 10px rgba(0,90,224,.1)}.aioseo-highlight-toggle.medium{min-height:40px}.aioseo-highlight-toggle .icon{display:flex;align-items:center;margin-right:5px}.aioseo-input[data-v-20c03142]{position:relative;width:100%}.aioseo-input.file[data-v-20c03142],.aioseo-input.file input[type=file][data-v-20c03142]{position:absolute;top:0;right:0;left:0;bottom:0;margin:0;padding:0}.aioseo-input.file input[type=file][data-v-20c03142]{cursor:pointer;opacity:0}.aioseo-input.file input[type=file][data-v-20c03142]::-webkit-file-upload-button{visibility:hidden}.aioseo-input.file input[type=file][data-v-20c03142]:focus{box-shadow:none}.aioseo-input input[data-v-20c03142]{height:48px;width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:3px;padding:15px;font-size:18px;position:relative;overflow:hidden;margin:0}.aioseo-input input[data-v-20c03142]:disabled{background:#f9f9fa}.aioseo-input input[data-v-20c03142]:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-input input[data-v-20c03142]::-moz-placeholder{color:#8c8f9a}.aioseo-input input[data-v-20c03142]:-ms-input-placeholder{color:#8c8f9a}.aioseo-input input[data-v-20c03142]::placeholder{color:#8c8f9a}.aioseo-input input.prepend[data-v-20c03142]{padding-left:50px}.aioseo-input input.append[data-v-20c03142]{padding-right:50px}.aioseo-input input.small[data-v-20c03142]{height:30px;padding:10px;font-size:14px}.aioseo-input input.small.prepend[data-v-20c03142]{padding-left:30px}.aioseo-input input.small.append[data-v-20c03142]{padding-right:30px}.aioseo-input input.medium[data-v-20c03142]{height:40px;padding:12px;font-size:16px}.aioseo-input input.medium.prepend[data-v-20c03142]{padding-left:35px}.aioseo-input input.medium.append[data-v-20c03142]{padding-right:35px}.aioseo-input.aioseo-active input[data-v-20c03142]{border-color:#00aa63}.aioseo-input.aioseo-active input[data-v-20c03142]:active,.aioseo-input.aioseo-active input[data-v-20c03142]:focus{box-shadow:0 0 0 1px #00aa63}.aioseo-input.aioseo-active .append-icon[data-v-20c03142],.aioseo-input.aioseo-active .prepend-icon[data-v-20c03142]{color:#00aa63}.aioseo-input.aioseo-error input[data-v-20c03142]{border-color:#df2a4a}.aioseo-input.aioseo-error input[data-v-20c03142]:active,.aioseo-input.aioseo-error input[data-v-20c03142]:focus{box-shadow:0 0 0 1px #df2a4a}.aioseo-input.aioseo-error .append-icon[data-v-20c03142],.aioseo-input.aioseo-error .prepend-icon[data-v-20c03142]{color:#df2a4a}.aioseo-input.aioseo-warning input[data-v-20c03142]{border-color:#f18200}.aioseo-input.aioseo-warning input[data-v-20c03142]:active,.aioseo-input.aioseo-warning input[data-v-20c03142]:focus{box-shadow:0 0 0 1px #f18200}.aioseo-input.aioseo-warning .append-icon[data-v-20c03142],.aioseo-input.aioseo-warning .prepend-icon[data-v-20c03142]{color:#f18200}.aioseo-input .prepend-icon[data-v-20c03142]{position:absolute;top:0;left:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .prepend-icon svg[data-v-20c03142]{width:30px;height:30px}.aioseo-input .prepend-icon.small[data-v-20c03142]{width:20px}.aioseo-input .prepend-icon.small svg[data-v-20c03142]{width:10px;height:10px}.aioseo-input .prepend-icon.medium[data-v-20c03142]{width:15px}.aioseo-input .prepend-icon.medium svg[data-v-20c03142]{width:15px;height:15px}.aioseo-input .append-icon[data-v-20c03142]{position:absolute;top:0;right:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .append-icon svg[data-v-20c03142]{width:30px;height:30px}.aioseo-input .append-icon.small[data-v-20c03142]{width:10px}.aioseo-input .append-icon.medium[data-v-20c03142]{width:15px}.aioseo-input .append-icon.clickable[data-v-20c03142]{cursor:pointer;padding:0 5px;background:#f3f4f5;border:1px solid #d0d1d7;color:#434960;right:0;width:30px;border-radius:0 3px 3px 0}.aioseo-input .append-icon.clickable.small[data-v-20c03142]{width:15px}.aioseo-input .append-icon.clickable.medium[data-v-20c03142]{padding:0 10px;width:40px}.aioseo-phone-number{max-width:600px}.aioseo-phone-number label{display:none}.aioseo-phone-number .maz-input__input{height:40px;min-height:40px;padding-top:0!important;border:1px solid #d0d1d7}.aioseo-phone-number .maz-input__input:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .country-selector{flex:0 0 140px;width:140px;min-width:140px;max-width:140px}.aioseo-phone-number .country-selector:hover{z-index:1}.aioseo-phone-number .country-selector>div.maz-base-component.maz-input.has-value.has-1-right-icon.maz-input--primary>input{padding-left:50px!important}.aioseo-phone-number .country-selector .maz-input.is-focused{border-color:#005ae0}.aioseo-phone-number .country-selector .maz-select__options-list__item.selected.keyboard-selected{background-color:#005ae0}.aioseo-phone-number .maz-phone-number-input__country-flag{left:20px;bottom:12px}.aioseo-phone-number .maz-select__options-list input{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .maz-input__input{border-radius:3px}.aioseo-phone-number .input-phone-number,.aioseo-phone-number .input-phone-number:focus{z-index:2}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input{border-color:red}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input:focus{border-color:#df2a4a;box-shadow:0 0 0 1px #df2a4a}.aioseo-phone-number.validNumber div.maz-flex-1>div>input:focus{border-color:#00aa63;box-shadow:0 0 0 1px #00aa63}.aioseo-radio{display:inline-flex;align-items:center}.aioseo-radio .form-radio-wrapper{margin-right:10px;display:flex}.aioseo-radio.medium .form-radio{width:20px;height:20px}.aioseo-radio.medium .form-radio .fancy-radio svg{width:12px;height:12px}.aioseo-radio.medium.type-1 .form-radio span:before{height:18px;width:18px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:before{height:16px;width:16px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:after{height:6px;width:6px;left:6px;bottom:6px}.aioseo-radio .form-radio{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-radio .form-radio input{opacity:0}.aioseo-radio .form-radio input:checked+.fancy-radio{background:#005ae0;border-color:#005ae0}.aioseo-radio .form-radio input:checked+.fancy-radio:before{background:transparent}.aioseo-radio .form-radio input:checked+.fancy-radio:after{display:block}.aioseo-radio .form-radio input:disabled+.fancy-radio{cursor:default}.aioseo-radio .form-radio input:focus+.fancy-radio{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-radio .form-radio .fancy-radio{border-radius:50%}.aioseo-radio .form-radio .fancy-radio svg{color:#fff;width:16px;height:16px}.aioseo-radio .form-radio span{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;transition:.2s;border-radius:50%;display:flex;align-items:center;justify-content:center}.aioseo-radio .form-radio span:before{position:absolute;content:"";height:26px;width:26px;left:1px;bottom:1px;transition:.2s;font-size:18px;line-height:28px;border-radius:50%}.aioseo-radio.type-1 .form-radio span,.aioseo-radio.type-1 .form-radio span:before{background-color:#f3f4f5}.aioseo-radio.type-2 .form-radio span{border:1px solid #d0d1d7;background-color:#fff}.aioseo-radio.type-2 .form-radio span:before{background-color:#fff}.aioseo-radio.type-2 .form-radio span:after{display:none;position:absolute;content:"";height:10px;width:10px;left:8px;bottom:8px;background-color:#fff;transition:.2s;border-radius:50%}.aioseo-radio.disabled{cursor:default}.aioseo-radio.disabled.type-2 .form-radio input:checked+.fancy-radio{background-color:#e8e8eb;border-color:#d0d1d7}.aioseo-radio.disabled.type-2 .form-radio span,.aioseo-radio.disabled.type-2 .form-radio span:before{background-color:#e8e8eb}.aioseo-radio.disabled.type-2 .form-radio span:after{background-color:#8c8f9a}.aioseo-radio-toggle{display:flex;align-items:center;height:40px}.aioseo-radio-toggle div{height:100%}.aioseo-radio-toggle.inline{display:inline-flex}.aioseo-radio-toggle div:first-child{overflow:hidden;border-radius:3px 0 0 3px}.aioseo-radio-toggle div:first-child label{border-radius:3px 0 0 3px}.aioseo-radio-toggle div:last-child{overflow:hidden;border-radius:0 3px 3px 0}.aioseo-radio-toggle div:last-child label{border-radius:0 3px 3px 0}.aioseo-radio-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-radio-toggle input:checked+label{background-color:#005ae0;color:#fff}.aioseo-radio-toggle input:checked+label.dark{background-color:#434960;color:#fff}.aioseo-radio-toggle label{height:100%;background-color:#e8e8eb;color:#141b38;font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;transition:all .1s ease-in-out;position:relative;padding:11px 20px;font-weight:600}.aioseo-radio-toggle label.disabled{cursor:default;pointer-events:none;opacity:.5}.aioseo-radio-toggle label:hover{background-color:#dadadf;cursor:pointer}.aioseo-radio-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-radio-toggle.circle label{background:#fff;color:#8c8f9a}.aioseo-radio-toggle.circle input+label{border-radius:50%;width:36px;height:36px;padding:8px}.aioseo-radio-toggle.circle input:checked+label{background:#e8e8eb;color:#2c324c}.aioseo-select{height:48px}.aioseo-select.multiselect--disabled .multiselect__select{background:none}.aioseo-select .multiselect__select{display:flex;align-items:center;justify-content:center;min-height:46px}.aioseo-select .multiselect__select:before{display:none}.aioseo-select .multiselect__select svg.aioseo-caret{color:#141b38;width:18px;height:18px;transition:transform .3s}.aioseo-select .multiselect__tags{height:100%;border:1px solid #d0d1d7;border-radius:3px;display:flex;justify-content:center;flex-direction:column;padding:16px 40px 16px 16px}.aioseo-select .multiselect__tags .multiselect__spinner{height:calc(100% - 2px);border:2px solid transparent}.aioseo-select .multiselect__tags .multiselect__spinner:after,.aioseo-select .multiselect__tags .multiselect__spinner:before{border-top-color:#434960}.aioseo-select .multiselect__tags .multiselect__single{display:inline-flex;margin:0;padding:0;color:#141b38;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.aioseo-select .multiselect__tags .multiselect__placeholder{color:#8c8f9a;font-size:16px;line-height:20px;margin:0;padding:0}.aioseo-select .multiselect__tags .multiselect__input{padding:0;margin:0 10px 0 0;border-radius:0;border:none;color:#141b38;min-height:auto;line-height:20px}.aioseo-select .multiselect__tags .multiselect__input:focus{outline:0;box-shadow:none;border:none}.aioseo-select .multiselect__tags .multiselect__input::-moz-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input:-ms-input-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input::placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__tags-wrap{display:flex;align-items:center;flex-wrap:wrap}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag{padding:0;display:inline-flex;align-items:center;font-size:14px;font-weight:600;color:#434960;margin:0 3px 0 0;height:24px;background-color:#f3f4f5;flex-shrink:0}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-value{padding:0 5px 0 10px}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove{padding:0 10px;height:100%;cursor:pointer;background-color:#f3f4f5;display:flex;align-items:center}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover{background-color:#434960;color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover svg.aioseo-close{color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove svg.aioseo-close{color:#434960;width:10px;height:10px}.aioseo-select.multiselect--active .multiselect__tags-wrap{margin-bottom:7px}.aioseo-select.small{height:30px;min-height:30px}.aioseo-select.small .multiselect__tags{min-height:30px;padding:8px 38px 8px 8px}.aioseo-select.small .multiselect__tags .multiselect__placeholder{font-size:14px}.aioseo-select.small .multiselect__select{height:28px;min-height:28px}.aioseo-select.small .multiselect__input{font-size:14px}.aioseo-select.small .multiselect__content-wrapper li.multiselect__element .multiselect__option{font-size:14px;padding:8px;min-height:30px}.aioseo-select.medium{height:40px}.aioseo-select.medium .multiselect__tags{padding:7px 40px 7px 7px}.aioseo-select.medium .multiselect__select{min-height:38px}.aioseo-select.multiple{min-height:48px;height:auto}.aioseo-select.multiple.small{min-height:30px}.aioseo-select.multiple.medium{min-height:40px}.aioseo-select.multiselect--above .multiselect__content-wrapper{border-top:1px solid #d0d1d7;border-bottom:none}.aioseo-select .multiselect__content-wrapper{border:1px solid #d0d1d7;border-top:none;border-bottom-left-radius:3px;border-bottom-right-radius:3px;z-index:50;-webkit-overflow-scrolling:touch}.aioseo-select .multiselect__content-wrapper .multiselect__content{max-width:100%}.aioseo-select .multiselect__content-wrapper li.multiselect__element{margin:0;border-bottom:1px solid #e8e8eb}.aioseo-select .multiselect__content-wrapper li.multiselect__element.last{border-bottom:none}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight:after{background-color:#005ae0;color:#fff}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--selected{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--disabled{font-weight:400;background-color:#fff!important;color:#8c8f9a}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option .docLink{font-size:13px;float:right}.aioseo-textarea-autosize{width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:4px;font-size:16px;padding:12px}.aioseo-toggle{display:inline-flex}.aioseo-toggle:active,.aioseo-toggle:focus{outline:2px solid transparent}.aioseo-toggle.disabled{pointer-events:none}.aioseo-toggle.disabled .toggle-content{opacity:.5}.aioseo-toggle .toggle-content{position:relative;display:inline-block;width:36px;height:20px;margin-right:10px}.aioseo-toggle .toggle-content input{display:none}.aioseo-toggle .toggle-content input:checked+.toggle-switch{border:1px solid #005ae0;background-color:#005ae0}.aioseo-toggle .toggle-content input:checked+.toggle-switch:focus{outline:2px solid transparent}.aioseo-toggle .toggle-content input:checked+.toggle-switch:before{background-color:#fff;transform:translateX(15px)}.aioseo-toggle .toggle-content input:focus+.toggle-switch{box-shadow:0 0 1px #005ae0;outline:2px solid transparent}.aioseo-toggle .toggle-content .toggle-switch{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#fff;border:1px solid #d0d1d7;border-radius:15px;transition:.2s}.aioseo-toggle .toggle-content .toggle-switch:before{position:absolute;content:"";height:14px;width:14px;left:3px;bottom:2px;background-color:#d0d1d7;border-radius:50%;transition:.2s}.aioseo-wp-table input[type=search],.aioseo-wp-table select{border-color:#d0d1d7}.aioseo-wp-table select:focus{border-color:#005ae0;color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-wp-table select:hover{color:#005ae0}.aioseo-wp-table input.button,.aioseo-wp-table input.button:hover{color:#005ae0;border-color:#005ae0}.aioseo-wp-table .header .subsubsub{color:#555d66;font-size:13px;font-weight:600}.aioseo-wp-table .header .subsubsub>span{display:inline-flex}.aioseo-wp-table .header .subsubsub .separator{margin:0 5px}.aioseo-wp-table .header .subsubsub .active{font-weight:700;color:#141b38}.aioseo-wp-table .header .subsubsub a{text-decoration:none}.aioseo-wp-table .header .subsubsub a:hover{text-decoration:underline}.aioseo-wp-table .header .search{display:flex;justify-content:flex-end}.aioseo-wp-table .header .search .aioseo-input{width:100%;max-width:215px;margin-right:6px}.aioseo-wp-table .header .pagination{color:#555d66}.aioseo-wp-table .header .pagination .button,.aioseo-wp-table .header .pagination input{margin-left:6px}.aioseo-wp-table .tablenav-pages .current-page{padding:0 0 0 8px}.aioseo-wp-table .wp-table{width:100%;position:relative}.aioseo-wp-table .wp-table .loader-overlay{position:absolute;top:46px;right:0;bottom:36px;left:0;background:rgba(0,0,0,.3);z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-wp-table .wp-table .no-results{color:#8c8f9a;min-height:200px;display:flex;align-items:center;justify-content:center;font-weight:400;font-size:24px}.aioseo-wp-table .wp-table tr.even{background-color:#f9f9fa}.aioseo-wp-table .wp-table tr.enabled td,.aioseo-wp-table .wp-table tr.enabled td strong a{color:#141b38}.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td,.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td a.edit-link{color:#8c8f9a}.aioseo-wp-table .wp-table tr.edit-row th{padding:0 0 0 3px}.aioseo-wp-table .wp-table tr.edit-row td{padding:0 30px 0 10px}.aioseo-wp-table .wp-table tr td strong a{font-weight:400}.aioseo-wp-table .wp-table tr td .row-actions .edit a,.aioseo-wp-table .wp-table tr td strong a:hover{color:#005ae0}.aioseo-wp-table .wp-table tr td .row-actions .edit .trash a{color:#df2a4a}.aioseo-wp-table .wp-table tr td.edit-row-content .wrapper .border{padding:8px 0;border-top:1px solid #e8e8eb}.aioseo-add-404-redirection .generic-error{margin-bottom:20px}.aioseo-add-404-redirection .aioseo-settings-row .settings-name .name{font-size:14px}.aioseo-add-404-redirection .urls{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap}.aioseo-add-404-redirection .urls .target{flex:1;display:flex;align-items:center;max-width:480px;min-width:400px;margin-right:20px}.aioseo-add-404-redirection .urls .target>*{flex:1}.aioseo-add-404-redirection .urls .target .aioseo-input{margin-bottom:10px}.aioseo-add-404-redirection .urls .target .aioseo-description{height:30px}.aioseo-add-404-redirection .urls .target .append-icon{width:60px;justify-content:flex-end}.aioseo-add-404-redirection .urls .target .append-icon svg{max-width:16px;margin-right:5px}.aioseo-add-404-redirection .urls .target .append-icon svg:last-of-type{margin-right:0}.aioseo-add-404-redirection .urls .target .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-add-404-redirection .urls .target .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-add-404-redirection .urls .target .target-url-error,.aioseo-add-404-redirection .urls .target .target-url-warning{margin-bottom:10px}.aioseo-add-404-redirection .urls .redirect-type{flex:1;align-self:flex-start}.aioseo-add-404-redirection .urls .redirect-type .aioseo-select{max-width:220px}.aioseo-add-404-redirection .settings{display:flex;flex-direction:row;align-items:center;margin-top:30px}.aioseo-add-404-redirection .settings .all-settings{flex:1}.aioseo-add-404-redirection .settings .all-settings .all-settings-content{display:flex;align-items:center}.aioseo-add-404-redirection .settings .redirect-type{width:100%;max-width:350px;margin-right:24px}.aioseo-add-404-redirection .settings .redirect-type .aioseo-select{margin-top:5px}.aioseo-add-404-redirection .settings .aioseo-button{align-self:flex-end}.aioseo-add-404-redirection .settings .cancel-edit-row{margin-left:10px}.custom-rules[data-v-7e05ebd5]{width:100%}.custom-rules .rule-table[data-v-7e05ebd5]{margin-top:5px;border:1px solid #d0d1d7;border-radius:3px;width:100%;font-family:Helvetica;font-size:14px;font-style:normal;font-weight:400;line-height:21px;letter-spacing:0;text-align:left}.custom-rules .rule-table .rule[data-v-7e05ebd5]{padding:13px;background:#f9f9fa}.custom-rules .rule-table .rule.even[data-v-7e05ebd5]{background-color:#fff}.custom-rules .rule[data-v-7e05ebd5]{display:flex;flex-direction:row;align-items:center;padding-top:10px}.custom-rules .rule[data-v-7e05ebd5]:first-child{border-radius:3px 3px 0 0}.custom-rules .rule[data-v-7e05ebd5]:last-child{border-radius:0 0 3px 3px}.custom-rules .rule .rule-settings>.aioseo-select[data-v-7e05ebd5]:first-child{width:250px;min-width:250px}.custom-rules .rule .rule-settings[data-v-7e05ebd5]{display:flex;flex-direction:row;align-items:center;flex:1}.custom-rules .rule .rule-settings>[data-v-7e05ebd5]{margin:0 6px 0 0}.custom-rules .rule .rule-settings>.aioseo-toggle[data-v-7e05ebd5]{margin:0 10px 0 4px}.custom-rules .rule .actions[data-v-7e05ebd5],.custom-rules .rule .logical[data-v-7e05ebd5]{flex:0}.custom-rules svg[data-v-7e05ebd5]{width:14px;height:14px;cursor:pointer}.custom-rules svg.aioseo-trash[data-v-7e05ebd5]{color:#dadada}.custom-rules svg.aioseo-trash[data-v-7e05ebd5]:hover{color:#df2a4a}.custom-rules .aioseo-tooltip[data-v-7e05ebd5]{margin:0;display:flex}.custom-rules .aioseo-button svg[data-v-7e05ebd5]{color:#fff}.custom-rules .add-rule[data-v-7e05ebd5]{margin-top:10px}.custom-rules .add-rule svg[data-v-7e05ebd5]{margin-right:6px}.aioseo-add-redirection.edit-url{margin-bottom:30px}.aioseo-add-redirection.edit-url .urls{align-items:flex-start}.aioseo-add-redirection.edit-url .urls .url-arrow{margin:-8px 30px 0}.aioseo-add-redirection.edit-url .advanced-settings-link{text-decoration:underline;margin-top:21px}.aioseo-add-redirection.log-404 .urls .source{min-height:103px;align-items:flex-start}.aioseo-add-redirection .generic-error{margin-bottom:20px}.aioseo-add-redirection .aioseo-settings-row .settings-name .name{font-size:14px}.aioseo-add-redirection .urls{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .urls .break{flex-basis:100%;height:0}.aioseo-add-redirection .urls .url-arrow{width:36px;margin:-15px 30px 0;display:flex;align-items:center;justify-content:center}.aioseo-add-redirection .urls .url-arrow svg{height:103px;color:#005ae0}.aioseo-add-redirection .urls .source,.aioseo-add-redirection .urls .target{flex:1;display:flex;align-items:center}.aioseo-add-redirection .urls .source>*,.aioseo-add-redirection .urls .target>*{flex:1}.aioseo-add-redirection .urls .source .aioseo-input,.aioseo-add-redirection .urls .target .aioseo-input{margin-bottom:10px}.aioseo-add-redirection .urls .target .aioseo-description{height:30px}.aioseo-add-redirection .urls .target .append-icon{width:60px;justify-content:flex-end}.aioseo-add-redirection .urls .target .append-icon svg{max-width:16px;margin-right:5px}.aioseo-add-redirection .urls .target .append-icon svg:last-of-type{margin-right:0}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-add-redirection .urls .target .target-url-error,.aioseo-add-redirection .urls .target .target-url-warning{margin-bottom:10px}.aioseo-add-redirection .settings{display:flex;flex-direction:column;align-items:center;margin-top:30px}.aioseo-add-redirection .settings .all-settings{width:100%}.aioseo-add-redirection .settings .all-settings .all-settings-content{display:flex;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .settings .all-settings .all-settings-content .advanced-settings-link{margin:16px 0 0 16px;color:#8c8f9a}@media (max-width:767px){.aioseo-add-redirection .settings .all-settings .all-settings-content{align-items:start}}.aioseo-add-redirection .settings>.actions{align-self:flex-end;margin-top:-50px}.aioseo-add-redirection .settings>.actions.advanced{margin-top:-40px}.aioseo-add-redirection .settings .query-params,.aioseo-add-redirection .settings .redirect-type{margin-bottom:10px;flex:0 1 auto}.aioseo-add-redirection .settings .query-params .aioseo-select,.aioseo-add-redirection .settings .redirect-type .aioseo-select{margin-top:5px}.aioseo-add-redirection .settings .query-params{width:340px}.aioseo-add-redirection .settings .redirect-type{width:300px;margin-right:24px}.aioseo-add-redirection .settings .aioseo-button{align-self:flex-end}.aioseo-add-redirection .settings .cancel-edit-row{margin-left:10px}.aioseo-add-redirection-target-url,.aioseo-redirect-source-url{position:relative}.aioseo-redirect-source-url .aioseo-input input{padding-right:76px}.aioseo-redirect-source-url .aioseo-input .append-icon{width:60px;justify-content:flex-end}.aioseo-redirect-source-url .aioseo-input .append-icon svg{max-width:16px;margin-right:5px}.aioseo-redirect-source-url .aioseo-input .append-icon svg:last-of-type{margin-right:0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear:hover{color:#005ae0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash:hover{color:#df2a4a}.aioseo-redirect-source-url .source-url-error,.aioseo-redirect-source-url .source-url-warning{margin-bottom:10px}.aioseo-redirect-source-url .source-url-options>div{padding-bottom:5px}.aioseo-redirect-source-url .source-url-options>div>div{margin-bottom:5px}.aioseo-add-redirection-url-results{display:flex;position:absolute;background:#fff;width:100%;max-height:300px;overflow:auto;border:1px solid #d0d1d7;border-radius:3px;z-index:50;left:1px;margin-top:-9px}.aioseo-add-redirection-url-results ul{display:inline-block;max-width:100%;list-style:none;padding:0;margin:0;min-width:100%;vertical-align:top}.aioseo-add-redirection-url-results ul li{margin:0;border-bottom:1px solid #e8e8eb;display:block}.aioseo-add-redirection-url-results ul li:last-of-type{border-bottom:none}.aioseo-add-redirection-url-results ul li>span{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4;display:flex;padding:12px;min-height:40px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer}.aioseo-add-redirection-url-results ul li>span:hover{background-color:#f2f7fd}.aioseo-add-redirection-url-results ul li>span:hover .option-title{color:#005ae0}.aioseo-add-redirection-url-results .option{flex:1}.aioseo-add-redirection-url-results .option .option-title{font-weight:500;display:flex;font-size:16px;color:#141b38}.aioseo-add-redirection-url-results .option .option-title>div{margin-right:5px}.aioseo-add-redirection-url-results .option .option-title>div:first-of-type{display:inline-block}.aioseo-add-redirection-url-results .option .option-title .search-term{font-weight:700}.aioseo-add-redirection-url-results .option .option-details{display:flex;align-items:center;font-size:14px;color:#8c8f9a}.aioseo-add-redirection-url-results .option .option-details span{margin-right:15px}.aioseo-add-redirection-url-results .option-permalink{display:flex;align-items:center}.aioseo-add-redirection-url-results .option-permalink svg.aioseo-external{width:15px;height:15px;color:#434960}.aioseo-add-template-tag{border-radius:3px;padding:5px 10px;color:#141b38;font-size:14px;border:1px solid #e8e8eb;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-weight:600}.aioseo-add-template-tag:hover{background-color:#f3f4f5}.aioseo-add-template-tag svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-additional-pages .additional-pages-table{border:1px solid #d0d1d7;border-radius:3px;margin-bottom:20px}.aioseo-additional-pages .additional-pages-table .page-priority{max-width:110px}.aioseo-additional-pages .additional-pages-table .page-frequency{max-width:166px}.aioseo-additional-pages .additional-pages-table .page-last-modified{max-width:155px}.aioseo-additional-pages .additional-pages-table .page-actions{max-width:20px}.aioseo-additional-pages .additional-pages-table .page-actions .aioseo-tooltip{display:inline-block;margin:0}.aioseo-additional-pages .additional-pages-table .pages-header{height:50px;display:flex;font-size:14px;padding:0 30px;align-items:center;border-bottom:1px solid #d0d1d7}.aioseo-additional-pages .additional-pages-table .pages-header>div{flex:1 0 auto}.aioseo-additional-pages .additional-pages-table .pages-rows{font-size:14px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row{background-color:#fff;height:70px;display:flex;align-items:center;padding:0 30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row:last-of-type{border-radius:0 0 3px 3px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row.even{background-color:#f9f9fa}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div{flex:1 0 auto;padding-right:30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div:last-child{padding-right:0}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash{width:20px;height:20px;color:#8c8f9a;cursor:pointer;transition:color .1s ease}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash:hover{color:#df2a4a}.aioseo-additional-pages svg.aioseo-circle-plus{width:14px;height:14px;margin-right:10px}.aioseo-alert{position:relative;border-radius:3px;padding:24px;font-size:16px;color:#141b38;line-height:1.4}.aioseo-alert.small{padding:8px;font-size:13px}.aioseo-alert .aioseo-alert-close{cursor:pointer;position:absolute;top:-9px;right:-9px;width:18px;height:18px;border-radius:50%;padding:5px;display:inline-flex;justify-content:center;align-content:center}.aioseo-alert .aioseo-alert-close svg{width:100%;height:100%}.aioseo-alert.blue{border:1px solid #005ae0;background-color:#f2f7fd}.aioseo-alert.blue .aioseo-alert-close{background-color:#005ae0;color:#fff}.aioseo-alert.green{border:1px solid #00aa63;background-color:#f2fdf8}.aioseo-alert.green .aioseo-alert-close{background-color:#00aa63;color:#fff}.aioseo-alert.red{border:1px solid #df2a4a;background-color:#fbe9ec}.aioseo-alert.red .aioseo-alert-close{background-color:#df2a4a;color:#fff}.aioseo-alert.yellow{border:1px solid #f18200;background-color:#fcfae8}.aioseo-alert.yellow .aioseo-alert-close{background-color:#f18200;color:#fff}.aioseo-alert.no-border{border-width:0}.aioseo-alert.text-center{text-align:center}.aioseo-analyze-competitor-site-score{border:1px solid #00aa63;border-radius:3px;color:#00aa63;font-size:14px;padding:0 8px;height:24px;display:inline-flex;align-items:center;justify-content:center;margin-right:14px}.aioseo-analyze-competitor-site-score.red{color:#df2a4a;border-color:#df2a4a}.aioseo-analyze-competitor-site-score.orange{color:#f18200;border-color:#f18200}.aioseo-animated-dannie{display:flex;align-content:center;align-items:center;justify-content:center}.aioseo-animated-dannie svg{max-width:250px}.aioseo-blur{filter:blur(3px);pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-card{color:#141b38;background-color:#fff;border:1px solid #e8e8eb;box-shadow:0 2px 5px rgba(0,0,0,.05);margin:30px 0}.aioseo-card.disabled .content{background:#f9f9fa;font-size:16px;line-height:24px}@media only screen and (max-width:782px){.aioseo-card{margin:20px 0}}.aioseo-card svg.aioseo-circle-question-mark{width:17px;height:17px;color:#8c8f99;transition:background-color .2s ease}.aioseo-card svg.aioseo-circle-question-mark:hover{color:#5a5c65}.aioseo-card .header{display:flex;align-items:center;height:70px;padding:0 30px;font-weight:600;font-size:18px;border-bottom:1px solid #e8e8eb}.aioseo-card .header .header-icon{display:flex}.aioseo-card .header .header-icon svg{width:24px;height:24px;margin-right:16px}.aioseo-card .header .text{flex:1 0 auto;display:flex;align-items:center}.aioseo-card .header .text svg.aioseo-circle-question-mark{cursor:pointer;width:17px;height:17px}.aioseo-card .header .text .aioseo-pro-badge{margin-left:10px}.aioseo-card .header .text .card-score{display:flex;flex:1;align-items:center;justify-content:flex-end;padding-right:18px;font-size:13px}.aioseo-card .header .text .card-score.green{color:#00aa63}.aioseo-card .header .text .card-score.orange{color:#f18200}.aioseo-card .header .text .card-score.red{color:#df2a4a}.aioseo-card .header .text .card-score svg{margin-right:7px}.aioseo-card .header svg.aioseo-caret{width:24px;height:24px;cursor:pointer;transform:rotate(-180deg);transition:transform .3s}.aioseo-card .header svg.aioseo-caret.rotated{transform:rotate(-90deg)}.aioseo-card .header svg.aioseo-close{width:14px;height:14px;cursor:pointer}.aioseo-card .content{padding:30px;position:relative}.aioseo-card div.aioseo-settings-row:last-child{margin-bottom:0;border-bottom:none;padding-bottom:0}.aioseo-copy-block{display:flex}.aioseo-copy-block .message{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-radius:3px 0 0 3px;padding:10px 24px;font-weight:600}.aioseo-copy-block .copy-tooltip{display:flex}.aioseo-copy-block .copy{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-left-width:0;border-radius:0 3px 3px 0;padding:10px 16px;font-weight:600;cursor:pointer}.aioseo-copy-block .copy:hover svg.aioseo-copy{color:#a7a7a7}.aioseo-copy-block .copy svg.aioseo-copy{width:20px;height:20px;color:#dadada}.aioseo-copy-block .copy svg.aioseo-circle-check-solid{width:20px;height:20px;color:#00aa63}.aioseo-display-info .aioseo-box-toggle svg{margin-top:-15px;color:#434960}.aioseo-display-info svg.aioseo-shortcode,.aioseo-display-info svg.aioseo-widget{width:100%;height:auto;max-width:60px}.aioseo-display-info svg.aioseo-gutenberg-block{width:59px;height:54px}.aioseo-display-info svg.aioseo-gutenberg-block rect{width:100%;width:56px;height:51px}.aioseo-display-info svg.aioseo-php{width:110px}.aioseo-display-info .copy-box{padding-top:.5rem}.aioseo-display-info .copy-box>div{padding:30px;border-radius:3px;background-color:#f9f9fa}.aioseo-display-info .copy-box .aioseo-description{margin:0}.aioseo-display-info .copy-box .aioseo-copy-block{margin:20px 0 0}.aioseo-display-info .aioseo-tooltip{margin-left:0}.aioseo-exclude-posts{display:flex}.aioseo-exclude-posts .aioseo-select{max-width:600px;display:inline-block;margin-right:10px}.aioseo-exclude-posts .aioseo-select .multiselect__option{display:flex}.aioseo-exclude-posts .aioseo-select .multiselect__option--highlight .option-title{color:#005ae0}.aioseo-exclude-posts .option{flex:1 0 auto}.aioseo-exclude-posts .option .option-title{font-weight:500;font-size:16px;color:#141b38}.aioseo-exclude-posts .option .option-title .search-term{font-weight:700}.aioseo-exclude-posts .option .option-details{display:flex;align-items:center;font-size:14px;color:#8c8f9a}.aioseo-exclude-posts .option .option-details span{margin-right:15px}.aioseo-exclude-posts .option-permalink{display:flex;align-items:center}.aioseo-exclude-posts .option-permalink svg.aioseo-external{width:15px;height:15px;color:#434960}.aioseo-exclude-posts .multiselect-toggle{padding:10px 13px;width:40px;position:absolute;height:36px;right:2px;top:2px;text-align:center;z-index:1}.aioseo-exclude-posts .multiselect-toggle svg.aioseo-add-plus{width:14px;height:14px;color:#000}.aioseo-facebook-preview{background-color:#f0f2f5;padding:30px;display:flex;align-items:center;justify-content:center}.aioseo-facebook-preview .facebook-post{width:100%;max-width:525px;border-radius:10px;box-shadow:0 2px 5px rgba(0,0,0,.1);background-color:#fff}.aioseo-facebook-preview .facebook-post .facebook-header{height:65px;padding:0 18px;display:flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo{overflow:hidden;width:40px;height:40px;border:1px solid #e8e8eb;border-radius:50%}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo img{height:100%;width:100%}.aioseo-facebook-preview .facebook-post .facebook-header .poster{margin-left:10px;flex:1 0 auto}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-name{font-size:15px;color:#050505;font-weight:500}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-date{color:#65676b;font-size:13px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis{display:inline-flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div{background-color:#5e666f;width:4px;height:4px;border-radius:50%;margin:0 2px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:first-child{margin-left:0}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:last-child{margin-right:0}.aioseo-facebook-preview .facebook-post .facebook-content{display:flex;flex-direction:column}.aioseo-facebook-preview .facebook-post .facebook-content img{width:100%;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content.vertical{flex-direction:row}.aioseo-facebook-preview .facebook-post .facebook-content.vertical img{max-width:158px;max-height:158px;width:auto;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description{flex:1;background-color:#f2f3f5;padding:9px 13px;color:#606770}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-domain{font-size:13px;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-title{color:#1d2129;font-size:17px;font-weight:600;margin:5px 0}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-description{font-size:14px}.aioseo-facebook-preview .facebook-post .facebook-footer{height:24px}.aioseo-feature-card{height:100%;border:1px solid #e8e8eb;background:#fff;box-shadow:0 2px 5px rgba(0,0,0,.05);color:#141b38;display:flex;flex-direction:column}.aioseo-feature-card .feature-card-body{padding:30px 30px 20px;flex:1}.aioseo-feature-card .feature-card-body.static{padding:30px}.aioseo-feature-card .feature-card-body .feature-card-header{display:flex;align-items:center;font-size:18px;font-weight:600;margin-bottom:16px}.aioseo-feature-card .feature-card-body .feature-card-header img,.aioseo-feature-card .feature-card-body .feature-card-header svg{width:28px;height:28px;margin-right:10px}.aioseo-feature-card .feature-card-body .feature-card-description{color:#434960;font-size:15px}.aioseo-feature-card .feature-card-body .feature-card-description .learn-more{margin-top:10px}.aioseo-feature-card .feature-card-footer{padding:15px}.aioseo-feature-card .feature-card-footer:not(.upgrade-required){border:2px solid #fff;background-color:#f9f9fa;padding:12px;min-height:43px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate{display:flex;align-items:center;justify-content:flex-end;height:30px;position:relative}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-loading-spinner{position:absolute;left:0}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .status{font-weight:600;font-size:14px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-toggle .toggle-content{margin-right:0;margin-left:10px}.aioseo-feature-card .feature-card-footer .feature-card-upgrade-cta{display:flex;align-items:center;justify-content:flex-end}.aioseo-feature-card .feature-card-footer.installed .feature-card-install-activate .status{color:#8c8f9a}.aioseo-setup-wizard-container{margin-top:30px;margin-bottom:50px;padding:30px;color:#fff;position:relative;background-color:#005ae0}@media only screen and (max-width:782px){.aioseo-setup-wizard-container{margin-top:20px}}.aioseo-setup-wizard-container p{color:#fff}.aioseo-setup-wizard-container .getting-started-wrapper{display:flex}.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 533px;margin:20px 20px 0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{padding-bottom:56.25%;margin-bottom:-60px;position:relative;height:0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper iframe{width:100%;height:100%;position:absolute;top:0;left:0}@media only screen and (max-width:1350px){.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 593px;margin:20px;align-self:center}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{margin-bottom:0}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}@media only screen and (max-width:1300px){.aioseo-setup-wizard-container .getting-started-wrapper{flex-direction:row;flex-wrap:wrap}.aioseo-setup-wizard-container .getting-started-wrapper .video{margin:20px 0 -60px}.aioseo-setup-wizard-container .getting-started-wrapper .text,.aioseo-setup-wizard-container .getting-started-wrapper .video{flex-basis:100%;width:100%}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions{justify-content:center}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:inherit;max-width:inherit;justify-content:center}}@media only screen and (max-width:782px){.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}.aioseo-setup-wizard-container .aioseo-row{position:relative;z-index:1}.aioseo-setup-wizard-container .wizard-actions .aioseo-col{display:flex;align-items:center}.aioseo-setup-wizard-container .wizard-actions .aioseo-button svg{width:16px;height:16px;margin-right:10px}.aioseo-setup-wizard-container .setup-wizard-bg{width:100%;height:100%;overflow:hidden;z-index:0;position:absolute;top:0;left:0}.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg,.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg rect{width:auto;height:100%}.aioseo-setup-wizard-container .close-wizard{color:#fff;width:20px;height:20px;position:absolute;right:20px;top:20px;z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-setup-wizard-container .close-wizard:hover{color:#ccc}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close{width:12px;height:12px;cursor:pointer;color:#fff}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close:hover{color:#dadada}.aioseo-setup-wizard-container p.how-to-get-started{margin:0}.aioseo-setup-wizard-container p.welcome-text{line-height:1.6}.aioseo-setup-wizard-container h2{color:#fff;line-height:1.4}.aioseo-setup-wizard-container a{color:#fff}.aioseo-setup-wizard-container svg.aioseo-book{width:20px;height:20px;margin:0 10px 0 0}.aioseo-setup-wizard-container .getting-started-video{padding-right:20px;margin-bottom:-60px;position:relative;height:0;padding-bottom:56.25%}.aioseo-setup-wizard-container .getting-started-video iframe{width:100%;height:100%;position:absolute;top:0;left:0}.aioseo-google-search-preview{padding:32px 30px;border:1px solid #e8e8eb}.aioseo-google-search-preview .domain{font-size:14px;line-height:1.3;color:#3c4043;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-google-search-preview .site-title{font-size:20px;line-height:1.3;color:#1a0dab;margin:3px 0}.aioseo-google-search-preview .meta-description{max-width:600px;font-size:14px;line-height:1.4;color:#52565a}.edit-post-sidebar .domain{font-size:13px}.edit-post-sidebar .site-title{font-size:16px}.edit-post-sidebar .meta-description{font-size:12px}.aioseo-modal-content .domain,.aioseo-modal-content .meta-description{font-size:14px}.aioseo-modal-content .site-title{font-size:20px}html:not([data-scroll="0"]) .aioseo-header{box-shadow:0 2px 5px rgba(0,0,0,.05);transition:box-shadow .6s}.aioseo-header{position:fixed;z-index:1051;top:0;right:0;left:0;background-color:#fff;height:72px;color:#141b38}.aioseo-header .mascot{width:35px;height:auto;margin-right:10px}.aioseo-header .aioseo-header-content{padding:0;display:flex;height:72px;align-items:center}.aioseo-header .aioseo-header-content svg.aioseo-logo{height:26px;margin-right:10px}.aioseo-header .aioseo-header-content .spacer{display:inline-flex;width:26.25px;height:0;border:1px solid #d0d1d7;transform:rotate(-72.26deg)}.aioseo-header .aioseo-header-content .page-name{display:inline-flex;margin-left:10px;font-size:18px;font-weight:400;flex:1 0 auto}.aioseo-header .aioseo-header-content .header-actions{display:flex}.aioseo-header .aioseo-header-content .header-actions .round{position:relative;background-color:#f3f4f5;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;margin-left:10px;cursor:pointer;transition:background-color .2s ease}.aioseo-header .aioseo-header-content .header-actions .round svg{width:20px;height:20px}.aioseo-header .aioseo-header-content .header-actions .round:hover{background-color:#e5e7e9}.aioseo-header .aioseo-header-content .header-actions .number{position:absolute;background-color:#df2a4a;width:16px;height:16px;font-weight:600;font-size:10px;color:#fff;top:-8px;left:50%;transform:translateX(-50%);margin:0;-webkit-animation:bounce 2s 5;animation:bounce 2s 5}.aioseo-header .aioseo-header-content .header-actions .number:hover{background-color:#df2a4a}@-webkit-keyframes bounce{0%,25%,50%,75%,to{transform:translateX(-50%) translateY(0)}40%{transform:translateX(-50%) translateY(-8px)}60%{transform:translateX(-50%) translateY(-4px)}}@keyframes bounce{0%,25%,50%,75%,to{transform:translateX(-50%) translateY(0)}40%{transform:translateX(-50%) translateY(-8px)}60%{transform:translateX(-50%) translateY(-4px)}}body.modal-open{overflow:hidden}.aioseo-help{display:block;position:fixed;top:0;bottom:0;left:0;right:0;height:100%;width:100vw;background-color:#fff;color:#8c8f9a;opacity:0;max-height:100vh;overflow-y:auto;transition:opacity .3s ease-in 0s;z-index:-999}.aioseo-help.visible{opacity:1;z-index:100000}.aioseo-help .aioseo-help-header{background:#fff;width:100%;height:60px;position:fixed;z-index:1;top:0;left:0}.aioseo-help .aioseo-help-docs{margin-bottom:25px;display:none}.aioseo-help .aioseo-help-docs li{padding:0 0 14px 4px;margin:0}.aioseo-help .aioseo-help-docs .aioseo-help-docs-viewall{margin:10px 0 0}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs{display:none}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs.opened{display:block}.aioseo-help .aioseo-help-docs .icon .aioseo-description{width:20px;margin-top:0;position:relative;top:5px;left:-5px;color:#8c8f9a}.aioseo-help .help-content{background-color:#fff;width:100%;max-width:740px;margin:0 auto 50px;padding:0 20px;box-sizing:border-box;z-index:1}.aioseo-help .help-content .aioseo-help-category{border-top:1px solid #e8e8eb;margin:0}.aioseo-help .help-content .aioseo-help-category:last-child{border-bottom:1px solid #e8e8eb}.aioseo-help .help-content .aioseo-help-category header{display:block;position:relative;cursor:pointer;width:100%;height:68px}.aioseo-help .help-content .aioseo-help-category header .title{display:block;font-size:16px;color:#8c8f9a;font-weight:600;padding:23px 11px 23px 30px}.aioseo-help .help-content .aioseo-help-category .folder-open{position:absolute;top:24px;width:20px;height:20px;color:#8c8f9a}.aioseo-help .help-content .aioseo-help-category .dashicons-arrow-right-alt2{position:absolute;top:20px;right:0;transition:transform .3s ease-out}.aioseo-help .help-content .aioseo-help-category.opened .aioseo-help-docs{display:block}.aioseo-help .help-content .aioseo-help-category.opened .dashicons-arrow-right-alt2{transform:rotate(90deg)}.aioseo-help .help-content #aioseo-help-search{position:relative;background-color:#fff;text-align:center;top:0;padding:74px 0 50px}.aioseo-help .help-content #aioseo-help-result .aioseo-help-docs{display:block}.aioseo-help .help-content #aioseo-help-footer{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;margin:50px 0 0}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer{display:block}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{box-sizing:border-box;max-width:325px;border:1px solid #8c8f9a;border-radius:6px;text-align:center}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{max-width:100%}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin-right:20px}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin:0 0 20px}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a{display:block;padding:25px;text-decoration:none;color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a h3{color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a span{font-size:16px;color:#005ae0;text-decoration:underline}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a:hover span{text-decoration:none}.aioseo-help .help-content #aioseo-help-footer .aioseo-description,.aioseo-help .help-content #aioseo-help-footer .aioseo-support{width:48px;margin-top:0;color:#8c8f9a}#aioseo-help-logo{position:fixed;width:132px;height:26px;top:20px;left:20px;z-index:2}#aioseo-help-close{position:fixed;width:20px;height:20px;top:30px;right:30px;cursor:pointer;opacity:.7;transition:all .05s;z-index:2}@media screen and (max-width:750px){#aioseo-help-close{top:20px;right:20px}}.aioseo-html-tags-editor .no-access{margin-bottom:20px}.aioseo-html-tags-editor .aioseo-description.tags-description{margin:0 0 20px}.aioseo-html-tags-editor .add-tags{display:flex;align-items:center;margin-bottom:20px}.aioseo-html-tags-editor .add-tags div{margin-right:10px}.aioseo-html-tags-editor .add-tags a{font-size:14px}.aioseo-html-tags-editor .add-tags a.no-underline{padding-left:10px}.aioseo-loading-spinner{width:35px;height:35px;position:absolute}.aioseo-loading-spinner .double-bounce1,.aioseo-loading-spinner .double-bounce2{width:100%;height:100%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;left:0;-webkit-animation:sk-bounce 1.3s ease-in-out infinite;animation:sk-bounce 1.3s ease-in-out infinite}.aioseo-loading-spinner.dark .double-bounce1,.aioseo-loading-spinner.dark .double-bounce2{background-color:#8c8f9a}.aioseo-loading-spinner .double-bounce2{-webkit-animation-delay:-.65s;animation-delay:-.65s}@-webkit-keyframes sk-bounce{0%,to{-webkit-transform:scale(0)}50%{-webkit-transform:scale(1)}}@keyframes sk-bounce{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}body.vue-build{margin:0}body.vue-build .aioseo-app{min-height:calc(100vh - 88px)}body.vue-build .aioseo-app .aioseo-main{padding-bottom:30px}body.aioseo-setup-wizard{margin:0;padding:0}body.aioseo-setup-wizard .aioseo-app{min-height:100vh;width:100%}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay{left:160px}body[class*=page_aioseo].folded .aioseo-header,body[class*=page_aioseo].folded .aioseo-notifications .overlay{left:36px}body[class*=page_aioseo] #wpcontent{padding:0;background-color:#f3f4f5}body[class*=page_aioseo] .update-nag{display:none}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 185px)}body[class*=page_aioseo].admin-bar.aioseo-has-bar .aioseo-app{min-height:calc(100vh - 225px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:32px}body[class*=page_aioseo] .aioseo-app{min-height:calc(100vh - 153px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-app{min-height:calc(100vh - 193px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:112px}@media screen and (max-width:782px){body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:132px}}@media screen and (max-width:960px){body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{left:36px}}@media screen and (max-width:782px){body[class*=page_aioseo] #wpbody-content{padding-bottom:20px}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 199px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:46px}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay,body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{left:0}}@media screen and (max-width:600px){body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{position:absolute;top:46px}}body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:128px}@media screen and (max-width:782px){body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:148px}}.aioseo-app{box-sizing:border-box;background-color:#f3f4f5}.aioseo-app .route-fade-enter-active,.aioseo-app .route-fade-leave-active{transition:all .2s}.aioseo-app .route-fade-enter,.aioseo-app .route-fade-leave-active{opacity:0}.aioseo-app .route-fade-enter{transform:translateX(30px)}.aioseo-app .route-fade-leave-active{transform:translateX(-30px)}.aioseo-app *,.aioseo-app :after,.aioseo-app :before{box-sizing:inherit}.aioseo-app * :not(.aioseo-button):not(.aioseo-input),.aioseo-app :after :not(.aioseo-button):not(.aioseo-input),.aioseo-app :before :not(.aioseo-button):not(.aioseo-input){line-height:1.4}.aioseo-app p{font-size:16px}.aioseo-app a:not(.aioseo-button){color:#005ae0}.aioseo-app a:not(.aioseo-button).text-white{color:#fff}.aioseo-app a:not(.aioseo-button).no-underline,.aioseo-app a:not(.aioseo-button):hover{text-decoration:none}.aioseo-app h2{font-size:32px;margin:0}.aioseo-app .aioseo-main{height:100%}.aioseo-app .aioseo-main>.aioseo-container{margin-top:88px}.aioseo-app .aioseo-main .save-changes{display:flex;justify-content:flex-end}.aioseo-app .d-flex{display:flex}.aioseo-app .aioseo-section-description{font-size:16px;color:#141b38;line-height:1.8;padding-bottom:30px}.aioseo-app .aioseo-description-text{font-size:14px;line-height:1.8;color:#141b38}.aioseo-app .aioseo-description-text.aioseo-error{color:#df2a4a}.aioseo-app .aioseo-description{font-size:14px;line-height:1.8;margin:8px 0 0;color:#141b38}.aioseo-app .aioseo-description.no-margin{margin:0}.aioseo-app .aioseo-description.aioseo-error{color:#df2a4a}.aioseo-app .max-recommended-count{color:#434960;text-align:right;margin-top:10px;font-size:14px}.aioseo-app .max-recommended-count strong.error{color:#df2a4a}.aioseo-app .popper{text-align:left;font-size:12px;padding:20px;background-color:#fff;border:none;border-radius:3px;box-shadow:0 3px 4.8px 0 rgba(32,71,102,.27);z-index:9999;max-width:350px;line-height:1.4}.aioseo-app .popper.action{padding:8px 12px;background-color:#141b38;color:#fff}.aioseo-app .popper.action .popper__arrow{border-top-color:#141b38}.aioseo-app .popper[x-placement^=bottom]{box-shadow:0 -2px 4.8px 0 rgba(32,71,102,.27)}.aioseo-app .popper .aioseo-description{margin:0}.aioseo-app .aioseo-row-highlight{-webkit-animation-name:color;animation-name:color;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-iteration-count:2;animation-iteration-count:2}@-webkit-keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}@keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}.aioseo-seo-site-score .aioseo-blur{display:flex;align-items:center}.aioseo-seo-site-score .aioseo-seo-site-score-cta{position:absolute;left:50%;top:50%;transform:translateX(-50%) translateY(-50%);background-color:#fff;padding:24px 30px;border:1px solid #e8e8eb;box-shadow:0 2px 10px rgba(0,90,224,.2);color:#141b38;font-size:16px;font-weight:600;width:82%;max-width:500px;text-align:center}.aioseo-app .aioseo-upgrade-bar{height:40px;background-color:#00aa63;display:flex;align-items:center;justify-content:center;color:#fff;font-size:13px;padding:0 14px 0 40px}.aioseo-app .aioseo-upgrade-bar .upgrade-text{display:flex;align-items:center;flex:1;justify-content:center}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow{font-size:15px;text-decoration:none}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow:hover{text-decoration:none}.aioseo-app .aioseo-upgrade-bar strong{font-weight:600}.aioseo-app .aioseo-upgrade-bar svg.aioseo-logo-gear{width:20px;height:20px;min-width:20px;margin-right:14px}.aioseo-app .aioseo-upgrade-bar svg.aioseo-close{cursor:pointer;width:12px;height:12px}.aioseo-app .aioseo-upgrade-bar a{color:#fff;text-decoration:underline}.aioseo-app .aioseo-upgrade-bar a:hover{text-decoration:none}@media screen and (max-width:782px){.aioseo-app .aioseo-upgrade-bar{padding:0 10px;height:60px}}.field-description[data-v-2bfc1de2]{display:inline-block;margin-top:10px;font-size:14px}.aioseo-address-wrapper[data-v-4bc9bbe6]{display:flex;max-width:500px}.field-description[data-v-4bc9bbe6]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4bc9bbe6]{margin-top:8px}.field-description[data-v-a0a894b8]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-a0a894b8]{margin-top:8px}.field-description[data-v-4fb4e044]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4fb4e044]{margin-top:8px}.field-description[data-v-85733554]{display:inline-block;margin-top:10px;font-size:14px}.field-description[data-v-515336a2]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-515336a2]{margin-top:8px}.field-description[data-v-78337de7]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-78337de7]{margin-top:8px}.aioseo-general-settings .more-tooltip-text strong{color:#00aa63}.aioseo-general-settings .license-cta-box{border-radius:3px;background-color:#f2f7fd;padding:20px;max-width:630px;margin:10px 0 30px}.aioseo-general-settings .license-cta-box a{color:#00aa63}.aioseo-general-settings .license-cta-box div{font-weight:600}.aioseo-general-settings .license-cta-box span{font-size:14px;font-style:italic}.aioseo-general-settings .license-key{margin-top:10px;display:flex;max-width:560px}.aioseo-general-settings .license-key .aioseo-input{margin-right:10px}.aioseo-app .aioseo-tabs.internal{margin-bottom:0}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation{margin-top:5px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button{height:60px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 25px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-ripple-wave{display:none}.aioseo-app .aioseo-tabs.skinny .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 16px}.aioseo-app .md-tabs{display:flex;flex-direction:column}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation{margin-top:2px;background:transparent;display:flex;position:relative;justify-content:flex-start}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation.md-elevation-0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button{color:#141b38;max-width:264px;min-width:72px;height:60px;margin:0;border-radius:0;font-size:15px;font-weight:500;padding:0;display:inline-block;position:relative;overflow:hidden;outline:none;background:transparent;border:0;transition:.4s cubic-bezier(.4,0,.2,1);font-family:inherit;line-height:normal;text-decoration:none;vertical-align:top;white-space:nowrap}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:before{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;transition:.4s cubic-bezier(.4,0,.2,1);will-change:background-color,opacity;content:" "}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 18px;display:flex;justify-content:center;align-items:center;width:100%;height:100%;position:relative;overflow:hidden;-webkit-mask-image:radial-gradient(circle,#fff 100%,#000 0);mask-image:radial-gradient(circle,#fff 100%,#000 0)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-button-content{position:static;z-index:2}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]){cursor:pointer}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]):active:before,.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]):hover:before{background-color:currentColor;opacity:.12}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button.md-active{color:#005ae0}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button.md-active:focus{outline:none;box-shadow:none}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator{height:2px;background-color:#005ae0;bottom:-2px;position:absolute;left:0;transform:translateZ(0);will-change:left,right}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator.md-tabs-indicator-left{transition:left .3s cubic-bezier(.4,0,.2,1),right .35s cubic-bezier(.4,0,.2,1)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator.md-tabs-indicator-right{transition:right .3s cubic-bezier(.4,0,.2,1),left .35s cubic-bezier(.4,0,.2,.1)}.aioseo-app .aioseo-tabs{display:flex;border-bottom:2px solid #e8e8eb;position:relative;margin-bottom:38px}.aioseo-app .aioseo-tabs .save-changes{position:absolute;right:0;bottom:10px}.aioseo-app .aioseo-tabs .tab-score{display:inline-flex;align-items:center;justify-content:flex-end;font-size:11px;font-weight:700;padding-left:12px}.aioseo-app .aioseo-tabs .tab-score.green{color:#00aa63}.aioseo-app .aioseo-tabs .tab-score.orange{color:#f18200}.aioseo-app .aioseo-tabs .tab-score.red{color:#df2a4a}.aioseo-app .aioseo-tabs .tab-score svg{display:inline;margin-right:7px}.aioseo-app .aioseo-mobile-tabs{position:relative;height:40px;margin-top:20px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.aioseo-app .aioseo-mobile-tabs .active-tab{color:#005ae0;padding-left:18px;min-height:100%;display:flex;align-items:center;cursor:pointer}.aioseo-app .aioseo-mobile-tabs .active-tab div{position:relative}.aioseo-app .aioseo-mobile-tabs .active-tab div span{height:2px;background-color:#005ae0;bottom:-7px;position:absolute;left:-18px;right:-18px;z-index:10}.aioseo-app .aioseo-mobile-tabs .active-tab svg.aioseo-caret{width:24px;height:24px;position:relative;top:6px;cursor:pointer;transition:transform .3s}.aioseo-app .aioseo-mobile-tabs .active-tab svg.aioseo-caret.rotated{transform:rotate(180deg)}.aioseo-app .aioseo-mobile-tabs .tab-dropdown{border:1px solid #e8e8eb;border-top:none}.aioseo-app .aioseo-mobile-tabs .tab-links{background:#fff;position:relative;z-index:3;padding:8px;width:100%;max-width:300px}@media screen and (max-width:782px){.aioseo-app .aioseo-mobile-tabs .tab-links{max-width:100%}}.aioseo-app .aioseo-mobile-tabs .tab-links a{padding:10px;display:block;color:#141b38;text-decoration:none}.aioseo-app .aioseo-mobile-tabs .tab-links a:hover{color:#005ae0}.md-tooltip{background-color:#141b38!important;color:#fff!important;border-radius:2px;padding:6px 12px;font-size:14px}.md-tooltip:after{content:"";position:absolute;top:100%;left:50%;margin-left:-5px;border:5px solid transparent;border-top-color:#141b38}.modal-mask{position:fixed;z-index:9998;top:0;left:0;width:100%;height:100%;background-color:rgba(20,27,56,.3);display:table;transition:opacity .3s ease}@media screen and (max-width:520px){.modal-mask{display:block;top:46px}}.modal-mask .modal-wrapper{display:table-cell;vertical-align:middle}@media screen and (max-width:520px){.modal-mask .modal-wrapper{display:block;height:100%}}.modal-mask .modal-wrapper .modal-container{width:100%;max-width:750px;max-height:90vh;overflow-y:hidden;overflow-x:hidden;margin:0 auto;background-color:#fff;box-shadow:0 10px 30px rgba(0,0,0,.15);transition:all .3s ease}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container{width:100%;max-width:100%;max-height:calc(100vh - 46px);height:100%}}.modal-mask .modal-wrapper .modal-container .modal-header{color:#141b38;position:sticky;top:0;z-index:15;padding:0 0 0 40px;height:70px;font-size:20px;font-weight:700;line-height:1.4;border-bottom:1px solid #e8e8eb;background-color:#fff;display:flex;align-items:center}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container .modal-header{padding:15px 0 0 20px}}.modal-mask .modal-wrapper .modal-container .modal-header button.close{position:absolute;right:11px;top:11px;width:24px;height:24px;background-color:#fff;border:none;display:flex;align-items:center}.modal-mask .modal-wrapper .modal-container .modal-header button.close svg.aioseo-close{cursor:pointer;width:14px;height:14px}.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-post-general,.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-post-social{height:calc(90vh - 120px);max-height:600px;overflow-y:auto;overflow-x:hidden}.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-modal-content.has-padding{padding:40px}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container .aioseo-modal-content,.modal-mask .modal-wrapper .modal-container .aioseo-modal-content>.component-wrapper,.modal-mask .modal-wrapper .modal-container .modal-body,.modal-mask .modal-wrapper .modal-container .modal-body>div{height:100%}.modal-mask .modal-wrapper .modal-container .aioseo-modal-content>.component-wrapper{display:flex;align-items:flex-end}.modal-mask .modal-wrapper .modal-container .aioseo-post-general,.modal-mask .modal-wrapper .modal-container .aioseo-post-social{height:100%!important;max-height:100%!important;padding:20px!important}.modal-mask .modal-wrapper .modal-container .aioseo-post-general .mobile-radio-buttons,.modal-mask .modal-wrapper .modal-container .aioseo-post-social .mobile-radio-buttons{margin-bottom:0}.modal-mask .modal-wrapper .modal-container .aioseo-add-template-tag{display:none}.modal-mask .modal-wrapper .modal-container .tab-facebook .aioseo-settings-row:last-of-type,.modal-mask .modal-wrapper .modal-container .tab-twitter .aioseo-settings-row:last-of-type{margin-bottom:64px!important;padding-bottom:32px!important}}.modal-enter,.modal-leave-active{opacity:0}.modal-enter .modal-container,.modal-leave-active .modal-container{transform:scale(1.1)}.aioseo-notification>div .body .title .date{font-weight:400;color:#8c8f9a;font-size:12px}.aioseo-notification-cards .aioseo-notification:last-child>div{border-bottom:none;margin-bottom:none}.aioseo-notification-cards .no-notifications{display:flex;align-items:center;flex-direction:column;padding-top:100px;font-size:16px;color:#8c8f9a}.aioseo-notification-cards .no-notifications img{width:30%;height:auto}.aioseo-notification-cards .no-notifications .great-scott{margin:20px 0 10px;font-size:24px;font-weight:600;color:#434960}.aioseo-notification-cards .no-notifications .no-new-notifications{margin-bottom:10px}.aioseo-notification{margin-bottom:20px}.aioseo-notification>div{display:flex;align-items:flex-start;padding-bottom:10px;border-bottom:1px solid #e8e8eb}.aioseo-notification>div .icon{margin-right:20px}.aioseo-notification>div .icon svg{width:20px;height:20px;color:#00aa63}.aioseo-notification>div .icon svg.warning{color:#f18200}.aioseo-notification>div .icon svg.info{color:#005ae0}.aioseo-notification>div .icon svg.success{color:#00aa63}.aioseo-notification>div .icon svg.error{color:#df2a4a}.aioseo-notification>div .body{margin-right:20px;flex:1}.aioseo-notification>div .body .title{font-size:16px;font-weight:600;color:#141b38;margin-bottom:7px;display:flex;align-items:center}.aioseo-notification>div .body .title div:first-child{flex:1;margin-right:5px;line-height:1.4}.aioseo-notification>div .body .notification-content{margin-bottom:10px;max-width:400px}.aioseo-notification>div .body .actions{flex-wrap:wrap;display:flex;align-items:center}.aioseo-notification>div .body .actions>*{margin-bottom:10px}.aioseo-notification>div .body .actions .aioseo-button{margin-right:20px}.aioseo-notification>div .body .actions .dismiss{color:#8c8f9a;font-size:14px}body.aioseo-show-notifications .aioseo-main{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-notifications a.dismiss{color:#8c8f9a;font-size:14px}.aioseo-notifications .notification-menu{height:100%;width:100%;max-width:570px;position:fixed;z-index:1053;top:0;right:0;bottom:0;background-color:#fff;overflow-x:hidden;transition:.5s}.aioseo-notifications .notification-menu .notification-header{height:70px;display:flex;align-items:center;padding:0 30px;color:#fff;background-color:#005ae0}.aioseo-notifications .notification-menu .notification-header .new-notifications{font-size:18px;font-weight:600}.aioseo-notifications .notification-menu .notification-header .dismissed-notifications{margin-left:25px;flex:1 1 auto}.aioseo-notifications .notification-menu .notification-header .dismissed-notifications a{font-size:14px;color:#fff}.aioseo-notifications .notification-menu .notification-header svg.aioseo-close{width:14px;height:14px;cursor:pointer}.aioseo-notifications .notification-menu .notification-header svg.aioseo-close:hover{color:#ccc}.aioseo-notifications .notification-menu .notification-cards{padding:30px;height:calc(100% - 192px);overflow:auto}.aioseo-notifications .notification-menu .notification-footer{height:90px;padding:30px;display:flex;align-items:center}.aioseo-notifications .notification-menu .notification-footer div.pagination{flex:1;display:flex;align-items:center}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number{font-size:13px;color:#141b38;background:#e8e8eb;height:30px;width:30px;display:flex;align-items:center;justify-content:center;border-radius:2px;margin-right:4px;cursor:pointer}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number:last-child{margin-right:0}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number.active,.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number:hover{color:#fff;background-color:#005ae0}.aioseo-notifications .overlay{position:fixed;z-index:1052;top:0;right:0;bottom:0;left:160px;background-color:#141b38;opacity:.5;transition:.5s}.aioseo-notifications .notifications-fade-enter-active,.aioseo-notifications .notifications-fade-leave-active{transition:opacity .5s}.aioseo-notifications .notifications-fade-enter,.aioseo-notifications .notifications-fade-leave-to{opacity:0}.aioseo-notifications .notifications-slide-enter-active,.aioseo-notifications .notifications-slide-leave-active{transition:all .5s ease-in-out}.aioseo-notifications .notifications-slide-enter,.aioseo-notifications .notifications-slide-leave-to{right:-570px}.aioseo-post-type-options-toggle{margin-top:20px}.aioseo-priority-score{max-width:350px}.aioseo-priority-score .header-row{font-size:14px}.aioseo-pro-badge{height:24px;border-radius:3px;background:#e8e8eb;color:#434960;font-size:14px;font-weight:600;display:inline-flex;padding:0 8px;align-items:center}.aioseo-score-settings{display:flex;align-items:center;padding-bottom:14px}.aioseo-score-settings svg{margin-right:7px}.aioseo-score-settings span{margin-right:12px}.aioseo-score-button{display:inline-block;padding:5px 8px;font-size:14px;font-weight:700;color:#a1a1a1;border:1px solid #a1a1a1;border-radius:3px}.aioseo-score-button.score-none,.aioseo-score-button.score-red{border-color:#df2a4a;color:#df2a4a!important}.aioseo-score-button.score-orange{border-color:#f18200;color:#f18200!important}.aioseo-score-button.score-green{border-color:#00aa63;color:#00aa63!important}.aioseo-score-button.classic-editor{background:#fff!important;display:inline-block!important;height:auto!important}.aioseo-score-button.classic-editor span{margin-right:0}.aioseo-seo-site-analysis-result{border:1px solid #dcdde1;margin-top:10px}.aioseo-seo-site-analysis-result .result-header{height:66px;padding:0 20px;display:flex;align-items:center}.aioseo-seo-site-analysis-result .result-header .result-icon{display:flex;align-items:center;margin-right:16px}.aioseo-seo-site-analysis-result .result-header .result-icon svg{width:24px;height:24px;color:#8c8f9a}.aioseo-seo-site-analysis-result .result-header .result-icon svg.passed{color:#00aa63}.aioseo-seo-site-analysis-result .result-header .result-icon svg.error{color:#df2a4a}.aioseo-seo-site-analysis-result .result-header .result-icon svg.warning{color:#005ae0}.aioseo-seo-site-analysis-result .result-header .result-content{font-size:16px;font-weight:600;flex:1}.aioseo-seo-site-analysis-result .result-header .result-toggle{width:30px;height:26px;border:1px solid #dcdde1;border-radius:3px;display:flex;align-items:center;justify-content:center;cursor:pointer}.aioseo-seo-site-analysis-result .result-header .result-toggle.active,.aioseo-seo-site-analysis-result .result-header .result-toggle:hover{background-color:#434960}.aioseo-seo-site-analysis-result .result-header .result-toggle.active svg,.aioseo-seo-site-analysis-result .result-header .result-toggle:hover svg{color:#fff}.aioseo-seo-site-analysis-result .result-header .result-toggle.active svg{transform:rotate(-180deg)}.aioseo-seo-site-analysis-result .result-header .result-toggle svg{width:100%;max-width:20px;height:auto;color:#8c8f9a;transform:rotate(-90deg);transition:transform .3s}.aioseo-seo-site-analysis-result .result-body{padding:0 60px 24px}.aioseo-seo-site-analysis-result .result-body .result-message{color:#434960;font-size:16px}.aioseo-seo-site-analysis-result .result-body .result-code-alt pre,.aioseo-seo-site-analysis-result .result-body .result-code pre{background:#f3f4f5;border-radius:3px;max-width:100%;padding:10px;overflow:auto}.aioseo-seo-site-analysis-result .result-body .result-code-alt pre code,.aioseo-seo-site-analysis-result .result-body .result-code pre code{padding:0;background:transparent}.aioseo-seo-site-analysis-result .result-body .result-code pre{white-space:pre-wrap}.aioseo-seo-site-analysis-result .result-body .result-action{margin-top:20px}.aioseo-seo-site-analysis-results .group-header{font-size:16px;font-weight:600}.aioseo-seo-site-analysis-results .group-header:not(:first-child){margin-top:30px}.aioseo-seo-site-analysis-results .group-keywords{display:flex;margin-top:5px;flex-wrap:wrap;align-items:center}.aioseo-seo-site-analysis-results .group-keywords .keyword{font-size:14px;color:#434960;font-weight:600;background:#f3f4f5;padding:9px 10px;border-radius:3px;margin:0 10px 5px 0}.aioseo-seo-site-analysis-results .group-keywords .keyword:first-child{font-size:20px}.aioseo-settings-row{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid #e8e8eb}.aioseo-settings-row.no-margin{margin-bottom:0}.aioseo-settings-row.small-padding{padding-bottom:5px}.aioseo-settings-row.medium-margin{margin-bottom:15px}.aioseo-settings-row.no-border{border:none}.aioseo-settings-row.no-side-margin{margin-left:0!important;margin-right:0!important}.aioseo-settings-row .settings-name{color:#141b38}.aioseo-settings-row .settings-name .name{font-weight:600;font-size:16px;display:flex;align-items:center}.aioseo-settings-row .settings-name .name.small-margin{margin-bottom:5px}.aioseo-settings-row .settings-name .name.align{line-height:40px}.aioseo-settings-row .settings-name .name.align-small{line-height:30px}.aioseo-settings-row .settings-name .name .aioseo-pro-badge{margin-left:10px}.aioseo-settings-row .settings-name .aioseo-description{margin-top:20px}.aioseo-settings-row .settings-content{font-size:16px}.aioseo-settings-row p.description{font-size:14px}.aioseo-separators{margin-top:-.5rem}.aioseo-separators .aioseo-col .separator{background-color:#f3f4f5;display:flex;align-items:center;justify-content:center;min-height:51px;font-weight:600;font-size:25px;border:1px solid #dcdde1;border-radius:3px;cursor:pointer}.aioseo-separators .aioseo-col .separator:hover{background-color:#e5e7e9}.aioseo-separators .aioseo-col .separator.active{background-color:#005ae0;border-color:#005ae0;color:#fff}.aioseo-separators .aioseo-col .separator.active:hover{background-color:#005ae0}.aioseo-separators .aioseo-col .show-more{height:100%;display:flex;align-items:center}.aioseo-separators .aioseo-col .show-more a{color:#8c8f9a}.aioseo-separators .aioseo-col .custom-separator{margin:20px 0;display:flex;align-items:center}.aioseo-separators .aioseo-col .custom-separator .aioseo-input{margin-left:10px;max-width:100px}.aioseo-sidebar-card .header{height:46px}.aioseo-sidebar-card .header:hover{cursor:pointer}.aioseo-sidebar-card .content{padding-bottom:8px!important}.aioseo-sidebar-card ul{margin-bottom:0}.aioseo-sidebar-card ul li{margin-bottom:16px;padding-left:25px}.aioseo-sidebar-card ul .description{margin:0}.aioseo-robots-meta .global-robots-settings{margin:0;padding-top:24px}.aioseo-robots-meta .global-robots-settings>.settings{padding:8px 0 16px}.aioseo-robots-meta .global-robots-settings-options{display:flex}.aioseo-robots-meta .global-robots-settings-options .max-snippet{margin-right:30px}.aioseo-robots-meta .global-robots-settings-options .max-snippet .aioseo-input{max-width:90px}.aioseo-robots-meta .global-robots-settings-options .max-video-preview{margin-right:30px}.aioseo-robots-meta .global-robots-settings-options .max-video-preview .aioseo-input{max-width:90px}.aioseo-robots-meta .global-robots-settings-options .max-image-preview .aioseo-select{min-width:155px}.aioseo-robots-meta .global-robots-settings-options>span{display:inline-block;margin-bottom:4px}@media screen and (max-width:782px){.aioseo-robots-meta .global-robots-settings-options{display:block}.aioseo-robots-meta .global-robots-settings-options .max-snippet,.aioseo-robots-meta .global-robots-settings-options .max-video-preview{margin-right:0;margin-bottom:20px}.aioseo-robots-meta .global-robots-settings-options>div .aioseo-input,.aioseo-robots-meta .global-robots-settings-options>div .aioseo-select{min-width:100%}}.edit-post-sidebar .global-robots-settings{padding-top:12px}.edit-post-sidebar .global-robots-settings>.settings{padding:4px 0 12px}.edit-post-sidebar .global-robots-settings>.settings label{font-size:16px}.edit-post-sidebar .global-robots-settings .robots-meta-title{padding-top:4px;display:inline-block}.edit-post-sidebar .global-robots-settings-options{flex-wrap:wrap}.edit-post-sidebar .max-snippet{margin-right:30px!important}.edit-post-sidebar .max-video-preview{margin-right:0!important}.edit-post-sidebar .max-image-preview{margin-top:20px!important}.aioseo-score-amount-wrapper{position:absolute;left:0;top:0;right:0;bottom:0;display:flex;align-items:center;justify-content:center;flex-direction:column;color:#141b38;margin:20px}.aioseo-score-amount-wrapper .aioseo-score-amount .score{font-size:64px;font-weight:600}.aioseo-score-amount-wrapper .aioseo-score-amount .total{font-size:18px;color:#8c8f9a;padding-left:3px}.aioseo-score-amount-wrapper .score-description{max-width:80%;text-align:center;font-size:17px;font-weight:600;line-height:1.1}.aioseo-score-amount-wrapper .score-analyzing{margin-top:20px;font-size:30px}.aioseo-site-score-analyze{position:relative;display:flex;align-items:center;justify-content:center;flex:1}.aioseo-site-score-analyze .analyze-errors{text-align:center;margin-bottom:1em}.aioseo-site-score-analyze .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-right:5em}.aioseo-site-score-analyze .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-analyze .aioseo-seo-site-score-description h2{line-height:1.4}.aioseo-site-score-analyze .aioseo-seo-site-score-description svg.aioseo-book{width:20px;height:20px;margin:0 10px 0 0;color:#005ae0}.aioseo-site-score-analyze .aioseo-seo-site-score-description>div{font-size:16px;color:#141b38;margin-bottom:10px}.aioseo-site-score-analyze .aioseo-seo-site-score-description .links{margin-top:30px;font-size:14px;font-weight:600}.aioseo-site-score-analyze .aioseo-seo-site-score-description .links .no-underline{padding-left:5px}.aioseo-site-score-competitor{position:relative;display:flex;align-items:center;justify-content:center;flex-direction:column}.aioseo-site-score-competitor .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-right:1em}.aioseo-site-score-competitor .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations{margin:20px 0}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links){display:flex;align-items:center;font-size:14px;color:#141b38;font-weight:600;margin-bottom:10px}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round{position:relative;border-radius:50%;width:24px;min-width:24px;max-width:24px;height:24px;display:flex;align-items:center;justify-content:center;margin-right:10px;font-size:12px;color:#fff;font-weight:600}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.red{background-color:#df2a4a}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.blue{background-color:#005ae0}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.orange{background-color:#f18200}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.green{background-color:#00aa63}.aioseo-site-score-competitor .refresh-results .aioseo-refresh{width:14px;height:14px;margin-right:10px}.aioseo-site-score-competitor .mobile-snapshot{margin-top:60px;max-width:250px}.aioseo-site-score-competitor .mobile-snapshot div{font-weight:600;font-size:16px;margin-bottom:10px}.aioseo-site-score-competitor .mobile-snapshot img{width:100%;height:auto}.aioseo-site-score-dashboard{position:relative;display:flex;align-items:center;justify-content:center}.aioseo-site-score-dashboard .analyze-errors{text-align:center;margin-bottom:1em}.aioseo-site-score-dashboard .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-right:1em}.aioseo-site-score-dashboard .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links){display:flex;align-items:center;font-size:14px;color:#141b38;font-weight:600;margin-bottom:10px}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round{position:relative;border-radius:50%;width:24px;min-width:24px;max-width:24px;height:24px;display:flex;align-items:center;justify-content:center;margin-right:10px;font-size:12px;color:#fff;font-weight:600}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.red{background-color:#df2a4a}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.blue{background-color:#005ae0}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.orange{background-color:#f18200}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.green{background-color:#00aa63}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations .links{margin-top:30px;font-size:14px;font-weight:600}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations .links .no-underline{padding-left:5px}.aioseo-social-profiles .same-username .use-same{padding:30px;background:#f9f9fa}.aioseo-social-profiles .same-username .use-same .aioseo-checkbox{font-size:16px}.aioseo-social-profiles .aioseo-social-profile-list,.aioseo-social-profiles .same-username .use-same .aioseo-settings-row,.aioseo-social-profiles .same-username .use-same .profiles{margin-top:20px}.aioseo-social-profiles .aioseo-social-profile-list .social-profile{margin-bottom:0;padding-bottom:0;border-bottom:none}.aioseo-social-profiles .aioseo-social-profile-list .social-profile .profile-error{margin-top:10px}.aioseo-social-profiles .aioseo-social-profile-list .social-profile .name{margin-bottom:0}.aioseo-social-profiles .aioseo-social-profile-list .social-profile img{height:16px;width:auto;margin-right:10px}.aioseo-tooltip{margin-left:14px;display:inline-flex}.aioseo-tooltip,.aioseo-twitter-preview{align-items:center;justify-content:center}.aioseo-twitter-preview{background-color:#f0f2f5;padding:30px;display:flex}.aioseo-twitter-preview .twitter-post{width:100%;max-width:500px;border-radius:5px;border:1px solid #e1e8ed;background-color:#fff}.aioseo-twitter-preview .twitter-post .twitter-header{height:65px;padding:0 18px;display:flex;align-items:center}.aioseo-twitter-preview .twitter-post .twitter-header .profile-photo{overflow:hidden;width:40px;height:40px;border:1px solid #e8e8eb;border-radius:50%}.aioseo-twitter-preview .twitter-post .twitter-header .profile-photo img{height:100%;width:100%}.aioseo-twitter-preview .twitter-post .twitter-header .poster{margin-left:10px;flex:1 0 auto}.aioseo-twitter-preview .twitter-post .twitter-header .poster .poster-name{font-size:15px;color:#1c2022;font-weight:600}.aioseo-twitter-preview .twitter-post .twitter-header .poster .poster-username{color:#697882;font-weight:500;font-size:13px}.aioseo-twitter-preview .twitter-post .twitter-container{padding:0 20px 20px}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content{flex-direction:row}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content .twitter-image-preview{display:flex;align-items:center;justify-content:center;background-color:#e1e8ed;min-width:125px;min-height:125px;background-size:cover;background-repeat:no-repeat;background-position:50%}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content .twitter-image-preview svg.aioseo-book{width:50px;height:50px;color:#8999a5}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content{border-radius:10px;overflow:hidden;display:flex;flex-direction:column;border:1px solid #e1e8ed}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content img{width:100%;height:auto}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description{padding:18px;color:#1c2022}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-domain{font-size:14px;color:#8899a6;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-title{font-size:15px;font-weight:600}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-description{font-size:14px;margin:5px 0}.aioseo-col .reverse{flex-direction:column-reverse}.aioseo-col.col-xs,.aioseo-col.col-xs-1,.aioseo-col.col-xs-2,.aioseo-col.col-xs-3,.aioseo-col.col-xs-4,.aioseo-col.col-xs-5,.aioseo-col.col-xs-6,.aioseo-col.col-xs-7,.aioseo-col.col-xs-8,.aioseo-col.col-xs-9,.aioseo-col.col-xs-10,.aioseo-col.col-xs-11,.aioseo-col.col-xs-12,.aioseo-col.col-xs-offset-0,.aioseo-col.col-xs-offset-1,.aioseo-col.col-xs-offset-2,.aioseo-col.col-xs-offset-3,.aioseo-col.col-xs-offset-4,.aioseo-col.col-xs-offset-5,.aioseo-col.col-xs-offset-6,.aioseo-col.col-xs-offset-7,.aioseo-col.col-xs-offset-8,.aioseo-col.col-xs-offset-9,.aioseo-col.col-xs-offset-10,.aioseo-col.col-xs-offset-11,.aioseo-col.col-xs-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-xs{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-xs-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-xs-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-xs-3{flex-basis:25%;max-width:25%}.aioseo-col.col-xs-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-xs-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-xs-6{flex-basis:50%;max-width:50%}.aioseo-col.col-xs-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-xs-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-xs-9{flex-basis:75%;max-width:75%}.aioseo-col.col-xs-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-xs-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-xs-12{flex-basis:100%;max-width:100%}.aioseo-col.col-xs-offset-0{margin-left:0}.aioseo-col.col-xs-offset-1{margin-left:8.33333333%}.aioseo-col.col-xs-offset-2{margin-left:16.66666667%}.aioseo-col.col-xs-offset-3{margin-left:25%}.aioseo-col.col-xs-offset-4{margin-left:33.33333333%}.aioseo-col.col-xs-offset-5{margin-left:41.66666667%}.aioseo-col.col-xs-offset-6{margin-left:50%}.aioseo-col.col-xs-offset-7{margin-left:58.33333333%}.aioseo-col.col-xs-offset-8{margin-left:66.66666667%}.aioseo-col.col-xs-offset-9{margin-left:75%}.aioseo-col.col-xs-offset-10{margin-left:83.33333333%}.aioseo-col.col-xs-offset-11{margin-left:91.66666667%}.aioseo-col.first-xs{order:-1}.aioseo-col.last-xs{order:1}.aioseo-col.text-xs-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-xs-center{text-align:center!important;justify-content:center}.aioseo-col.text-xs-right{text-align:right!important;justify-content:flex-end}.aioseo-col.p-0{padding:0!important}.aioseo-col.pt-0,.aioseo-col.py-0{padding-top:0!important}.aioseo-col.pr-0,.aioseo-col.px-0{padding-right:0!important}.aioseo-col.pb-0,.aioseo-col.py-0{padding-bottom:0!important}.aioseo-col.pl-0,.aioseo-col.px-0{padding-left:0!important}.aioseo-col.p-1{padding:.25rem!important}.aioseo-col.pt-1,.aioseo-col.py-1{padding-top:.25rem!important}.aioseo-col.pr-1,.aioseo-col.px-1{padding-right:.25rem!important}.aioseo-col.pb-1,.aioseo-col.py-1{padding-bottom:.25rem!important}.aioseo-col.pl-1,.aioseo-col.px-1{padding-left:.25rem!important}.aioseo-col.p-2{padding:.5rem!important}.aioseo-col.pt-2,.aioseo-col.py-2{padding-top:.5rem!important}.aioseo-col.pr-2,.aioseo-col.px-2{padding-right:.5rem!important}.aioseo-col.pb-2,.aioseo-col.py-2{padding-bottom:.5rem!important}.aioseo-col.pl-2,.aioseo-col.px-2{padding-left:.5rem!important}.aioseo-col.p-3{padding:1rem!important}.aioseo-col.pt-3,.aioseo-col.py-3{padding-top:1rem!important}.aioseo-col.pr-3,.aioseo-col.px-3{padding-right:1rem!important}.aioseo-col.pb-3,.aioseo-col.py-3{padding-bottom:1rem!important}.aioseo-col.pl-3,.aioseo-col.px-3{padding-left:1rem!important}.aioseo-col.p-4{padding:1.5rem!important}.aioseo-col.pt-4,.aioseo-col.py-4{padding-top:1.5rem!important}.aioseo-col.pr-4,.aioseo-col.px-4{padding-right:1.5rem!important}.aioseo-col.pb-4,.aioseo-col.py-4{padding-bottom:1.5rem!important}.aioseo-col.pl-4,.aioseo-col.px-4{padding-left:1.5rem!important}.aioseo-col.p-5{padding:3rem!important}.aioseo-col.pt-5,.aioseo-col.py-5{padding-top:3rem!important}.aioseo-col.pr-5,.aioseo-col.px-5{padding-right:3rem!important}.aioseo-col.pb-5,.aioseo-col.py-5{padding-bottom:3rem!important}.aioseo-col.pl-5,.aioseo-col.px-5{padding-left:3rem!important}@media only screen and (min-width:782px){.aioseo-col.col-sm,.aioseo-col.col-sm-1,.aioseo-col.col-sm-2,.aioseo-col.col-sm-3,.aioseo-col.col-sm-4,.aioseo-col.col-sm-5,.aioseo-col.col-sm-6,.aioseo-col.col-sm-7,.aioseo-col.col-sm-8,.aioseo-col.col-sm-9,.aioseo-col.col-sm-10,.aioseo-col.col-sm-11,.aioseo-col.col-sm-12,.aioseo-col.col-sm-offset-0,.aioseo-col.col-sm-offset-1,.aioseo-col.col-sm-offset-2,.aioseo-col.col-sm-offset-3,.aioseo-col.col-sm-offset-4,.aioseo-col.col-sm-offset-5,.aioseo-col.col-sm-offset-6,.aioseo-col.col-sm-offset-7,.aioseo-col.col-sm-offset-8,.aioseo-col.col-sm-offset-9,.aioseo-col.col-sm-offset-10,.aioseo-col.col-sm-offset-11,.aioseo-col.col-sm-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-sm{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-sm-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-sm-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-sm-3{flex-basis:25%;max-width:25%}.aioseo-col.col-sm-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-sm-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-sm-6{flex-basis:50%;max-width:50%}.aioseo-col.col-sm-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-sm-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-sm-9{flex-basis:75%;max-width:75%}.aioseo-col.col-sm-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-sm-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-sm-12{flex-basis:100%;max-width:100%}.aioseo-col.col-sm-offset-0{margin-left:0}.aioseo-col.col-sm-offset-1{margin-left:8.33333333%}.aioseo-col.col-sm-offset-2{margin-left:16.66666667%}.aioseo-col.col-sm-offset-3{margin-left:25%}.aioseo-col.col-sm-offset-4{margin-left:33.33333333%}.aioseo-col.col-sm-offset-5{margin-left:41.66666667%}.aioseo-col.col-sm-offset-6{margin-left:50%}.aioseo-col.col-sm-offset-7{margin-left:58.33333333%}.aioseo-col.col-sm-offset-8{margin-left:66.66666667%}.aioseo-col.col-sm-offset-9{margin-left:75%}.aioseo-col.col-sm-offset-10{margin-left:83.33333333%}.aioseo-col.col-sm-offset-11{margin-left:91.66666667%}.aioseo-col.first-sm{order:-1}.aioseo-col.last-sm{order:1}.aioseo-col.text-sm-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-sm-center{text-align:center!important;justify-content:center}.aioseo-col.text-sm-right{text-align:right!important;justify-content:flex-end}}@media only screen and (min-width:912px){.aioseo-col.col-md,.aioseo-col.col-md-1,.aioseo-col.col-md-2,.aioseo-col.col-md-3,.aioseo-col.col-md-4,.aioseo-col.col-md-5,.aioseo-col.col-md-6,.aioseo-col.col-md-7,.aioseo-col.col-md-8,.aioseo-col.col-md-9,.aioseo-col.col-md-10,.aioseo-col.col-md-11,.aioseo-col.col-md-12,.aioseo-col.col-md-offset-0,.aioseo-col.col-md-offset-1,.aioseo-col.col-md-offset-2,.aioseo-col.col-md-offset-3,.aioseo-col.col-md-offset-4,.aioseo-col.col-md-offset-5,.aioseo-col.col-md-offset-6,.aioseo-col.col-md-offset-7,.aioseo-col.col-md-offset-8,.aioseo-col.col-md-offset-9,.aioseo-col.col-md-offset-10,.aioseo-col.col-md-offset-11,.aioseo-col.col-md-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-md{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-md-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-md-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-md-3{flex-basis:25%;max-width:25%}.aioseo-col.col-md-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-md-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-md-6{flex-basis:50%;max-width:50%}.aioseo-col.col-md-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-md-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-md-9{flex-basis:75%;max-width:75%}.aioseo-col.col-md-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-md-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-md-12{flex-basis:100%;max-width:100%}.aioseo-col.col-md-offset-0{margin-left:0}.aioseo-col.col-md-offset-1{margin-left:8.33333333%}.aioseo-col.col-md-offset-2{margin-left:16.66666667%}.aioseo-col.col-md-offset-3{margin-left:25%}.aioseo-col.col-md-offset-4{margin-left:33.33333333%}.aioseo-col.col-md-offset-5{margin-left:41.66666667%}.aioseo-col.col-md-offset-6{margin-left:50%}.aioseo-col.col-md-offset-7{margin-left:58.33333333%}.aioseo-col.col-md-offset-8{margin-left:66.66666667%}.aioseo-col.col-md-offset-9{margin-left:75%}.aioseo-col.col-md-offset-10{margin-left:83.33333333%}.aioseo-col.col-md-offset-11{margin-left:91.66666667%}.aioseo-col.first-md{order:-1}.aioseo-col.last-md{order:1}.aioseo-col.text-md-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-md-center{text-align:center!important;justify-content:center}.aioseo-col.text-md-right{text-align:right!important;justify-content:flex-end}}@media only screen and (min-width:1042px){.aioseo-col.col-lg,.aioseo-col.col-lg-1,.aioseo-col.col-lg-2,.aioseo-col.col-lg-3,.aioseo-col.col-lg-4,.aioseo-col.col-lg-5,.aioseo-col.col-lg-6,.aioseo-col.col-lg-7,.aioseo-col.col-lg-8,.aioseo-col.col-lg-9,.aioseo-col.col-lg-10,.aioseo-col.col-lg-11,.aioseo-col.col-lg-12,.aioseo-col.col-lg-offset-0,.aioseo-col.col-lg-offset-1,.aioseo-col.col-lg-offset-2,.aioseo-col.col-lg-offset-3,.aioseo-col.col-lg-offset-4,.aioseo-col.col-lg-offset-5,.aioseo-col.col-lg-offset-6,.aioseo-col.col-lg-offset-7,.aioseo-col.col-lg-offset-8,.aioseo-col.col-lg-offset-9,.aioseo-col.col-lg-offset-10,.aioseo-col.col-lg-offset-11,.aioseo-col.col-lg-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-lg{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-lg-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-lg-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-lg-3{flex-basis:25%;max-width:25%}.aioseo-col.col-lg-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-lg-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-lg-6{flex-basis:50%;max-width:50%}.aioseo-col.col-lg-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-lg-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-lg-9{flex-basis:75%;max-width:75%}.aioseo-col.col-lg-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-lg-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-lg-12{flex-basis:100%;max-width:100%}.aioseo-col.col-lg-offset-0{margin-left:0}.aioseo-col.col-lg-offset-1{margin-left:8.33333333%}.aioseo-col.col-lg-offset-2{margin-left:16.66666667%}.aioseo-col.col-lg-offset-3{margin-left:25%}.aioseo-col.col-lg-offset-4{margin-left:33.33333333%}.aioseo-col.col-lg-offset-5{margin-left:41.66666667%}.aioseo-col.col-lg-offset-6{margin-left:50%}.aioseo-col.col-lg-offset-7{margin-left:58.33333333%}.aioseo-col.col-lg-offset-8{margin-left:66.66666667%}.aioseo-col.col-lg-offset-9{margin-left:75%}.aioseo-col.col-lg-offset-10{margin-left:83.33333333%}.aioseo-col.col-lg-offset-11{margin-left:91.66666667%}.aioseo-col.first-lg{order:-1}.aioseo-col.last-lg{order:1}.aioseo-col.text-lg-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-lg-center{text-align:center!important;justify-content:center}.aioseo-col.text-lg-right{text-align:right!important;justify-content:flex-end}}@media only screen and (min-width:1140px){.aioseo-col.col-xl,.aioseo-col.col-xl-1,.aioseo-col.col-xl-2,.aioseo-col.col-xl-3,.aioseo-col.col-xl-4,.aioseo-col.col-xl-5,.aioseo-col.col-xl-6,.aioseo-col.col-xl-7,.aioseo-col.col-xl-8,.aioseo-col.col-xl-9,.aioseo-col.col-xl-10,.aioseo-col.col-xl-11,.aioseo-col.col-xl-12,.aioseo-col.col-xl-offset-0,.aioseo-col.col-xl-offset-1,.aioseo-col.col-xl-offset-2,.aioseo-col.col-xl-offset-3,.aioseo-col.col-xl-offset-4,.aioseo-col.col-xl-offset-5,.aioseo-col.col-xl-offset-6,.aioseo-col.col-xl-offset-7,.aioseo-col.col-xl-offset-8,.aioseo-col.col-xl-offset-9,.aioseo-col.col-xl-offset-10,.aioseo-col.col-xl-offset-11,.aioseo-col.col-xl-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-xl{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-xl-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-xl-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-xl-3{flex-basis:25%;max-width:25%}.aioseo-col.col-xl-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-xl-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-xl-6{flex-basis:50%;max-width:50%}.aioseo-col.col-xl-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-xl-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-xl-9{flex-basis:75%;max-width:75%}.aioseo-col.col-xl-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-xl-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-xl-12{flex-basis:100%;max-width:100%}.aioseo-col.col-xl-offset-0{margin-left:0}.aioseo-col.col-xl-offset-1{margin-left:8.33333333%}.aioseo-col.col-xl-offset-2{margin-left:16.66666667%}.aioseo-col.col-xl-offset-3{margin-left:25%}.aioseo-col.col-xl-offset-4{margin-left:33.33333333%}.aioseo-col.col-xl-offset-5{margin-left:41.66666667%}.aioseo-col.col-xl-offset-6{margin-left:50%}.aioseo-col.col-xl-offset-7{margin-left:58.33333333%}.aioseo-col.col-xl-offset-8{margin-left:66.66666667%}.aioseo-col.col-xl-offset-9{margin-left:75%}.aioseo-col.col-xl-offset-10{margin-left:83.33333333%}.aioseo-col.col-xl-offset-11{margin-left:91.66666667%}.aioseo-col.first-xl{order:-1}.aioseo-col.last-xl{order:1}.aioseo-col.text-xl-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-xl-center{text-align:center!important;justify-content:center}.aioseo-col.text-xl-right{text-align:right!important;justify-content:flex-end}}.aioseo-container,.aioseo-container-fluid{margin-right:auto;margin-left:auto}.aioseo-container{padding:0 20px}.aioseo-container-fluid.hero,.aioseo-container.hero{min-height:100vh;display:flex;justify-content:center;align-items:center}.aioseo-container-fluid{padding-right:2rem;padding-left:2rem}@media only screen and (min-width:782px){.aioseo-container{padding:0 30px}}@media only screen and (min-width:1042px){.aioseo-container{max-width:80rem}.aioseo-container.full-width{max-width:100%}.aioseo-container.small{max-width:810px}}.aioseo-masonry{-moz-column-count:0;column-count:0;-moz-column-gap:20px;column-gap:20px;counter-reset:brick-counter}.aioseo-masonry>*{box-sizing:border-box;-moz-column-break-inside:avoid;break-inside:avoid;counter-increment:brick-counter;margin-bottom:20px}@media only screen and (min-width:782px){.aioseo-masonry{-moz-column-count:1;column-count:1}}@media only screen and (min-width:912px){.aioseo-masonry{-moz-column-count:2;column-count:2}}@media only screen and (min-width:1042px){.aioseo-masonry{-moz-column-count:3;column-count:3}}.aioseo-row{box-sizing:border-box;display:flex;flex:0 1 auto;flex-direction:row;flex-wrap:wrap;margin-right:-.5rem;margin-left:-.5rem}.aioseo-row.reverse{flex-direction:row-reverse}.aioseo-row.start-xs{justify-content:flex-start;text-align:start}.aioseo-row.center-xs{justify-content:center;text-align:center}.aioseo-row.end-xs{justify-content:flex-end;text-align:end}.aioseo-row.top-xs{align-items:flex-start}.aioseo-row.middle-xs{align-items:center}.aioseo-row.bottom-xs{align-items:flex-end}.aioseo-row.around-xs{justify-content:space-around}.aioseo-row.between-xs{justify-content:space-between}@media only screen and (min-width:782px){.aioseo-row.start-sm{justify-content:flex-start;text-align:start}.aioseo-row.center-sm{justify-content:center;text-align:center}.aioseo-row.end-sm{justify-content:flex-end;text-align:end}.aioseo-row.top-sm{align-items:flex-start}.aioseo-row.middle-sm{align-items:center}.aioseo-row.bottom-sm{align-items:flex-end}.aioseo-row.around-sm{justify-content:space-around}.aioseo-row.between-sm{justify-content:space-between}}@media only screen and (min-width:912px){.aioseo-row.start-md{justify-content:flex-start;text-align:start}.aioseo-row.center-md{justify-content:center;text-align:center}.aioseo-row.end-md{justify-content:flex-end;text-align:end}.aioseo-row.top-md{align-items:flex-start}.aioseo-row.middle-md{align-items:center}.aioseo-row.bottom-md{align-items:flex-end}.aioseo-row.around-md{justify-content:space-around}.aioseo-row.between-md{justify-content:space-between}}@media only screen and (min-width:1042px){.aioseo-row.start-lg{justify-content:flex-start;text-align:start}.aioseo-row.center-lg{justify-content:center;text-align:center}.aioseo-row.end-lg{justify-content:flex-end;text-align:end}.aioseo-row.top-lg{align-items:flex-start}.aioseo-row.middle-lg{align-items:center}.aioseo-row.bottom-lg{align-items:flex-end}.aioseo-row.around-lg{justify-content:space-around}.aioseo-row.between-lg{justify-content:space-between}}.aioseo-seo-site-score__circle{animation:aioseo-seo-site-score-fill 1s reverse;transform:rotate(-180deg);transform-origin:center;stroke:#00aa63}.aioseo-seo-site-score__circle.fast{-webkit-animation-duration:.5s;animation-duration:.5s;stroke:#df2a4a}.aioseo-seo-site-score__circle.medium{-webkit-animation-duration:.75s;animation-duration:.75s;stroke:#f18200}.aioseo-seo-site-score__background{stroke:#e8e8eb}@-webkit-keyframes aioseo-seo-site-score-fill{to{stroke-dasharray:0 100}}@keyframes aioseo-seo-site-score-fill{to{stroke-dasharray:0 100}}.aioseo-seo-site-score-svg-loading{-webkit-animation:aioseo-seo-site-score-svg-animation 2s linear infinite;animation:aioseo-seo-site-score-svg-animation 2s linear infinite}.aioseo-seo-site-score-loading__circle{-webkit-animation:aioseo-seo-site-score-fill-loading 2s ease-in-out infinite both;animation:aioseo-seo-site-score-fill-loading 2s ease-in-out infinite both;transform:rotate(-180deg);transform-origin:center;stroke:#005ae0}@-webkit-keyframes aioseo-seo-site-score-svg-animation{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes aioseo-seo-site-score-svg-animation{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@-webkit-keyframes aioseo-seo-site-score-fill-loading{0%,25%{stroke-dashoffset:90;transform:rotate(0)}50%,75%{stroke-dashoffset:10;transform:rotate(45deg)}to{stroke-dashoffset:90;transform:rotate(1turn)}}@keyframes aioseo-seo-site-score-fill-loading{0%,25%{stroke-dashoffset:90;transform:rotate(0)}50%,75%{stroke-dashoffset:10;transform:rotate(45deg)}to{stroke-dashoffset:90;transform:rotate(1turn)}}.aioseo-table-column{display:flex;flex-direction:column;flex-basis:100%;flex:1;padding:5px;justify-content:center}.aioseo-table-row{display:flex;flex-direction:row;flex-wrap:wrap;width:100%}.aioseo-wizard-body{background-color:#fff;max-width:900px;box-shadow:0 2px 5px rgba(0,0,0,.05)}.aioseo-wizard-body .body-content{padding:80px 140px}@media screen and (max-width:782px){.aioseo-wizard-body .body-content{padding:40px}}.aioseo-wizard-body .body-content .header{line-height:1.4}.aioseo-wizard-body .body-footer{border-top:1px solid #e8e8eb;padding:30px;display:flex;align-items:center}.aioseo-wizard-body .body-footer>*{margin-right:10px}.aioseo-wizard-body .body-footer>:last-child{margin-right:0}.aioseo-wizard-body .body-footer .spacer{flex:1 0 auto}.aioseo-wizard-close-and-exit{margin:96px 0;min-height:96px;text-align:center;font-size:14px}.aioseo-wizard-close-and-exit a{color:#8c8f9a!important}.aioseo-wizard-container{margin:40px auto;max-width:900px}@media screen and (max-width:782px){.aioseo-wizard-container{margin:0 20px}}.aioseo-wizard-header{display:flex;align-items:center;justify-content:center;flex-direction:column}.aioseo-wizard-header svg.aioseo-logo{width:100%;max-width:140px;height:auto;margin:60px 10px 40px 0}.aioseo-wizard-progress{display:flex;align-items:center;justify-content:center}@media screen and (max-width:782px){.aioseo-wizard-progress{display:none}}.aioseo-wizard-progress .circle{background-color:#dcdde1;width:16px;height:16px;border-radius:50%}.aioseo-wizard-progress .circle.active{background-color:#005ae0}.aioseo-wizard-progress .spacer{width:59px;border:1px solid #dcdde1;margin:0 12px}.aioseo-wizard-progress .spacer.active{border-color:#005ae0}.aioseo-wizard-steps{color:#8c8f9a;font-size:14px;margin-bottom:20px}.aioseo-localseo-info .aioseo-input,.aioseo-localseo-info .aioseo-multiselect,.aioseo-localseo-info .aioseo-select{max-width:480px}.aioseo-localseo-info .field-description{font-size:14px}.aioseo-localseo-info .info-businessaddress-row .columns{display:flex;flex:0 1 auto;flex-direction:row;flex-wrap:wrap}.aioseo-localseo-opening .field-description{display:inline-block;margin:10px 0;font-size:14px}.aioseo-localseo-opening .field-description.mt-8{margin-top:8px}.aioseo-localseo-opening .aioseo-input,.aioseo-localseo-opening .aioseo-multiselect,.aioseo-localseo-opening .aioseo-select{max-width:480px}.aioseo-localseo-opening .aioseo-col-flex{display:flex;align-items:center;padding:12px 0;border-bottom:1px solid #e8e8eb}.aioseo-localseo-opening .aioseo-col-flex:first-of-type{padding-top:0}.aioseo-localseo-opening .aioseo-col-flex:last-of-type{padding-bottom:0;border:none}.aioseo-localseo-opening .aioseo-col-flex .aioseo-col-day{flex:1}.aioseo-localseo-opening .aioseo-col-flex .aioseo-col-alwaysopen,.aioseo-localseo-opening .aioseo-col-flex .aioseo-col-hours{flex:2}.aioseo-localseo-opening .aioseo-col-flex span.separator{margin:0 5px}.aioseo-localseo-opening .aioseo-col-flex .aioseo-select{display:inline-block;max-width:120px;margin-bottom:5px}.aioseo-localseo-opening .aioseo-col-flex .multiselect--disabled .multiselect__single,.aioseo-localseo-opening .aioseo-col-flex .multiselect--disabled .multiselect__tags{background:#f3f4f5}.aioseo-localseo-opening .aioseo-col-alwaysopen .aioseo-checkbox{padding:0 10px}.sidebar-row{margin-bottom:16px}.sidebar-row .title{font-weight:700}
1
+ .aioseo-app .aioseo-cta{margin-top:30px;background:#fff;width:100%;padding:40px;box-shadow:0 2px 5px rgba(0,0,0,.05);border:1px solid #e8e8eb}.aioseo-app .aioseo-cta.floating{margin-top:0;position:absolute;max-width:850px;left:50%;top:50%;transform:translateX(-50%) translateY(-50%);box-shadow:0 5px 20px rgba(0,0,0,.1);border-radius:3px}.aioseo-app .aioseo-cta .header-text{line-height:1.4;font-weight:600;font-size:24px;text-align:center;color:#141b38}.aioseo-app .aioseo-cta .header-text span.large{line-height:1.4;font-size:32px}.aioseo-app .aioseo-cta .description{margin:30px 0 50px;width:100%;max-width:600px;text-align:center;font-size:16px;color:#141b38;line-height:1.4}.aioseo-app .aioseo-cta .description .aioseo-alert{margin-bottom:30px;text-align:left}.aioseo-app .aioseo-cta .feature-list{color:#141b38;font-size:16px;width:100%;max-width:500px;margin-bottom:50px}.aioseo-app .aioseo-cta .feature-list .aioseo-col{display:flex;align-items:flex-start}.aioseo-app .aioseo-cta .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:18px;min-width:18px;min-height:18px;margin-right:10px}.aioseo-app .aioseo-cta a.learn-more{margin-top:20px;color:#8c8f9a;font-size:14px}.aioseo-app .aioseo-cta .type-1{display:flex;flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2{margin:30px 0 30px 50px;display:flex}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:left}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-2>div{margin-right:20px;flex:0 0 50%}.aioseo-app .aioseo-cta .type-2 .featured-image{max-height:540px;border:1px solid #e8e8eb;flex:1;overflow:hidden;margin-right:-41px;margin-bottom:-71px;border-radius:5px 0 0}.aioseo-app .aioseo-cta .type-2 .featured-image img{max-height:600px}@media only screen and (max-width:912px){.aioseo-app .aioseo-cta .type-2{flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:center}.aioseo-app .aioseo-cta .type-2>div{text-align:center;margin-right:0;margin-bottom:30px;flex:1 0 100%;width:100%}.aioseo-app .aioseo-cta .type-2 .featured-image{margin:0 -10px -41px;border-radius:5px 5px 0 0;max-height:300px}}.aioseo-app .aioseo-cta .type-3 .sub-header{line-height:1.4;font-size:16px;font-weight:600;color:#005ae0;margin-bottom:5px}.aioseo-app .aioseo-cta .type-3 .header-text{text-align:left}.aioseo-app .aioseo-cta .type-3 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-3 .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:21px;min-width:21px;min-height:21px;margin-right:5px}.aioseo-app .aioseo-cta .type-3 .aioseo-button{margin-right:12px}.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:calc(200px + 1em)}@media only screen and (max-width:48em){.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:100%}}.aioseo-box-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-box-toggle input:checked+label{background-color:#fff;box-shadow:0 5px 10px rgba(0,90,224,.1);border:2px solid #005ae0;font-weight:600}.aioseo-box-toggle label{background-color:#f9f9fa;color:#141b38;font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;border:1px solid #f9f9fa;transition:all .1s ease-in-out;border-radius:3px;height:165px;position:relative}.aioseo-box-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-box-toggle label:hover{cursor:pointer}.aioseo-button{flex-shrink:0;line-height:1;display:inline-flex;align-items:center;justify-content:center;font-size:16px;font-weight:600;padding:0 24px;border-radius:4px;-webkit-appearance:none;cursor:pointer;height:48px;transition:background-color .2s ease;position:relative;overflow:hidden;text-decoration:none;color:#141b38;white-space:nowrap}.aioseo-button.small,.aioseo-button.small-table{height:30px;font-size:14px;padding:0 12px}.aioseo-button.small-table .loading-spinner,.aioseo-button.small .loading-spinner{width:25px;height:25px}.aioseo-button.small-table{font-size:12px;border-radius:3px}.aioseo-button.medium{height:40px;font-size:14px;padding:0 18px}.aioseo-button.medium .loading-spinner{width:35px;height:35px}.aioseo-button.xl{height:66px;border-radius:4px;font-size:18px;padding:0 48px}.aioseo-button.gray{border:1px solid #dcdde1;background-color:#f3f4f5}.aioseo-button.gray:hover{background-color:#fff;color:#141b38}.aioseo-button.gray:active{background-color:#f3f4f5}.aioseo-button.green{border:none;background-color:#00aa63;color:#fff}.aioseo-button.green:hover{background-color:#07c575}.aioseo-button.green:active{background-color:#15955f}.aioseo-button.blue{border:none;background-color:#005ae0;color:#fff}.aioseo-button.blue:hover{background-color:#1a82ea}.aioseo-button.blue:active{background-color:#004f9d}.aioseo-button.wp-blue{border:1px solid #005ae0;background-color:#f3f5f6;color:#005ae0}.aioseo-button.wp-blue:hover{background-color:#1a82ea;border-color:#1a82ea;color:#fff}.aioseo-button.wp-blue:active{background-color:#004f9d;border-color:#004f9d;color:#fff}.aioseo-button.black{border:none;background-color:#434960;color:#fff}.aioseo-button.black:hover{background-color:#2c324c}.aioseo-button.black:active{background-color:#141b38}.aioseo-button.red{border:1px solid #df2a4a;background-color:#fff;color:#df2a4a}.aioseo-button.red:hover{background-color:#df2a4a;color:#fff}.aioseo-button.red:active{background-color:#ab2039}.aioseo-button.loading.blue,.aioseo-button.loading.blue:hover{background-color:#004f9d;color:#004f9d}.aioseo-button.loading.green,.aioseo-button.loading.green:hover{background-color:#15955f;color:#15955f}.aioseo-button.loading.gray,.aioseo-button.loading.gray:hover{background-color:#f3f4f5;color:#f3f4f5}.aioseo-button.loading.black,.aioseo-button.loading.black:hover{background-color:#141b38;color:#141b38}.aioseo-button:disabled{border:1px solid #dcdde1;color:#8c8f9a;background-color:#f3f4f5;cursor:default}.aioseo-button:disabled.gray:hover{color:#8c8f9a}.aioseo-button:disabled.wp-blue{border-color:#ddd;background-color:#f7f7f7}.aioseo-button:disabled.wp-blue:hover{border-color:#ddd;color:#8c8f9a}.aioseo-button:disabled:hover{background-color:#f3f4f5}.aioseo-checkbox{display:inline-flex;align-items:center}.aioseo-checkbox.disabled,.aioseo-checkbox.disabled .form-checkbox .fancy-checkbox,.aioseo-checkbox.no-clicks,.aioseo-checkbox.no-clicks .form-checkbox .fancy-checkbox{cursor:default}.aioseo-checkbox .form-checkbox-wrapper{margin-right:10px;display:flex}.aioseo-checkbox.medium .form-checkbox{width:20px;height:20px}.aioseo-checkbox.medium .form-checkbox .fancy-checkbox svg{width:12px;height:12px}.aioseo-checkbox.medium .form-checkbox span:before{height:18px;width:18px;line-height:20px}.aioseo-checkbox.round .form-checkbox span,.aioseo-checkbox.round .form-checkbox span:before{border-radius:50%}.aioseo-checkbox .form-checkbox{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-checkbox .form-checkbox input{display:none}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.blue{background:#005ae0}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.green{background:#00aa63}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox:before{background:transparent}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox{background:#e8e8eb!important;border:1px solid #d0d1d7;cursor:default}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox svg{color:#8c8f9a}.aioseo-checkbox .form-checkbox input:not(:checked):disabled+.fancy-checkbox:before{left:0;bottom:0;background:#e8e8eb}.aioseo-checkbox .form-checkbox .fancy-checkbox svg{color:#fff;width:16px;height:16px}.aioseo-checkbox .form-checkbox span{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#d0d1d7;transition:.2s;border-radius:3px;display:flex;align-items:center;justify-content:center}.aioseo-checkbox .form-checkbox span:before{position:absolute;content:"";height:26px;width:26px;left:1px;bottom:1px;background-color:#fff;transition:.2s;font-size:18px;line-height:28px;border-radius:2px}.aioseo-date-picker.vue-daterange-picker{width:100%}.aioseo-date-picker.vue-daterange-picker .form-control{display:flex;align-items:center;color:#141b38;font-size:16px;height:48px;border-radius:3px;border:1px solid #d0d1d7;position:relative}.aioseo-date-picker.vue-daterange-picker .form-control svg.aioseo-circle-close{position:absolute;right:10px;color:#434960;width:15px;height:15px}.aioseo-date-picker.vue-daterange-picker.small .form-control{height:30px}.aioseo-date-picker.vue-daterange-picker.medium .form-control{height:40px}body[class*=all-in-one-seo_page] .daterangepicker .yearselect{width:75px}.aioseo-editor{position:relative}.aioseo-editor .aioseo-editor-description .ql-editor{min-height:100px}.aioseo-editor .aioseo-editor-line-numbers .ql-editor{padding:15px 15px 15px 45px}.aioseo-editor .aioseo-editor-single .ql-editor{padding:8px 10px}.aioseo-editor .aioseo-editor-single.aioseo-editor-line-numbers .ql-editor{padding:8px 10px 8px 45px}.aioseo-editor .aioseo-editor-monospace .ql-editor{font-family:monospace}.aioseo-editor .aioseo-line-numbers{background:#f7f6f7;position:absolute;text-align:right;top:1px;width:29px;left:1px;border-radius:3px 0 0 3px;padding:15px 9px 0 0;display:flex;height:calc(100% - 2px);flex-direction:column;overflow:hidden}.aioseo-editor .aioseo-line-numbers div{min-height:25px;color:#8c8f9a;font-size:12px;line-height:1.9}.aioseo-editor .ql-disabled{pointer-events:none;background-color:#f9f9fa}.aioseo-editor .ql-editor{padding:15px;border-radius:3px;font-size:16px;color:#141b38;border:1px solid #d0d1d7}.aioseo-editor .ql-editor:focus{border:1px solid #005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-editor .ql-editor .mention .ql-mention-denotation-char{display:none}.aioseo-editor .ql-editor .mention .aioseo-tag{height:25px;margin:0 1px;color:#434960;font-weight:600;font-size:14px;padding:3px 25px 3px 10px;background-color:#f3f4f5;border-radius:3px;cursor:pointer;position:relative;display:inline-flex;align-items:center}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle{display:inline-flex;align-items:center;background-color:#e8e8eb;position:absolute;top:0;right:0;bottom:0;border-radius:0 3px 3px 0}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret{width:18px;height:18px;transition:transform .3s}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret.rotated{transform:rotate(180deg)}.aioseo-editor .ql-mention-list-container{color:#141b38;background-color:#fff;max-width:250px;width:100%;margin-top:3px;border:1px solid #d0d1d7;border-radius:3px;box-shadow:0 3px 15px rgba(0,0,0,.1);z-index:9001}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom,.aioseo-editor .ql-mention-list-container .aioseo-tag-search{padding:12px;border-bottom:1px solid #e8e8eb}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom{display:none}.aioseo-editor .ql-mention-list-container .ql-mention-list{list-style:none;margin:0;padding:0;max-height:210px;overflow:auto}.aioseo-editor .ql-mention-list-container .ql-mention-list li{color:#141b38;margin:0;background-color:transparent;border-bottom:1px solid #e8e8eb;padding:15px;cursor:pointer;font-size:14px}.aioseo-editor .ql-mention-list-container .ql-mention-list li:last-child{border-bottom:0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover{color:#005ae0;background-color:#f2f7fd}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected .aioseo-tag-description,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover .aioseo-tag-description{color:initial}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item{display:flex}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item>div:first-child{margin-right:10px}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item .aioseo-tag-title{font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match{cursor:default;padding:12px;font-size:16px;font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match.highlight,.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match:hover{color:initial;background-color:transparent}.aioseo-editor .ql-toolbar{display:none}.aioseo-editor .ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.aioseo-editor .ql-snow .ql-hidden{display:none}.aioseo-editor .ql-container.ql-snow{border:none}.aioseo-editor .ql-container p{font-size:16px;margin:0;line-height:25px}.aioseo-highlight-toggle{border:1px solid #e8e8eb;border-radius:3px;min-height:48px;display:flex;align-items:center;padding:5px 10px;cursor:pointer}.aioseo-highlight-toggle>*{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-highlight-toggle.active{border-color:#005ae0;box-shadow:0 5px 10px rgba(0,90,224,.1)}.aioseo-highlight-toggle.medium{min-height:40px}.aioseo-highlight-toggle .icon{display:flex;align-items:center;margin-right:5px}.aioseo-input[data-v-3f0a80a7]{position:relative;width:100%}.aioseo-input.file[data-v-3f0a80a7],.aioseo-input.file input[type=file][data-v-3f0a80a7]{position:absolute;top:0;right:0;left:0;bottom:0;margin:0;padding:0}.aioseo-input.file input[type=file][data-v-3f0a80a7]{cursor:pointer;opacity:0}.aioseo-input.file input[type=file][data-v-3f0a80a7]::-webkit-file-upload-button{visibility:hidden}.aioseo-input.file input[type=file][data-v-3f0a80a7]:focus{box-shadow:none}.aioseo-input input[data-v-3f0a80a7]{height:48px;width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:3px;padding:15px;font-size:18px;position:relative;overflow:hidden;margin:0}.aioseo-input input[data-v-3f0a80a7]:disabled{background:#f9f9fa}.aioseo-input input[data-v-3f0a80a7]:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-input input[data-v-3f0a80a7]::-moz-placeholder{color:#8c8f9a}.aioseo-input input[data-v-3f0a80a7]:-ms-input-placeholder{color:#8c8f9a}.aioseo-input input[data-v-3f0a80a7]::placeholder{color:#8c8f9a}.aioseo-input input.prepend[data-v-3f0a80a7]{padding-left:50px}.aioseo-input input.append[data-v-3f0a80a7]{padding-right:50px}.aioseo-input input.small[data-v-3f0a80a7]{height:30px;padding:10px;font-size:14px}.aioseo-input input.small.prepend[data-v-3f0a80a7]{padding-left:30px}.aioseo-input input.small.append[data-v-3f0a80a7]{padding-right:30px}.aioseo-input input.medium[data-v-3f0a80a7]{height:40px;padding:12px;font-size:16px}.aioseo-input input.medium.prepend[data-v-3f0a80a7]{padding-left:35px}.aioseo-input input.medium.append[data-v-3f0a80a7]{padding-right:35px}.aioseo-input.aioseo-active input[data-v-3f0a80a7]{border-color:#00aa63}.aioseo-input.aioseo-active input[data-v-3f0a80a7]:active,.aioseo-input.aioseo-active input[data-v-3f0a80a7]:focus{box-shadow:0 0 0 1px #00aa63}.aioseo-input.aioseo-active .append-icon[data-v-3f0a80a7],.aioseo-input.aioseo-active .prepend-icon[data-v-3f0a80a7]{color:#00aa63}.aioseo-input.aioseo-error input[data-v-3f0a80a7]{border-color:#df2a4a}.aioseo-input.aioseo-error input[data-v-3f0a80a7]:active,.aioseo-input.aioseo-error input[data-v-3f0a80a7]:focus{box-shadow:0 0 0 1px #df2a4a}.aioseo-input.aioseo-error .append-icon[data-v-3f0a80a7],.aioseo-input.aioseo-error .prepend-icon[data-v-3f0a80a7]{color:#df2a4a}.aioseo-input.aioseo-warning input[data-v-3f0a80a7]{border-color:#f18200}.aioseo-input.aioseo-warning input[data-v-3f0a80a7]:active,.aioseo-input.aioseo-warning input[data-v-3f0a80a7]:focus{box-shadow:0 0 0 1px #f18200}.aioseo-input.aioseo-warning .append-icon[data-v-3f0a80a7],.aioseo-input.aioseo-warning .prepend-icon[data-v-3f0a80a7]{color:#f18200}.aioseo-input .prepend-icon[data-v-3f0a80a7]{position:absolute;top:0;left:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .prepend-icon svg[data-v-3f0a80a7]{width:30px;height:30px}.aioseo-input .prepend-icon.small[data-v-3f0a80a7]{width:20px}.aioseo-input .prepend-icon.small svg[data-v-3f0a80a7]{width:10px;height:10px}.aioseo-input .prepend-icon.medium[data-v-3f0a80a7]{width:15px}.aioseo-input .prepend-icon.medium svg[data-v-3f0a80a7]{width:15px;height:15px}.aioseo-input .append-icon[data-v-3f0a80a7]{position:absolute;top:0;right:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .append-icon svg[data-v-3f0a80a7]{width:30px;height:30px}.aioseo-input .append-icon.small[data-v-3f0a80a7]{width:10px}.aioseo-input .append-icon.medium[data-v-3f0a80a7]{width:15px}.aioseo-input .append-icon.clickable[data-v-3f0a80a7]{cursor:pointer;padding:0 5px;background:#f3f4f5;border:1px solid #d0d1d7;color:#434960;right:0;width:30px;border-radius:0 3px 3px 0}.aioseo-input .append-icon.clickable.small[data-v-3f0a80a7]{width:15px}.aioseo-input .append-icon.clickable.medium[data-v-3f0a80a7]{padding:0 10px;width:40px}.aioseo-phone-number{max-width:600px}.aioseo-phone-number label{display:none}.aioseo-phone-number .maz-input__input{height:40px;min-height:40px;padding-top:0!important;border:1px solid #d0d1d7}.aioseo-phone-number .maz-input__input:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .country-selector{flex:0 0 140px;width:140px;min-width:140px;max-width:140px}.aioseo-phone-number .country-selector:hover{z-index:1}.aioseo-phone-number .country-selector>div.maz-base-component.maz-input.has-value.has-1-right-icon.maz-input--primary>input{padding-left:50px!important}.aioseo-phone-number .country-selector .maz-input.is-focused{border-color:#005ae0}.aioseo-phone-number .country-selector .maz-select__options-list__item.selected.keyboard-selected{background-color:#005ae0}.aioseo-phone-number .maz-phone-number-input__country-flag{left:20px;bottom:12px;z-index:auto}.aioseo-phone-number .maz-input__icon{z-index:auto}.aioseo-phone-number .maz-select__options-list input{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .maz-input__input{border-radius:3px}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input{border-color:red}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input:focus{border-color:#df2a4a;box-shadow:0 0 0 1px #df2a4a}.aioseo-phone-number.validNumber div.maz-flex-1>div>input:focus{border-color:#00aa63;box-shadow:0 0 0 1px #00aa63}.aioseo-radio{display:inline-flex;align-items:center}.aioseo-radio .form-radio-wrapper{margin-right:10px;display:flex}.aioseo-radio.medium .form-radio{width:20px;height:20px}.aioseo-radio.medium .form-radio .fancy-radio svg{width:12px;height:12px}.aioseo-radio.medium.type-1 .form-radio span:before{height:18px;width:18px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:before{height:16px;width:16px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:after{height:6px;width:6px;left:6px;bottom:6px}.aioseo-radio .form-radio{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-radio .form-radio input{opacity:0}.aioseo-radio .form-radio input:checked+.fancy-radio{background:#005ae0;border-color:#005ae0}.aioseo-radio .form-radio input:checked+.fancy-radio:before{background:transparent}.aioseo-radio .form-radio input:checked+.fancy-radio:after{display:block}.aioseo-radio .form-radio input:disabled+.fancy-radio{cursor:default}.aioseo-radio .form-radio input:focus+.fancy-radio{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-radio .form-radio .fancy-radio{border-radius:50%}.aioseo-radio .form-radio .fancy-radio svg{color:#fff;width:16px;height:16px}.aioseo-radio .form-radio span{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;transition:.2s;border-radius:50%;display:flex;align-items:center;justify-content:center}.aioseo-radio .form-radio span:before{position:absolute;content:"";height:26px;width:26px;left:1px;bottom:1px;transition:.2s;font-size:18px;line-height:28px;border-radius:50%}.aioseo-radio.type-1 .form-radio span,.aioseo-radio.type-1 .form-radio span:before{background-color:#f3f4f5}.aioseo-radio.type-2 .form-radio span{border:1px solid #d0d1d7;background-color:#fff}.aioseo-radio.type-2 .form-radio span:before{background-color:#fff}.aioseo-radio.type-2 .form-radio span:after{display:none;position:absolute;content:"";height:10px;width:10px;left:8px;bottom:8px;background-color:#fff;transition:.2s;border-radius:50%}.aioseo-radio.disabled{cursor:default}.aioseo-radio.disabled.type-2 .form-radio input:checked+.fancy-radio{background-color:#e8e8eb;border-color:#d0d1d7}.aioseo-radio.disabled.type-2 .form-radio span,.aioseo-radio.disabled.type-2 .form-radio span:before{background-color:#e8e8eb}.aioseo-radio.disabled.type-2 .form-radio span:after{background-color:#8c8f9a}.aioseo-radio-toggle{display:flex;align-items:center;height:40px}.aioseo-radio-toggle div{height:100%}.aioseo-radio-toggle.inline{display:inline-flex}.aioseo-radio-toggle div:first-child{overflow:hidden;border-radius:3px 0 0 3px}.aioseo-radio-toggle div:first-child label{border-radius:3px 0 0 3px}.aioseo-radio-toggle div:last-child{overflow:hidden;border-radius:0 3px 3px 0}.aioseo-radio-toggle div:last-child label{border-radius:0 3px 3px 0}.aioseo-radio-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-radio-toggle input:checked+label{background-color:#005ae0;color:#fff}.aioseo-radio-toggle input:checked+label.dark{background-color:#434960;color:#fff}.aioseo-radio-toggle label{height:100%;background-color:#e8e8eb;color:#141b38;font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;transition:all .1s ease-in-out;position:relative;padding:11px 20px;font-weight:600}.aioseo-radio-toggle label.disabled{cursor:default;pointer-events:none;opacity:.5}.aioseo-radio-toggle label:hover{background-color:#dadadf;cursor:pointer}.aioseo-radio-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-radio-toggle.circle label{background:#fff;color:#8c8f9a}.aioseo-radio-toggle.circle input+label{border-radius:50%;width:36px;height:36px;padding:8px}.aioseo-radio-toggle.circle input:checked+label{background:#e8e8eb;color:#2c324c}.aioseo-select{height:48px}.aioseo-select.multiselect--disabled .multiselect__select{background:none}.aioseo-select .multiselect__select{display:flex;align-items:center;justify-content:center;min-height:46px}.aioseo-select .multiselect__select:before{display:none}.aioseo-select .multiselect__select svg.aioseo-caret{color:#141b38;width:18px;height:18px;transition:transform .3s}.aioseo-select .multiselect__tags{height:100%;border:1px solid #d0d1d7;border-radius:3px;display:flex;justify-content:center;flex-direction:column;padding:16px 40px 16px 16px}.aioseo-select .multiselect__tags .multiselect__spinner{height:calc(100% - 2px);border:2px solid transparent}.aioseo-select .multiselect__tags .multiselect__spinner:after,.aioseo-select .multiselect__tags .multiselect__spinner:before{border-top-color:#434960}.aioseo-select .multiselect__tags .multiselect__single{display:inline-flex;margin:0;padding:0;color:#141b38;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.aioseo-select .multiselect__tags .multiselect__placeholder{color:#8c8f9a;font-size:16px;line-height:20px;margin:0;padding:0}.aioseo-select .multiselect__tags .multiselect__input{padding:0;margin:0 10px 0 0;border-radius:0;border:none;color:#141b38;min-height:auto;line-height:20px}.aioseo-select .multiselect__tags .multiselect__input:focus{outline:0;box-shadow:none;border:none}.aioseo-select .multiselect__tags .multiselect__input::-moz-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input:-ms-input-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input::placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__tags-wrap{display:flex;align-items:center;flex-wrap:wrap}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag{padding:0;display:inline-flex;align-items:center;font-size:14px;font-weight:600;color:#434960;margin:0 3px 0 0;height:24px;background-color:#f3f4f5;flex-shrink:0}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-value{padding:0 5px 0 10px}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove{padding:0 10px;height:100%;cursor:pointer;background-color:#f3f4f5;display:flex;align-items:center}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover{background-color:#434960;color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover svg.aioseo-close{color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove svg.aioseo-close{color:#434960;width:10px;height:10px}.aioseo-select.multiselect--active .multiselect__tags-wrap{margin-bottom:7px}.aioseo-select.small{height:30px;min-height:30px}.aioseo-select.small .multiselect__tags{min-height:30px;padding:8px 38px 8px 8px}.aioseo-select.small .multiselect__tags .multiselect__placeholder{font-size:14px}.aioseo-select.small .multiselect__select{height:28px;min-height:28px}.aioseo-select.small .multiselect__input{font-size:14px}.aioseo-select.small .multiselect__content-wrapper li.multiselect__element .multiselect__option{font-size:14px;padding:8px;min-height:30px}.aioseo-select.medium{height:40px}.aioseo-select.medium .multiselect__tags{padding:7px 40px 7px 7px}.aioseo-select.medium .multiselect__select{min-height:38px}.aioseo-select.multiple{min-height:48px;height:auto}.aioseo-select.multiple.small{min-height:30px}.aioseo-select.multiple.medium{min-height:40px}.aioseo-select.multiselect--above .multiselect__content-wrapper{border-top:1px solid #d0d1d7;border-bottom:none}.aioseo-select .multiselect__content-wrapper{border:1px solid #d0d1d7;border-top:none;border-bottom-left-radius:3px;border-bottom-right-radius:3px;z-index:50;-webkit-overflow-scrolling:touch}.aioseo-select .multiselect__content-wrapper .multiselect__content{max-width:100%}.aioseo-select .multiselect__content-wrapper li.multiselect__element{margin:0;border-bottom:1px solid #e8e8eb}.aioseo-select .multiselect__content-wrapper li.multiselect__element.last{border-bottom:none}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight:after{background-color:#005ae0;color:#fff}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--selected{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--disabled{font-weight:400;background-color:#fff!important;color:#8c8f9a}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option .docLink{font-size:13px;float:right}.aioseo-textarea-autosize{width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:4px;font-size:16px;padding:12px}.aioseo-toggle{display:inline-flex}.aioseo-toggle:active,.aioseo-toggle:focus{outline:2px solid transparent}.aioseo-toggle.disabled{pointer-events:none}.aioseo-toggle.disabled .toggle-content{opacity:.5}.aioseo-toggle .toggle-content{position:relative;display:inline-block;width:36px;height:20px;margin-right:10px}.aioseo-toggle .toggle-content input{display:none}.aioseo-toggle .toggle-content input:checked+.toggle-switch{border:1px solid #005ae0;background-color:#005ae0}.aioseo-toggle .toggle-content input:checked+.toggle-switch:focus{outline:2px solid transparent}.aioseo-toggle .toggle-content input:checked+.toggle-switch:before{background-color:#fff;transform:translateX(15px)}.aioseo-toggle .toggle-content input:focus+.toggle-switch{box-shadow:0 0 1px #005ae0;outline:2px solid transparent}.aioseo-toggle .toggle-content .toggle-switch{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#fff;border:1px solid #d0d1d7;border-radius:15px;transition:.2s}.aioseo-toggle .toggle-content .toggle-switch:before{position:absolute;content:"";height:14px;width:14px;left:3px;bottom:2px;background-color:#d0d1d7;border-radius:50%;transition:.2s}.aioseo-wp-table input[type=search],.aioseo-wp-table select{border-color:#d0d1d7}.aioseo-wp-table select:focus{border-color:#005ae0;color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-wp-table select:hover{color:#005ae0}.aioseo-wp-table input.button,.aioseo-wp-table input.button:hover{color:#005ae0;border-color:#005ae0}.aioseo-wp-table .header .subsubsub{color:#555d66;font-size:13px;font-weight:600}.aioseo-wp-table .header .subsubsub>span{display:inline-flex}.aioseo-wp-table .header .subsubsub .separator{margin:0 5px}.aioseo-wp-table .header .subsubsub .active{font-weight:700;color:#141b38}.aioseo-wp-table .header .subsubsub a{text-decoration:none}.aioseo-wp-table .header .subsubsub a:hover{text-decoration:underline}.aioseo-wp-table .header .search{display:flex;justify-content:flex-end}.aioseo-wp-table .header .search .aioseo-input{width:100%;max-width:215px;margin-right:6px}.aioseo-wp-table .header .pagination{color:#555d66}.aioseo-wp-table .header .pagination .button,.aioseo-wp-table .header .pagination input{margin-left:6px}.aioseo-wp-table .tablenav-pages .current-page{padding:0 0 0 8px}.aioseo-wp-table .wp-table{width:100%;position:relative}.aioseo-wp-table .wp-table .loader-overlay{position:absolute;top:46px;right:0;bottom:36px;left:0;background:rgba(0,0,0,.3);z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-wp-table .wp-table .no-results{color:#8c8f9a;min-height:200px;display:flex;align-items:center;justify-content:center;font-weight:400;font-size:24px}.aioseo-wp-table .wp-table tr.even{background-color:#f9f9fa}.aioseo-wp-table .wp-table tr.enabled td,.aioseo-wp-table .wp-table tr.enabled td strong a{color:#141b38}.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td,.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td a.edit-link{color:#8c8f9a}.aioseo-wp-table .wp-table tr.edit-row th{padding:0 0 0 3px}.aioseo-wp-table .wp-table tr.edit-row td{padding:0 30px 0 10px}.aioseo-wp-table .wp-table tr td strong a{font-weight:400}.aioseo-wp-table .wp-table tr td .row-actions .edit a,.aioseo-wp-table .wp-table tr td strong a:hover{color:#005ae0}.aioseo-wp-table .wp-table tr td .row-actions .edit .trash a{color:#df2a4a}.aioseo-wp-table .wp-table tr td.edit-row-content .wrapper .border{margin-top:7px;padding:19px 0 20px;border-top:1px solid #e8e8eb}.custom-rules[data-v-191c51fe]{width:100%;margin-top:14px}.custom-rules .rule .rule-settings[data-v-191c51fe]{display:flex;flex-direction:row;align-items:center;flex:1}.custom-rules .rule .rule-settings>.aioseo-select[data-v-191c51fe]:first-child{width:100%;max-width:250px}.custom-rules .rule .rule-settings>[data-v-191c51fe]{margin:0 16px 0 0}.custom-rules .rule .rule-settings>[data-v-191c51fe]:last-child{margin-right:0}.custom-rules .rule .rule-settings>.aioseo-toggle[data-v-191c51fe]{margin:0 10px 0 4px}.custom-rules .rule .actions[data-v-191c51fe],.custom-rules .rule .logical[data-v-191c51fe]{flex:0}.custom-rules svg[data-v-191c51fe]{width:14px;height:14px;cursor:pointer}.custom-rules svg.aioseo-trash[data-v-191c51fe]{color:#dadada}.custom-rules svg.aioseo-trash[data-v-191c51fe]:hover{color:#df2a4a}.custom-rules .aioseo-tooltip[data-v-191c51fe]{margin:0;display:flex}.custom-rules .aioseo-button svg[data-v-191c51fe]{color:#fff;margin-right:6px}.aioseo-add-redirection.edit-url{margin-bottom:30px}.aioseo-add-redirection.edit-url .urls{align-items:flex-start}.aioseo-add-redirection.edit-url .urls .url-arrow{margin:-8px 30px 0}.aioseo-add-redirection.edit-url .advanced-settings-link{margin-top:21px}.aioseo-add-redirection .advanced-settings-link{text-decoration:underline!important}.aioseo-add-redirection.log-404 .urls .source{min-height:103px;align-items:flex-start}.aioseo-add-redirection .generic-error{margin-bottom:20px}.aioseo-add-redirection .aioseo-settings-row .settings-name .name{font-size:14px}.aioseo-add-redirection .urls{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .urls .break{flex-basis:100%;height:0}.aioseo-add-redirection .urls .url-arrow{width:36px;margin:-15px 30px 0;display:flex;align-items:center;justify-content:center}@media (min-width:1200px){.aioseo-add-redirection .urls .url-arrow{margin:-15px 50px 0}}.aioseo-add-redirection .urls .url-arrow svg{height:103px;color:#005ae0}.aioseo-add-redirection .urls .source,.aioseo-add-redirection .urls .target{flex:1;display:flex;align-items:center}.aioseo-add-redirection .urls .source>*,.aioseo-add-redirection .urls .target>*{flex:1}.aioseo-add-redirection .urls .source .aioseo-input,.aioseo-add-redirection .urls .target .aioseo-input{margin-bottom:12px}.aioseo-add-redirection .urls .target input{padding-right:30px}.aioseo-add-redirection .urls .target .append-icon{width:30px;justify-content:flex-end}.aioseo-add-redirection .urls .target .append-icon svg{max-width:16px;margin-right:5px}.aioseo-add-redirection .urls .target .append-icon svg:last-of-type{margin-right:0}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-add-redirection .urls .target .aioseo-description{height:30px}.aioseo-add-redirection .urls .target .target-url-error,.aioseo-add-redirection .urls .target .target-url-warning{margin-bottom:10px}.aioseo-add-redirection .settings{display:flex;flex-direction:column;align-items:center;margin-top:24px}.aioseo-add-redirection .settings .all-settings{width:100%}.aioseo-add-redirection .settings .all-settings .all-settings-content{display:flex;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .settings .all-settings .all-settings-content .advanced-settings-link{margin:16px 0 0 16px;color:#8c8f9a}@media (max-width:767px){.aioseo-add-redirection .settings .all-settings .all-settings-content{align-items:start}}.aioseo-add-redirection .settings>.actions{align-self:flex-end;margin-top:-50px}.aioseo-add-redirection .settings>.actions.advanced{margin-top:24px}.aioseo-add-redirection .settings .query-params,.aioseo-add-redirection .settings .redirect-type{margin-bottom:10px;flex:0 1 auto}.aioseo-add-redirection .settings .query-params .aioseo-select,.aioseo-add-redirection .settings .redirect-type .aioseo-select{margin-top:5px}.aioseo-add-redirection .settings .query-params{width:340px}.aioseo-add-redirection .settings .redirect-type{width:300px;margin-right:24px}.aioseo-add-redirection .settings .aioseo-button{align-self:flex-end}.aioseo-add-redirection .settings .cancel-edit-row{margin-left:10px}@media (min-width:1200px){.aioseo-add-redirection .settings .cancel-edit-row{margin-left:16px}}.aioseo-add-redirection-target-url,.aioseo-redirect-source-url{position:relative}.aioseo-redirect-source-url .aioseo-input input{padding-right:76px!important}.aioseo-redirect-source-url .aioseo-input .append-icon{width:60px;justify-content:flex-end}.aioseo-redirect-source-url .aioseo-input .append-icon svg{max-width:16px;margin-right:5px}.aioseo-redirect-source-url .aioseo-input .append-icon svg:last-of-type{margin-right:0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear:hover{color:#005ae0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash:hover{color:#df2a4a}.aioseo-redirect-source-url .source-url-error,.aioseo-redirect-source-url .source-url-warning{margin-bottom:10px}.aioseo-redirect-source-url .source-url-options>div{padding-bottom:5px}.aioseo-redirect-source-url .source-url-options>div>div{margin-bottom:5px}.aioseo-add-redirection-url-results{display:flex;position:absolute;background:#fff;width:100%;max-height:300px;overflow:auto;border:1px solid #d0d1d7;border-radius:3px;z-index:50;left:1px;margin-top:-9px}.aioseo-add-redirection-url-results ul{display:inline-block;max-width:100%;list-style:none;padding:0;margin:0;min-width:100%;vertical-align:top}.aioseo-add-redirection-url-results ul li{margin:0;border-bottom:1px solid #e8e8eb;display:block}.aioseo-add-redirection-url-results ul li:last-of-type{border-bottom:none}.aioseo-add-redirection-url-results ul li>span{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4;display:flex;padding:12px;min-height:40px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer}.aioseo-add-redirection-url-results ul li>span:hover{background-color:#f2f7fd}.aioseo-add-redirection-url-results ul li>span:hover .option-title{color:#005ae0}.aioseo-add-redirection-url-results .option{flex:1}.aioseo-add-redirection-url-results .option .option-title{font-weight:500;display:flex;font-size:16px;color:#141b38}.aioseo-add-redirection-url-results .option .option-title>div{margin-right:5px}.aioseo-add-redirection-url-results .option .option-title>div:first-of-type{display:inline-block}.aioseo-add-redirection-url-results .option .option-title .search-term{font-weight:700}.aioseo-add-redirection-url-results .option .option-details{display:flex;align-items:center;font-size:14px;color:#8c8f9a}.aioseo-add-redirection-url-results .option .option-details span{margin-right:15px}.aioseo-add-redirection-url-results .option-permalink{display:flex;align-items:center}.aioseo-add-redirection-url-results .option-permalink svg.aioseo-external{width:15px;height:15px;color:#434960}.aioseo-add-template-tag{border-radius:3px;padding:5px 10px;color:#141b38;font-size:14px;border:1px solid #e8e8eb;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-weight:600}.aioseo-add-template-tag:hover{background-color:#f3f4f5}.aioseo-add-template-tag svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-additional-pages .additional-pages-table{border:1px solid #d0d1d7;border-radius:3px;margin-bottom:20px}.aioseo-additional-pages .additional-pages-table .page-priority{max-width:110px}.aioseo-additional-pages .additional-pages-table .page-frequency{max-width:166px}.aioseo-additional-pages .additional-pages-table .page-last-modified{max-width:155px}.aioseo-additional-pages .additional-pages-table .page-actions{max-width:20px}.aioseo-additional-pages .additional-pages-table .page-actions .aioseo-tooltip{display:inline-block;margin:0}.aioseo-additional-pages .additional-pages-table .pages-header{height:50px;display:flex;font-size:14px;padding:0 30px;align-items:center;border-bottom:1px solid #d0d1d7}.aioseo-additional-pages .additional-pages-table .pages-header>div{flex:1 0 auto}.aioseo-additional-pages .additional-pages-table .pages-rows{font-size:14px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row{background-color:#fff;height:70px;display:flex;align-items:center;padding:0 30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row:last-of-type{border-radius:0 0 3px 3px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row.even{background-color:#f9f9fa}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div{flex:1 0 auto;padding-right:30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div:last-child{padding-right:0}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash{width:20px;height:20px;color:#8c8f9a;cursor:pointer;transition:color .1s ease}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash:hover{color:#df2a4a}.aioseo-additional-pages svg.aioseo-circle-plus{width:14px;height:14px;margin-right:10px}.aioseo-alert{position:relative;border-radius:3px;padding:24px;font-size:16px;color:#141b38;line-height:1.4}.aioseo-alert.small{padding:8px;font-size:13px}.aioseo-alert .aioseo-alert-close{cursor:pointer;position:absolute;top:-9px;right:-9px;width:18px;height:18px;border-radius:50%;padding:5px;display:inline-flex;justify-content:center;align-content:center}.aioseo-alert .aioseo-alert-close svg{width:100%;height:100%}.aioseo-alert.blue{border:1px solid #005ae0;background-color:#f2f7fd}.aioseo-alert.blue .aioseo-alert-close{background-color:#005ae0;color:#fff}.aioseo-alert.green{border:1px solid #00aa63;background-color:#f2fdf8}.aioseo-alert.green .aioseo-alert-close{background-color:#00aa63;color:#fff}.aioseo-alert.red{border:1px solid #df2a4a;background-color:#fbe9ec}.aioseo-alert.red .aioseo-alert-close{background-color:#df2a4a;color:#fff}.aioseo-alert.yellow{border:1px solid #f18200;background-color:#fcfae8}.aioseo-alert.yellow .aioseo-alert-close{background-color:#f18200;color:#fff}.aioseo-alert.no-border{border-width:0}.aioseo-alert.text-center{text-align:center}.aioseo-analyze-competitor-site-score{border:1px solid #00aa63;border-radius:3px;color:#00aa63;font-size:14px;padding:0 8px;height:24px;display:inline-flex;align-items:center;justify-content:center;margin-right:14px}.aioseo-analyze-competitor-site-score.red{color:#df2a4a;border-color:#df2a4a}.aioseo-analyze-competitor-site-score.orange{color:#f18200;border-color:#f18200}.aioseo-animated-dannie{display:flex;align-content:center;align-items:center;justify-content:center}.aioseo-animated-dannie svg{max-width:250px}.aioseo-api-bar{height:40px;background-color:#df2a4a;color:#fff;font-size:13px;padding:0 14px 0 40px}.aioseo-api-bar,.aioseo-api-bar .upgrade-text{display:flex;align-items:center;justify-content:center}.aioseo-api-bar .upgrade-text{flex:1}.aioseo-api-bar strong{font-weight:600}.aioseo-api-bar svg.aioseo-logo-gear{width:20px;height:20px;min-width:20px;margin-right:14px}.aioseo-api-bar svg.aioseo-close{cursor:pointer;width:12px;height:12px}.aioseo-api-bar a{color:#fff;text-decoration:underline}.aioseo-api-bar a:hover{text-decoration:none}@media screen and (max-width:782px){.aioseo-api-bar{padding:0 10px;height:60px}}.aioseo-attributes ul.aioseo-attributes-list[data-v-02af7dd2]{list-style:inside;list-style-type:disc;margin:20px 0 0}.aioseo-attributes ul.aioseo-attributes-list li[data-v-02af7dd2]{display:flex;margin-bottom:8px;align-items:flex-start}.aioseo-attributes ul.aioseo-attributes-list li div[data-v-02af7dd2]:first-of-type{flex:0 0 140px}.aioseo-blur{filter:blur(3px);pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-card{color:#141b38;background-color:#fff;border:1px solid #e8e8eb;box-shadow:0 2px 5px rgba(0,0,0,.05);margin:30px 0}.aioseo-card.disabled .content{background:#f9f9fa;font-size:16px;line-height:24px}@media only screen and (max-width:782px){.aioseo-card{margin:20px 0}}.aioseo-card svg.aioseo-circle-question-mark{width:17px;height:17px;color:#8c8f99;transition:background-color .2s ease}.aioseo-card svg.aioseo-circle-question-mark:hover{color:#5a5c65}.aioseo-card .header{display:flex;align-items:center;height:70px;padding:0 30px;font-weight:600;font-size:18px;border-bottom:1px solid #e8e8eb}.aioseo-card .header .header-icon{display:flex}.aioseo-card .header .header-icon svg{width:24px;height:24px;margin-right:16px}.aioseo-card .header .text{flex:1 0 auto;display:flex;align-items:center}.aioseo-card .header .text svg.aioseo-circle-question-mark{cursor:pointer;width:17px;height:17px}.aioseo-card .header .text .aioseo-pro-badge{margin-left:10px}.aioseo-card .header .text .card-score{display:flex;flex:1;align-items:center;justify-content:flex-end;padding-right:18px;font-size:13px}.aioseo-card .header .text .card-score.green{color:#00aa63}.aioseo-card .header .text .card-score.orange{color:#f18200}.aioseo-card .header .text .card-score.red{color:#df2a4a}.aioseo-card .header .text .card-score svg{margin-right:7px}.aioseo-card .header svg.aioseo-caret{width:24px;height:24px;cursor:pointer;transform:rotate(-180deg);transition:transform .3s}.aioseo-card .header svg.aioseo-caret.rotated{transform:rotate(-90deg)}.aioseo-card .header svg.aioseo-close{width:14px;height:14px;cursor:pointer}.aioseo-card .content{padding:30px;position:relative}.aioseo-card div.aioseo-settings-row:last-child{margin-bottom:0;border-bottom:none;padding-bottom:0}.aioseo-copy-block{display:inline-flex}.aioseo-copy-block .message{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-radius:3px 0 0 3px;padding:10px 24px;font-weight:600}.aioseo-copy-block .copy-tooltip{display:flex}.aioseo-copy-block .copy{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-left-width:0;border-radius:0 3px 3px 0;padding:10px 16px;font-weight:600;cursor:pointer}.aioseo-copy-block .copy:hover svg.aioseo-copy{color:#a7a7a7}.aioseo-copy-block .copy svg.aioseo-copy{width:20px;height:20px;color:#dadada}.aioseo-copy-block .copy svg.aioseo-circle-check-solid{width:20px;height:20px;color:#00aa63}.aioseo-display-info .aioseo-box-toggle svg{margin-top:-15px;color:#434960}.aioseo-display-info svg.aioseo-new-page,.aioseo-display-info svg.aioseo-shortcode,.aioseo-display-info svg.aioseo-widget{width:100%;height:auto;max-width:60px}.aioseo-display-info svg.aioseo-gutenberg-block{width:59px;height:54px}.aioseo-display-info svg.aioseo-gutenberg-block rect{width:100%;width:56px;height:51px}.aioseo-display-info svg.aioseo-php{width:110px}.aioseo-display-info .copy-box,.aioseo-display-info .extra-box{margin-top:10px;padding:30px;border-radius:3px;background-color:#f9f9fa}.aioseo-display-info .copy-box .aioseo-description,.aioseo-display-info .extra-box .aioseo-description{margin:0}.aioseo-display-info .copy-box .aioseo-copy-block,.aioseo-display-info .extra-box .aioseo-copy-block{margin:20px 0 0}.aioseo-display-info .copy-box .advanced-settings-link,.aioseo-display-info .extra-box .advanced-settings-link{display:inline-block;padding-top:5px;margin:16px 0 0 16px;color:#8c8f9a;text-decoration:underline;font-size:13px}.aioseo-display-info .copy-box .advanced-settings-link:hover,.aioseo-display-info .extra-box .advanced-settings-link:hover{text-decoration:none}.aioseo-display-info .copy-box .advanced-settings,.aioseo-display-info .extra-box .advanced-settings{padding-top:20px}.aioseo-display-info .advanced-settings.advanced-settings-hidden{display:none}.aioseo-display-info .aioseo-tooltip{margin-left:0}.aioseo-exclude-posts{display:flex}.aioseo-facebook-preview{background-color:#f0f2f5;padding:30px;display:flex;align-items:center;justify-content:center}.aioseo-facebook-preview .facebook-post{width:100%;max-width:525px;border-radius:10px;box-shadow:0 2px 5px rgba(0,0,0,.1);background-color:#fff}.aioseo-facebook-preview .facebook-post .facebook-header{height:65px;padding:0 18px;display:flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo{overflow:hidden;width:40px;height:40px;border:1px solid #e8e8eb;border-radius:50%}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo img{height:100%;width:100%}.aioseo-facebook-preview .facebook-post .facebook-header .poster{margin-left:10px;flex:1 0 auto}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-name{font-size:15px;color:#050505;font-weight:500}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-date{color:#65676b;font-size:13px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis{display:inline-flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div{background-color:#5e666f;width:4px;height:4px;border-radius:50%;margin:0 2px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:first-child{margin-left:0}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:last-child{margin-right:0}.aioseo-facebook-preview .facebook-post .facebook-content{display:flex;flex-direction:column}.aioseo-facebook-preview .facebook-post .facebook-content img{width:100%;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content.vertical{flex-direction:row}.aioseo-facebook-preview .facebook-post .facebook-content.vertical img{max-width:158px;max-height:158px;width:auto;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description{flex:1;background-color:#f2f3f5;padding:9px 13px;color:#606770}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-domain{font-size:13px;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-title{color:#1d2129;font-size:17px;font-weight:600;margin:5px 0}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-description{font-size:14px}.aioseo-facebook-preview .facebook-post .facebook-footer{height:24px}.aioseo-feature-card{height:100%;border:1px solid #e8e8eb;background:#fff;box-shadow:0 2px 5px rgba(0,0,0,.05);color:#141b38;display:flex;flex-direction:column}.aioseo-feature-card .feature-card-body{padding:30px 30px 20px;flex:1}.aioseo-feature-card .feature-card-body.static{padding:30px}.aioseo-feature-card .feature-card-body .feature-card-header{display:flex;align-items:center;font-size:18px;font-weight:600;margin-bottom:16px}.aioseo-feature-card .feature-card-body .feature-card-header img,.aioseo-feature-card .feature-card-body .feature-card-header svg{width:28px;height:28px;margin-right:10px}.aioseo-feature-card .feature-card-body .feature-card-description{color:#434960;font-size:15px}.aioseo-feature-card .feature-card-body .feature-card-description .learn-more{margin-top:10px}.aioseo-feature-card .feature-card-footer{padding:15px}.aioseo-feature-card .feature-card-footer:not(.upgrade-required){border:2px solid #fff;background-color:#f9f9fa;padding:12px;min-height:43px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate{display:flex;align-items:center;justify-content:flex-end;height:30px;position:relative}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-loading-spinner{position:absolute;left:0}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .status{font-weight:600;font-size:14px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-toggle .toggle-content{margin-right:0;margin-left:10px}.aioseo-feature-card .feature-card-footer .feature-card-upgrade-cta{display:flex;align-items:center;justify-content:flex-end}.aioseo-feature-card .feature-card-footer.installed .feature-card-install-activate .status{color:#8c8f9a}.aioseo-setup-wizard-container{margin-top:30px;margin-bottom:50px;padding:30px;color:#fff;position:relative;background-color:#005ae0}@media only screen and (max-width:782px){.aioseo-setup-wizard-container{margin-top:20px}}.aioseo-setup-wizard-container p{color:#fff}.aioseo-setup-wizard-container .getting-started-wrapper{display:flex}.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 533px;margin:20px 20px 0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{padding-bottom:56.25%;margin-bottom:-60px;position:relative;height:0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper iframe{width:100%;height:100%;position:absolute;top:0;left:0}@media only screen and (max-width:1350px){.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 593px;margin:20px;align-self:center}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{margin-bottom:0}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}@media only screen and (max-width:1300px){.aioseo-setup-wizard-container .getting-started-wrapper{flex-direction:row;flex-wrap:wrap}.aioseo-setup-wizard-container .getting-started-wrapper .video{margin:20px 0 -60px}.aioseo-setup-wizard-container .getting-started-wrapper .text,.aioseo-setup-wizard-container .getting-started-wrapper .video{flex-basis:100%;width:100%}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions{justify-content:center}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:inherit;max-width:inherit;justify-content:center}}@media only screen and (max-width:782px){.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}.aioseo-setup-wizard-container .aioseo-row{position:relative;z-index:1}.aioseo-setup-wizard-container .wizard-actions .aioseo-col{display:flex;align-items:center}.aioseo-setup-wizard-container .wizard-actions .aioseo-button svg{width:16px;height:16px;margin-right:10px}.aioseo-setup-wizard-container .setup-wizard-bg{width:100%;height:100%;overflow:hidden;z-index:0;position:absolute;top:0;left:0}.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg,.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg rect{width:auto;height:100%}.aioseo-setup-wizard-container .close-wizard{color:#fff;width:20px;height:20px;position:absolute;right:20px;top:20px;z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-setup-wizard-container .close-wizard:hover{color:#ccc}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close{width:12px;height:12px;cursor:pointer;color:#fff}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close:hover{color:#dadada}.aioseo-setup-wizard-container p.how-to-get-started{margin:0}.aioseo-setup-wizard-container p.welcome-text{line-height:1.6}.aioseo-setup-wizard-container h2{color:#fff;line-height:1.4}.aioseo-setup-wizard-container a{color:#fff}.aioseo-setup-wizard-container svg.aioseo-book{width:20px;height:20px;margin:0 10px 0 0}.aioseo-setup-wizard-container .getting-started-video{padding-right:20px;margin-bottom:-60px;position:relative;height:0;padding-bottom:56.25%}.aioseo-setup-wizard-container .getting-started-video iframe{width:100%;height:100%;position:absolute;top:0;left:0}.aioseo-google-search-preview{padding:32px 30px;border:1px solid #e8e8eb}.aioseo-google-search-preview .domain{font-size:14px;line-height:1.3;color:#3c4043;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-google-search-preview .site-title{font-size:20px;line-height:1.3;color:#1a0dab;margin:3px 0}.aioseo-google-search-preview .meta-description{max-width:600px;font-size:14px;line-height:1.4;color:#52565a}.edit-post-sidebar .domain,.editor-post-publish-panel .domain{font-size:13px}.edit-post-sidebar .site-title,.editor-post-publish-panel .site-title{font-size:16px}.edit-post-sidebar .meta-description,.editor-post-publish-panel .meta-description{font-size:12px}.aioseo-modal-content .domain,.aioseo-modal-content .meta-description{font-size:14px}.aioseo-modal-content .site-title{font-size:20px}html:not([data-scroll="0"]) .aioseo-header{box-shadow:0 2px 5px rgba(0,0,0,.05);transition:box-shadow .6s}.aioseo-header{position:fixed;z-index:1051;top:0;right:0;left:0;background-color:#fff;height:72px;color:#141b38}.aioseo-header .mascot{width:35px;height:auto;margin-right:10px}.aioseo-header .aioseo-header-content{padding:0;display:flex;height:72px;align-items:center}.aioseo-header .aioseo-header-content a:focus{box-shadow:none}.aioseo-header .aioseo-header-content svg.aioseo-logo{height:26px;margin-right:10px}.aioseo-header .aioseo-header-content .spacer{display:inline-flex;width:26.25px;height:0;border:1px solid #d0d1d7;transform:rotate(-72.26deg)}.aioseo-header .aioseo-header-content .page-name{display:inline-flex;margin-left:10px;font-size:18px;font-weight:400;flex:1 0 auto}.aioseo-header .aioseo-header-content .header-actions{display:flex}.aioseo-header .aioseo-header-content .header-actions .round{position:relative;background-color:#f3f4f5;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;margin-left:10px;cursor:pointer;transition:background-color .2s ease}.aioseo-header .aioseo-header-content .header-actions .round svg{width:20px;height:20px}.aioseo-header .aioseo-header-content .header-actions .round:hover{background-color:#e5e7e9}.aioseo-header .aioseo-header-content .header-actions .number{position:absolute;background-color:#df2a4a;width:16px;height:16px;font-weight:600;font-size:10px;color:#fff;top:-8px;left:50%;transform:translateX(-50%);margin:0;-webkit-animation:bounce 2s 5;animation:bounce 2s 5}.aioseo-header .aioseo-header-content .header-actions .number:hover{background-color:#df2a4a}@-webkit-keyframes bounce{0%,25%,50%,75%,to{transform:translateX(-50%) translateY(0)}40%{transform:translateX(-50%) translateY(-8px)}60%{transform:translateX(-50%) translateY(-4px)}}@keyframes bounce{0%,25%,50%,75%,to{transform:translateX(-50%) translateY(0)}40%{transform:translateX(-50%) translateY(-8px)}60%{transform:translateX(-50%) translateY(-4px)}}body.modal-open{overflow:hidden}.aioseo-help{display:block;position:fixed;top:0;bottom:0;left:0;right:0;height:100%;width:100vw;background-color:#fff;color:#8c8f9a;opacity:0;max-height:100vh;overflow-y:auto;transition:opacity .3s ease-in 0s;z-index:-999}.aioseo-help.visible{opacity:1;z-index:100000}.aioseo-help .aioseo-help-header{background:#fff;width:100%;height:60px;z-index:1;padding:20px;display:flex}.aioseo-help .aioseo-help-header>.logo{flex:1}.aioseo-help .aioseo-help-docs{margin-bottom:25px;display:none}.aioseo-help .aioseo-help-docs li{padding:0 0 14px 4px;margin:0}.aioseo-help .aioseo-help-docs .aioseo-help-docs-viewall{margin:10px 0 0}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs{display:none}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs.opened{display:block}.aioseo-help .aioseo-help-docs .icon .aioseo-description{width:20px;margin-top:0;position:relative;top:5px;left:-5px;color:#8c8f9a}.aioseo-help .help-content{background-color:#fff;width:100%;max-width:740px;margin:0 auto 50px;padding:0 20px;box-sizing:border-box;z-index:1}.aioseo-help .help-content .aioseo-help-category{border-top:1px solid #e8e8eb;margin:0}.aioseo-help .help-content .aioseo-help-category:last-child{border-bottom:1px solid #e8e8eb}.aioseo-help .help-content .aioseo-help-category header{display:block;position:relative;cursor:pointer;width:100%;height:68px}.aioseo-help .help-content .aioseo-help-category header .title{display:block;font-size:16px;color:#8c8f9a;font-weight:600;padding:23px 11px 23px 30px}.aioseo-help .help-content .aioseo-help-category .folder-open{position:absolute;top:24px;width:20px;height:20px;color:#8c8f9a}.aioseo-help .help-content .aioseo-help-category .dashicons-arrow-right-alt2{position:absolute;top:20px;right:0;transition:transform .3s ease-out}.aioseo-help .help-content .aioseo-help-category.opened .aioseo-help-docs{display:block}.aioseo-help .help-content .aioseo-help-category.opened .dashicons-arrow-right-alt2{transform:rotate(90deg)}.aioseo-help .help-content #aioseo-help-search{position:relative;background-color:#fff;text-align:center;top:0;padding:20px 0 50px}.aioseo-help .help-content #aioseo-help-result .aioseo-help-docs{display:block}.aioseo-help .help-content #aioseo-help-footer{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;margin:50px 0 0}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer{display:block}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{box-sizing:border-box;max-width:325px;border:1px solid #8c8f9a;border-radius:6px;text-align:center}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{max-width:100%}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin-right:20px}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin:0 0 20px}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a{display:block;padding:25px;text-decoration:none;color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a h3{color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a span{font-size:16px;color:#005ae0;text-decoration:underline}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a:hover span{text-decoration:none}.aioseo-help .help-content #aioseo-help-footer .aioseo-description,.aioseo-help .help-content #aioseo-help-footer .aioseo-support{width:48px;margin-top:0;color:#8c8f9a}#aioseo-help-logo{width:132px;height:26px;z-index:2}#aioseo-help-close{width:20px;height:20px;cursor:pointer;opacity:.7;transition:all .05s;z-index:2}@media screen and (max-width:750px){#aioseo-help-close{top:20px;right:20px}}.aioseo-html-tags-editor .no-access{margin-bottom:20px}.aioseo-html-tags-editor .aioseo-description.tags-description{margin:0 0 20px}.aioseo-html-tags-editor .add-tags{display:flex;align-items:center;margin-bottom:20px}.aioseo-html-tags-editor .add-tags div{margin-right:10px}.aioseo-html-tags-editor .add-tags a{font-size:14px}.aioseo-html-tags-editor .add-tags a.no-underline{padding-left:10px}.aioseo-loading-spinner{width:35px;height:35px;position:absolute}.aioseo-loading-spinner .double-bounce1,.aioseo-loading-spinner .double-bounce2{width:100%;height:100%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;left:0;-webkit-animation:sk-bounce 1.3s ease-in-out infinite;animation:sk-bounce 1.3s ease-in-out infinite}.aioseo-loading-spinner.dark .double-bounce1,.aioseo-loading-spinner.dark .double-bounce2{background-color:#8c8f9a}.aioseo-loading-spinner .double-bounce2{-webkit-animation-delay:-.65s;animation-delay:-.65s}@-webkit-keyframes sk-bounce{0%,to{-webkit-transform:scale(0)}50%{-webkit-transform:scale(1)}}@keyframes sk-bounce{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}body.vue-build{margin:0}body.vue-build .aioseo-app{min-height:calc(100vh - 88px)}body.vue-build .aioseo-app .aioseo-main{padding-bottom:30px}body.aioseo-setup-wizard{margin:0;padding:0}body.aioseo-setup-wizard .aioseo-app{min-height:100vh;width:100%}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay{left:160px}body[class*=page_aioseo].folded .aioseo-header,body[class*=page_aioseo].folded .aioseo-notifications .overlay{left:36px}body[class*=page_aioseo] #wpcontent{padding:0;background-color:#f3f4f5}body[class*=page_aioseo] .update-nag{display:none}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 185px)}body[class*=page_aioseo].admin-bar.aioseo-has-bar .aioseo-app{min-height:calc(100vh - 225px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:32px}body[class*=page_aioseo] .aioseo-app{min-height:calc(100vh - 153px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-app{min-height:calc(100vh - 193px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:112px}@media screen and (max-width:782px){body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:132px}}@media screen and (max-width:960px){body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{left:36px}}@media screen and (max-width:782px){body[class*=page_aioseo] #wpbody-content{padding-bottom:20px}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 199px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:46px}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay,body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{left:0}}@media screen and (max-width:600px){body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{position:absolute;top:46px}}body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:128px}@media screen and (max-width:782px){body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:148px}}.aioseo-app{box-sizing:border-box;background-color:#f3f4f5}.aioseo-app .route-fade-enter-active,.aioseo-app .route-fade-leave-active{transition:all .2s}.aioseo-app .route-fade-enter,.aioseo-app .route-fade-leave-active{opacity:0}.aioseo-app .route-fade-enter{transform:translateX(30px)}.aioseo-app .route-fade-leave-active{transform:translateX(-30px)}.aioseo-app *,.aioseo-app :after,.aioseo-app :before{box-sizing:inherit}.aioseo-app * :not(.aioseo-button):not(.aioseo-input),.aioseo-app :after :not(.aioseo-button):not(.aioseo-input),.aioseo-app :before :not(.aioseo-button):not(.aioseo-input){line-height:1.4}.aioseo-app p{font-size:16px}.aioseo-app a:not(.aioseo-button){color:#005ae0}.aioseo-app a:not(.aioseo-button).text-white{color:#fff}.aioseo-app a:not(.aioseo-button).no-underline,.aioseo-app a:not(.aioseo-button):hover{text-decoration:none}.aioseo-app h2{font-size:32px;margin:0}.aioseo-app .aioseo-main{height:100%}.aioseo-app .aioseo-main>.aioseo-container{margin-top:88px}.aioseo-app .aioseo-main .save-changes{display:flex;justify-content:flex-end}.aioseo-app .d-flex{display:flex}.aioseo-app .aioseo-section-description{font-size:16px;color:#141b38;line-height:1.8;padding-bottom:30px}.aioseo-app .aioseo-description-text{font-size:14px;line-height:1.8;color:#141b38}.aioseo-app .aioseo-description-text.aioseo-error{color:#df2a4a}.aioseo-app .aioseo-description{font-size:14px;line-height:1.8;margin:8px 0 0;color:#141b38}.aioseo-app .aioseo-description.no-margin{margin:0}.aioseo-app .aioseo-description.aioseo-error{color:#df2a4a}.aioseo-app .max-recommended-count{color:#434960;text-align:right;margin-top:10px;font-size:14px}.aioseo-app .max-recommended-count strong.error{color:#df2a4a}.aioseo-app .popper{text-align:left;font-size:12px;padding:20px;background-color:#fff;border:none;border-radius:3px;box-shadow:0 3px 4.8px 0 rgba(32,71,102,.27);z-index:9999;max-width:350px;line-height:1.4}.aioseo-app .popper.action{padding:8px 12px;background-color:#141b38;color:#fff}.aioseo-app .popper.action .popper__arrow{border-top-color:#141b38}.aioseo-app .popper[x-placement^=bottom]{box-shadow:0 -2px 4.8px 0 rgba(32,71,102,.27)}.aioseo-app .popper .aioseo-description{margin:0}.aioseo-app .aioseo-row-highlight{-webkit-animation-name:color;animation-name:color;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-iteration-count:2;animation-iteration-count:2}@-webkit-keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}@keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}.column-aioseo-details{position:relative}.aioseo-seo-site-score .aioseo-blur{display:flex;align-items:center}.aioseo-seo-site-score .aioseo-seo-site-score-cta{position:absolute;left:50%;top:50%;transform:translateX(-50%) translateY(-50%);background-color:#fff;padding:24px 30px;border:1px solid #e8e8eb;box-shadow:0 2px 10px rgba(0,90,224,.2);color:#141b38;font-size:16px;font-weight:600;width:82%;max-width:500px;text-align:center}.aioseo-app .aioseo-upgrade-bar{height:40px;background-color:#00aa63;display:flex;align-items:center;justify-content:center;color:#fff;font-size:13px;padding:0 14px 0 40px}.aioseo-app .aioseo-upgrade-bar .upgrade-text{display:flex;align-items:center;flex:1;justify-content:center}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow{font-size:15px;text-decoration:none}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow:hover{text-decoration:none}.aioseo-app .aioseo-upgrade-bar strong{font-weight:600}.aioseo-app .aioseo-upgrade-bar svg.aioseo-logo-gear{width:20px;height:20px;min-width:20px;margin-right:14px}.aioseo-app .aioseo-upgrade-bar svg.aioseo-close{cursor:pointer;width:12px;height:12px}.aioseo-app .aioseo-upgrade-bar a{color:#fff;text-decoration:underline}.aioseo-app .aioseo-upgrade-bar a:hover{text-decoration:none}@media screen and (max-width:782px){.aioseo-app .aioseo-upgrade-bar{padding:0 10px;height:60px}}.field-description[data-v-2bfc1de2]{display:inline-block;margin-top:10px;font-size:14px}.aioseo-address-wrapper[data-v-4bc9bbe6]{display:flex;max-width:500px}.field-description[data-v-4bc9bbe6]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4bc9bbe6]{margin-top:8px}.field-description[data-v-a0a894b8]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-a0a894b8]{margin-top:8px}.field-description[data-v-4fb4e044]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4fb4e044]{margin-top:8px}.field-description[data-v-85733554]{display:inline-block;margin-top:10px;font-size:14px}.field-description[data-v-515336a2]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-515336a2]{margin-top:8px}.field-description[data-v-78337de7]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-78337de7]{margin-top:8px}.aioseo-general-settings .more-tooltip-text strong{color:#00aa63}.aioseo-general-settings .license-cta-box{border-radius:3px;background-color:#f2f7fd;padding:20px;max-width:630px;margin:10px 0 30px}.aioseo-general-settings .license-cta-box a{color:#00aa63}.aioseo-general-settings .license-cta-box div{font-weight:600}.aioseo-general-settings .license-cta-box span{font-size:14px;font-style:italic}.aioseo-general-settings .license-key{margin-top:10px;display:flex;max-width:560px}.aioseo-general-settings .license-key .aioseo-input{margin-right:10px}.aioseo-app .aioseo-tabs.internal{margin-bottom:0}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation{margin-top:5px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button{height:60px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 25px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-ripple-wave{display:none}.aioseo-app .aioseo-tabs.skinny .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 16px}.aioseo-app .md-tabs{display:flex;flex-direction:column}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation{margin-top:2px;background:transparent;display:flex;position:relative;justify-content:flex-start}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation.md-elevation-0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button{color:#141b38;max-width:264px;min-width:72px;height:60px;margin:0;border-radius:0;font-size:15px;font-weight:500;padding:0;display:inline-block;position:relative;overflow:hidden;outline:none;background:transparent;border:0;transition:.4s cubic-bezier(.4,0,.2,1);font-family:inherit;line-height:normal;text-decoration:none;vertical-align:top;white-space:nowrap}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:before{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;transition:.4s cubic-bezier(.4,0,.2,1);will-change:background-color,opacity;content:" "}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 18px;display:flex;justify-content:center;align-items:center;width:100%;height:100%;position:relative;overflow:hidden;-webkit-mask-image:radial-gradient(circle,#fff 100%,#000 0);mask-image:radial-gradient(circle,#fff 100%,#000 0)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-button-content{position:static;z-index:2}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]){cursor:pointer}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]):active:before,.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]):hover:before{background-color:currentColor;opacity:.12}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button.md-active{color:#005ae0}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button.md-active:focus{outline:none;box-shadow:none}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator{height:2px;background-color:#005ae0;bottom:-2px;position:absolute;left:0;transform:translateZ(0);will-change:left,right}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator.md-tabs-indicator-left{transition:left .3s cubic-bezier(.4,0,.2,1),right .35s cubic-bezier(.4,0,.2,1)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator.md-tabs-indicator-right{transition:right .3s cubic-bezier(.4,0,.2,1),left .35s cubic-bezier(.4,0,.2,.1)}.aioseo-app .aioseo-tabs{display:flex;border-bottom:2px solid #e8e8eb;position:relative;margin-bottom:38px}.aioseo-app .aioseo-tabs .save-changes{position:absolute;right:0;bottom:10px}.aioseo-app .aioseo-tabs .tab-score{display:inline-flex;align-items:center;justify-content:flex-end;font-size:11px;font-weight:700;padding-left:12px}.aioseo-app .aioseo-tabs .tab-score.green{color:#00aa63}.aioseo-app .aioseo-tabs .tab-score.orange{color:#f18200}.aioseo-app .aioseo-tabs .tab-score.red{color:#df2a4a}.aioseo-app .aioseo-tabs .tab-score svg{display:inline;margin-right:7px}.aioseo-app .aioseo-mobile-tabs{position:relative;height:40px;margin-top:20px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.aioseo-app .aioseo-mobile-tabs .active-tab{color:#005ae0;padding-left:18px;min-height:100%;display:flex;align-items:center;cursor:pointer}.aioseo-app .aioseo-mobile-tabs .active-tab div{position:relative}.aioseo-app .aioseo-mobile-tabs .active-tab div span{height:2px;background-color:#005ae0;bottom:-7px;position:absolute;left:-18px;right:-18px;z-index:10}.aioseo-app .aioseo-mobile-tabs .active-tab svg.aioseo-caret{width:24px;height:24px;position:relative;top:6px;cursor:pointer;transition:transform .3s}.aioseo-app .aioseo-mobile-tabs .active-tab svg.aioseo-caret.rotated{transform:rotate(180deg)}.aioseo-app .aioseo-mobile-tabs .tab-dropdown{border:1px solid #e8e8eb;border-top:none}.aioseo-app .aioseo-mobile-tabs .tab-links{background:#fff;position:relative;z-index:3;padding:8px;width:100%;max-width:300px}@media screen and (max-width:782px){.aioseo-app .aioseo-mobile-tabs .tab-links{max-width:100%}}.aioseo-app .aioseo-mobile-tabs .tab-links a{padding:10px;display:block;color:#141b38;text-decoration:none}.aioseo-app .aioseo-mobile-tabs .tab-links a:hover{color:#005ae0}.md-tooltip{background-color:#141b38!important;color:#fff!important;border-radius:2px;padding:6px 12px;font-size:14px}.md-tooltip:after{content:"";position:absolute;top:100%;left:50%;margin-left:-5px;border:5px solid transparent;border-top-color:#141b38}.modal-mask{position:fixed;z-index:9998;top:0;left:0;width:100%;height:100%;background-color:rgba(20,27,56,.3);display:table;transition:opacity .3s ease}@media screen and (max-width:520px){.modal-mask{display:block;top:46px}}.modal-mask .modal-wrapper{display:table-cell;vertical-align:middle}@media screen and (max-width:520px){.modal-mask .modal-wrapper{display:block;height:100%}}.modal-mask .modal-wrapper .modal-container{width:100%;max-width:750px;max-height:90vh;overflow-y:hidden;overflow-x:hidden;margin:0 auto;background-color:#fff;box-shadow:0 10px 30px rgba(0,0,0,.15);transition:all .3s ease}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container{width:100%;max-width:100%;max-height:calc(100vh - 46px);height:100%}}.modal-mask .modal-wrapper .modal-container .modal-header{color:#141b38;position:sticky;top:0;z-index:15;padding:0 0 0 40px;height:70px;font-size:20px;font-weight:700;line-height:1.4;border-bottom:1px solid #e8e8eb;background-color:#fff;display:flex;align-items:center}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container .modal-header{padding:15px 0 0 20px}}.modal-mask .modal-wrapper .modal-container .modal-header button.close{position:absolute;right:11px;top:11px;width:24px;height:24px;background-color:#fff;border:none;display:flex;align-items:center}.modal-mask .modal-wrapper .modal-container .modal-header button.close svg.aioseo-close{cursor:pointer;width:14px;height:14px}.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-post-general,.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-post-social{height:calc(90vh - 120px);max-height:600px;overflow-y:auto;overflow-x:hidden}.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-modal-content.has-padding{padding:40px}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container .aioseo-modal-content,.modal-mask .modal-wrapper .modal-container .aioseo-modal-content>.component-wrapper,.modal-mask .modal-wrapper .modal-container .modal-body,.modal-mask .modal-wrapper .modal-container .modal-body>div{height:100%}.modal-mask .modal-wrapper .modal-container .aioseo-modal-content>.component-wrapper{display:flex;align-items:flex-end}.modal-mask .modal-wrapper .modal-container .aioseo-post-general,.modal-mask .modal-wrapper .modal-container .aioseo-post-social{height:100%!important;max-height:100%!important;padding:20px!important}.modal-mask .modal-wrapper .modal-container .aioseo-post-general .mobile-radio-buttons,.modal-mask .modal-wrapper .modal-container .aioseo-post-social .mobile-radio-buttons{margin-bottom:0}.modal-mask .modal-wrapper .modal-container .aioseo-add-template-tag{display:none}.modal-mask .modal-wrapper .modal-container .tab-facebook .aioseo-settings-row:last-of-type,.modal-mask .modal-wrapper .modal-container .tab-twitter .aioseo-settings-row:last-of-type{margin-bottom:64px!important;padding-bottom:32px!important}}.modal-enter,.modal-leave-active{opacity:0}.modal-enter .modal-container,.modal-leave-active .modal-container{transform:scale(1.1)}.aioseo-notification>div .body .title .date{font-weight:400;color:#8c8f9a;font-size:12px}.aioseo-notification-cards .aioseo-notification:last-child>div{border-bottom:none;margin-bottom:none}.aioseo-notification-cards .no-notifications{display:flex;align-items:center;flex-direction:column;padding-top:100px;font-size:16px;color:#8c8f9a}.aioseo-notification-cards .no-notifications img{width:30%;height:auto}.aioseo-notification-cards .no-notifications .great-scott{margin:20px 0 10px;font-size:24px;font-weight:600;color:#434960}.aioseo-notification-cards .no-notifications .no-new-notifications{margin-bottom:10px}body.aioseo-show-notifications .aioseo-main{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-notifications a.dismiss{color:#8c8f9a;font-size:14px}.aioseo-notifications .notification-menu{height:100%;width:100%;max-width:570px;position:fixed;z-index:1053;top:0;right:0;bottom:0;background-color:#fff;overflow-x:hidden;transition:.5s}.aioseo-notifications .notification-menu .notification-header{height:70px;display:flex;align-items:center;padding:0 30px;color:#fff;background-color:#005ae0}.aioseo-notifications .notification-menu .notification-header .new-notifications{font-size:18px;font-weight:600}.aioseo-notifications .notification-menu .notification-header .dismissed-notifications{margin-left:25px;flex:1 1 auto}.aioseo-notifications .notification-menu .notification-header .dismissed-notifications a{font-size:14px;color:#fff}.aioseo-notifications .notification-menu .notification-header svg.aioseo-close{width:14px;height:14px;cursor:pointer}.aioseo-notifications .notification-menu .notification-header svg.aioseo-close:hover{color:#ccc}.aioseo-notifications .notification-menu .notification-cards{padding:30px;height:calc(100% - 192px);overflow:auto}.aioseo-notifications .notification-menu .notification-footer{height:90px;padding:30px;display:flex;align-items:center}.aioseo-notifications .notification-menu .notification-footer div.pagination{flex:1;display:flex;align-items:center}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number{font-size:13px;color:#141b38;background:#e8e8eb;height:30px;width:30px;display:flex;align-items:center;justify-content:center;border-radius:2px;margin-right:4px;cursor:pointer}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number:last-child{margin-right:0}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number.active,.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number:hover{color:#fff;background-color:#005ae0}.aioseo-notifications .overlay{position:fixed;z-index:1052;top:0;right:0;bottom:0;left:160px;background-color:#141b38;opacity:.5;transition:.5s}.aioseo-notifications .notifications-fade-enter-active,.aioseo-notifications .notifications-fade-leave-active{transition:opacity .5s}.aioseo-notifications .notifications-fade-enter,.aioseo-notifications .notifications-fade-leave-to{opacity:0}.aioseo-notifications .notifications-slide-enter-active,.aioseo-notifications .notifications-slide-leave-active{transition:all .5s ease-in-out}.aioseo-notifications .notifications-slide-enter,.aioseo-notifications .notifications-slide-leave-to{right:-570px}.aioseo-post-type-options-toggle{margin-top:20px}.aioseo-priority-score{max-width:350px}.aioseo-priority-score .header-row{font-size:14px}.aioseo-pro-badge{height:24px;border-radius:3px;background:#e8e8eb;color:#434960;font-size:14px;font-weight:600;display:inline-flex;padding:0 8px;align-items:center}.aioseo-score-settings{display:flex;align-items:center;padding-bottom:14px}.aioseo-score-settings svg{margin-right:7px}.aioseo-score-settings span{margin-right:12px}.aioseo-score-button{display:inline-block;padding:5px 8px;font-size:14px;font-weight:700;color:#a1a1a1;border:1px solid #a1a1a1;border-radius:3px}.aioseo-score-button.score-none,.aioseo-score-button.score-red{border-color:#df2a4a;color:#df2a4a!important}.aioseo-score-button.score-orange{border-color:#f18200;color:#f18200!important}.aioseo-score-button.score-green{border-color:#00aa63;color:#00aa63!important}.aioseo-score-button.classic-editor{background:#fff!important;display:inline-block!important;height:auto!important}.aioseo-score-button.classic-editor span{margin-right:0}.aioseo-seo-site-analysis-result{border:1px solid #dcdde1;margin-top:10px}.aioseo-seo-site-analysis-result .result-header{height:66px;padding:0 20px;display:flex;align-items:center}.aioseo-seo-site-analysis-result .result-header .result-icon{display:flex;align-items:center;margin-right:16px}.aioseo-seo-site-analysis-result .result-header .result-icon svg{width:24px;height:24px;color:#8c8f9a}.aioseo-seo-site-analysis-result .result-header .result-icon svg.passed{color:#00aa63}.aioseo-seo-site-analysis-result .result-header .result-icon svg.error{color:#df2a4a}.aioseo-seo-site-analysis-result .result-header .result-icon svg.warning{color:#005ae0}.aioseo-seo-site-analysis-result .result-header .result-content{font-size:16px;font-weight:600;flex:1}.aioseo-seo-site-analysis-result .result-header .result-toggle{width:30px;height:26px;border:1px solid #dcdde1;border-radius:3px;display:flex;align-items:center;justify-content:center;cursor:pointer}.aioseo-seo-site-analysis-result .result-header .result-toggle.active,.aioseo-seo-site-analysis-result .result-header .result-toggle:hover{background-color:#434960}.aioseo-seo-site-analysis-result .result-header .result-toggle.active svg,.aioseo-seo-site-analysis-result .result-header .result-toggle:hover svg{color:#fff}.aioseo-seo-site-analysis-result .result-header .result-toggle.active svg{transform:rotate(-180deg)}.aioseo-seo-site-analysis-result .result-header .result-toggle svg{width:100%;max-width:20px;height:auto;color:#8c8f9a;transform:rotate(-90deg);transition:transform .3s}.aioseo-seo-site-analysis-result .result-body{padding:0 60px 24px}.aioseo-seo-site-analysis-result .result-body .result-message{color:#434960;font-size:16px}.aioseo-seo-site-analysis-result .result-body .result-code-alt pre,.aioseo-seo-site-analysis-result .result-body .result-code pre{background:#f3f4f5;border-radius:3px;max-width:100%;padding:10px;overflow:auto}.aioseo-seo-site-analysis-result .result-body .result-code-alt pre code,.aioseo-seo-site-analysis-result .result-body .result-code pre code{padding:0;background:transparent}.aioseo-seo-site-analysis-result .result-body .result-code pre{white-space:pre-wrap}.aioseo-seo-site-analysis-result .result-body .result-action{margin-top:20px}.aioseo-seo-site-analysis-results .group-header{font-size:16px;font-weight:600}.aioseo-seo-site-analysis-results .group-header:not(:first-child){margin-top:30px}.aioseo-seo-site-analysis-results .group-keywords{display:flex;margin-top:5px;flex-wrap:wrap;align-items:center}.aioseo-seo-site-analysis-results .group-keywords .keyword{font-size:14px;color:#434960;font-weight:600;background:#f3f4f5;padding:9px 10px;border-radius:3px;margin:0 10px 5px 0}.aioseo-seo-site-analysis-results .group-keywords .keyword:first-child{font-size:20px}.aioseo-settings-row{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid #e8e8eb}.aioseo-settings-row.no-margin{margin-bottom:0}.aioseo-settings-row.small-padding{padding-bottom:5px}.aioseo-settings-row.medium-margin{margin-bottom:15px}.aioseo-settings-row.no-border{border:none}.aioseo-settings-row.no-side-margin{margin-left:0!important;margin-right:0!important}.aioseo-settings-row .settings-name{color:#141b38}.aioseo-settings-row .settings-name .name{font-weight:600;font-size:16px;display:flex;align-items:center}.aioseo-settings-row .settings-name .name.small-margin{margin-bottom:5px}.aioseo-settings-row .settings-name .name.align{line-height:40px}.aioseo-settings-row .settings-name .name.align-small{line-height:30px}.aioseo-settings-row .settings-name .name .aioseo-pro-badge{margin-left:10px}.aioseo-settings-row .settings-name .aioseo-description{margin-top:20px}.aioseo-settings-row .settings-content{font-size:16px}.aioseo-settings-row p.description{font-size:14px}.aioseo-separators{margin-top:-.5rem}.aioseo-separators .aioseo-col .separator{background-color:#f3f4f5;display:flex;align-items:center;justify-content:center;min-height:51px;font-weight:600;font-size:25px;border:1px solid #dcdde1;border-radius:3px;cursor:pointer}.aioseo-separators .aioseo-col .separator:hover{background-color:#e5e7e9}.aioseo-separators .aioseo-col .separator.active{background-color:#005ae0;border-color:#005ae0;color:#fff}.aioseo-separators .aioseo-col .separator.active:hover{background-color:#005ae0}.aioseo-separators .aioseo-col .show-more{height:100%;display:flex;align-items:center}.aioseo-separators .aioseo-col .show-more a{color:#8c8f9a}.aioseo-separators .aioseo-col .custom-separator{margin:20px 0;display:flex;align-items:center}.aioseo-separators .aioseo-col .custom-separator .aioseo-input{margin-left:10px;max-width:100px}.aioseo-sidebar-card .header{height:46px}.aioseo-sidebar-card .header:hover{cursor:pointer}.aioseo-sidebar-card .content{padding-bottom:8px!important}.aioseo-sidebar-card ul{margin-bottom:0}.aioseo-sidebar-card ul li{margin-bottom:16px;padding-left:25px}.aioseo-sidebar-card ul .description{margin:0}.aioseo-robots-meta .global-robots-settings{margin:0;padding-top:24px}.aioseo-robots-meta .global-robots-settings>.settings{padding:8px 0 16px}.aioseo-robots-meta .global-robots-settings-options{display:flex}.aioseo-robots-meta .global-robots-settings-options .max-snippet{margin-right:30px}.aioseo-robots-meta .global-robots-settings-options .max-snippet .aioseo-input{max-width:90px}.aioseo-robots-meta .global-robots-settings-options .max-video-preview{margin-right:30px}.aioseo-robots-meta .global-robots-settings-options .max-video-preview .aioseo-input{max-width:90px}.aioseo-robots-meta .global-robots-settings-options .max-image-preview .aioseo-select{min-width:155px}.aioseo-robots-meta .global-robots-settings-options>span{display:inline-block;margin-bottom:4px}@media screen and (max-width:782px){.aioseo-robots-meta .global-robots-settings-options{display:block}.aioseo-robots-meta .global-robots-settings-options .max-snippet,.aioseo-robots-meta .global-robots-settings-options .max-video-preview{margin-right:0;margin-bottom:20px}.aioseo-robots-meta .global-robots-settings-options>div .aioseo-input,.aioseo-robots-meta .global-robots-settings-options>div .aioseo-select{min-width:100%}}.edit-post-sidebar .global-robots-settings{padding-top:12px}.edit-post-sidebar .global-robots-settings>.settings{padding:4px 0 12px}.edit-post-sidebar .global-robots-settings>.settings label{font-size:16px}.edit-post-sidebar .global-robots-settings .robots-meta-title{padding-top:4px;display:inline-block}.edit-post-sidebar .global-robots-settings-options{flex-wrap:wrap}.edit-post-sidebar .max-snippet{margin-right:30px!important}.edit-post-sidebar .max-video-preview{margin-right:0!important}.edit-post-sidebar .max-image-preview{margin-top:20px!important}.aioseo-score-amount-wrapper{position:absolute;left:0;top:0;right:0;bottom:0;display:flex;align-items:center;justify-content:center;flex-direction:column;color:#141b38;margin:20px}.aioseo-score-amount-wrapper .aioseo-score-amount .score{font-size:64px;font-weight:600}.aioseo-score-amount-wrapper .aioseo-score-amount .total{font-size:18px;color:#8c8f9a;padding-left:3px}.aioseo-score-amount-wrapper .score-description{max-width:80%;text-align:center;font-size:17px;font-weight:600;line-height:1.1}.aioseo-score-amount-wrapper .score-analyzing{margin-top:20px;font-size:30px}.aioseo-site-score-analyze{position:relative;display:flex;align-items:center;justify-content:center;flex:1}.aioseo-site-score-analyze .analyze-errors{text-align:center;margin-bottom:1em}.aioseo-site-score-analyze .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-right:5em}.aioseo-site-score-analyze .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-analyze .aioseo-seo-site-score-description h2{line-height:1.4}.aioseo-site-score-analyze .aioseo-seo-site-score-description svg.aioseo-book{width:20px;height:20px;margin:0 10px 0 0;color:#005ae0}.aioseo-site-score-analyze .aioseo-seo-site-score-description>div{font-size:16px;color:#141b38;margin-bottom:10px}.aioseo-site-score-analyze .aioseo-seo-site-score-description .links{margin-top:30px;font-size:14px;font-weight:600}.aioseo-site-score-analyze .aioseo-seo-site-score-description .links .no-underline{padding-left:5px}.aioseo-site-score-competitor{position:relative;display:flex;align-items:center;justify-content:center;flex-direction:column}.aioseo-site-score-competitor .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-right:1em}.aioseo-site-score-competitor .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations{margin:20px 0}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links){display:flex;align-items:center;font-size:14px;color:#141b38;font-weight:600;margin-bottom:10px}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round{position:relative;border-radius:50%;width:24px;min-width:24px;max-width:24px;height:24px;display:flex;align-items:center;justify-content:center;margin-right:10px;font-size:12px;color:#fff;font-weight:600}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.red{background-color:#df2a4a}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.blue{background-color:#005ae0}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.orange{background-color:#f18200}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.green{background-color:#00aa63}.aioseo-site-score-competitor .refresh-results .aioseo-refresh{width:14px;height:14px;margin-right:10px}.aioseo-site-score-competitor .mobile-snapshot{margin-top:60px;max-width:250px}.aioseo-site-score-competitor .mobile-snapshot div{font-weight:600;font-size:16px;margin-bottom:10px}.aioseo-site-score-competitor .mobile-snapshot img{width:100%;height:auto}.aioseo-site-score-dashboard{position:relative;display:flex;align-items:center;justify-content:center}.aioseo-site-score-dashboard .analyze-errors{text-align:center;margin-bottom:1em}.aioseo-site-score-dashboard .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-right:1em}.aioseo-site-score-dashboard .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links){display:flex;align-items:center;font-size:14px;color:#141b38;font-weight:600;margin-bottom:10px}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round{position:relative;border-radius:50%;width:24px;min-width:24px;max-width:24px;height:24px;display:flex;align-items:center;justify-content:center;margin-right:10px;font-size:12px;color:#fff;font-weight:600}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.red{background-color:#df2a4a}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.blue{background-color:#005ae0}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.orange{background-color:#f18200}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.green{background-color:#00aa63}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations .links{margin-top:30px;font-size:14px;font-weight:600}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations .links .no-underline{padding-left:5px}.aioseo-social-profiles .same-username .use-same{padding:30px;background:#f9f9fa}.aioseo-social-profiles .same-username .use-same .aioseo-checkbox{font-size:16px}.aioseo-social-profiles .aioseo-social-profile-list,.aioseo-social-profiles .same-username .use-same .aioseo-settings-row,.aioseo-social-profiles .same-username .use-same .profiles{margin-top:20px}.aioseo-social-profiles .aioseo-social-profile-list .social-profile{margin-bottom:0;padding-bottom:0;border-bottom:none}.aioseo-social-profiles .aioseo-social-profile-list .social-profile .logo-svg{margin-right:10px}.aioseo-social-profiles .aioseo-social-profile-list .social-profile .profile-error{margin-top:10px}.aioseo-social-profiles .aioseo-social-profile-list .social-profile .name{margin-bottom:0}.aioseo-tooltip{margin-left:14px;display:inline-flex}.aioseo-tooltip,.aioseo-twitter-preview{align-items:center;justify-content:center}.aioseo-twitter-preview{background-color:#f0f2f5;padding:30px;display:flex}.aioseo-twitter-preview .twitter-post{width:100%;max-width:500px;border-radius:5px;border:1px solid #e1e8ed;background-color:#fff}.aioseo-twitter-preview .twitter-post .twitter-header{height:65px;padding:0 18px;display:flex;align-items:center}.aioseo-twitter-preview .twitter-post .twitter-header .profile-photo{overflow:hidden;width:40px;height:40px;border:1px solid #e8e8eb;border-radius:50%}.aioseo-twitter-preview .twitter-post .twitter-header .profile-photo img{height:100%;width:100%}.aioseo-twitter-preview .twitter-post .twitter-header .poster{margin-left:10px;flex:1 0 auto}.aioseo-twitter-preview .twitter-post .twitter-header .poster .poster-name{font-size:15px;color:#1c2022;font-weight:600}.aioseo-twitter-preview .twitter-post .twitter-header .poster .poster-username{color:#697882;font-weight:500;font-size:13px}.aioseo-twitter-preview .twitter-post .twitter-container{padding:0 20px 20px}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content{flex-direction:row}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content .twitter-image-preview{display:flex;align-items:center;justify-content:center;background-color:#e1e8ed;min-width:125px;min-height:125px;background-size:cover;background-repeat:no-repeat;background-position:50%}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content .twitter-image-preview svg.aioseo-book{width:50px;height:50px;color:#8999a5}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content{border-radius:10px;overflow:hidden;display:flex;flex-direction:column;border:1px solid #e1e8ed}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content img{width:100%;height:auto}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description{padding:18px;color:#1c2022}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-domain{font-size:14px;color:#8899a6;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-title{font-size:15px;font-weight:600}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-description{font-size:14px;margin:5px 0}.aioseo-col .reverse{flex-direction:column-reverse}.aioseo-col.col-xs,.aioseo-col.col-xs-1,.aioseo-col.col-xs-2,.aioseo-col.col-xs-3,.aioseo-col.col-xs-4,.aioseo-col.col-xs-5,.aioseo-col.col-xs-6,.aioseo-col.col-xs-7,.aioseo-col.col-xs-8,.aioseo-col.col-xs-9,.aioseo-col.col-xs-10,.aioseo-col.col-xs-11,.aioseo-col.col-xs-12,.aioseo-col.col-xs-offset-0,.aioseo-col.col-xs-offset-1,.aioseo-col.col-xs-offset-2,.aioseo-col.col-xs-offset-3,.aioseo-col.col-xs-offset-4,.aioseo-col.col-xs-offset-5,.aioseo-col.col-xs-offset-6,.aioseo-col.col-xs-offset-7,.aioseo-col.col-xs-offset-8,.aioseo-col.col-xs-offset-9,.aioseo-col.col-xs-offset-10,.aioseo-col.col-xs-offset-11,.aioseo-col.col-xs-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-xs{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-xs-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-xs-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-xs-3{flex-basis:25%;max-width:25%}.aioseo-col.col-xs-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-xs-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-xs-6{flex-basis:50%;max-width:50%}.aioseo-col.col-xs-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-xs-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-xs-9{flex-basis:75%;max-width:75%}.aioseo-col.col-xs-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-xs-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-xs-12{flex-basis:100%;max-width:100%}.aioseo-col.col-xs-offset-0{margin-left:0}.aioseo-col.col-xs-offset-1{margin-left:8.33333333%}.aioseo-col.col-xs-offset-2{margin-left:16.66666667%}.aioseo-col.col-xs-offset-3{margin-left:25%}.aioseo-col.col-xs-offset-4{margin-left:33.33333333%}.aioseo-col.col-xs-offset-5{margin-left:41.66666667%}.aioseo-col.col-xs-offset-6{margin-left:50%}.aioseo-col.col-xs-offset-7{margin-left:58.33333333%}.aioseo-col.col-xs-offset-8{margin-left:66.66666667%}.aioseo-col.col-xs-offset-9{margin-left:75%}.aioseo-col.col-xs-offset-10{margin-left:83.33333333%}.aioseo-col.col-xs-offset-11{margin-left:91.66666667%}.aioseo-col.first-xs{order:-1}.aioseo-col.last-xs{order:1}.aioseo-col.text-xs-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-xs-center{text-align:center!important;justify-content:center}.aioseo-col.text-xs-right{text-align:right!important;justify-content:flex-end}.aioseo-col.p-0{padding:0!important}.aioseo-col.pt-0,.aioseo-col.py-0{padding-top:0!important}.aioseo-col.pr-0,.aioseo-col.px-0{padding-right:0!important}.aioseo-col.pb-0,.aioseo-col.py-0{padding-bottom:0!important}.aioseo-col.pl-0,.aioseo-col.px-0{padding-left:0!important}.aioseo-col.p-1{padding:.25rem!important}.aioseo-col.pt-1,.aioseo-col.py-1{padding-top:.25rem!important}.aioseo-col.pr-1,.aioseo-col.px-1{padding-right:.25rem!important}.aioseo-col.pb-1,.aioseo-col.py-1{padding-bottom:.25rem!important}.aioseo-col.pl-1,.aioseo-col.px-1{padding-left:.25rem!important}.aioseo-col.p-2{padding:.5rem!important}.aioseo-col.pt-2,.aioseo-col.py-2{padding-top:.5rem!important}.aioseo-col.pr-2,.aioseo-col.px-2{padding-right:.5rem!important}.aioseo-col.pb-2,.aioseo-col.py-2{padding-bottom:.5rem!important}.aioseo-col.pl-2,.aioseo-col.px-2{padding-left:.5rem!important}.aioseo-col.p-3{padding:1rem!important}.aioseo-col.pt-3,.aioseo-col.py-3{padding-top:1rem!important}.aioseo-col.pr-3,.aioseo-col.px-3{padding-right:1rem!important}.aioseo-col.pb-3,.aioseo-col.py-3{padding-bottom:1rem!important}.aioseo-col.pl-3,.aioseo-col.px-3{padding-left:1rem!important}.aioseo-col.p-4{padding:1.5rem!important}.aioseo-col.pt-4,.aioseo-col.py-4{padding-top:1.5rem!important}.aioseo-col.pr-4,.aioseo-col.px-4{padding-right:1.5rem!important}.aioseo-col.pb-4,.aioseo-col.py-4{padding-bottom:1.5rem!important}.aioseo-col.pl-4,.aioseo-col.px-4{padding-left:1.5rem!important}.aioseo-col.p-5{padding:3rem!important}.aioseo-col.pt-5,.aioseo-col.py-5{padding-top:3rem!important}.aioseo-col.pr-5,.aioseo-col.px-5{padding-right:3rem!important}.aioseo-col.pb-5,.aioseo-col.py-5{padding-bottom:3rem!important}.aioseo-col.pl-5,.aioseo-col.px-5{padding-left:3rem!important}@media only screen and (min-width:782px){.aioseo-col.col-sm,.aioseo-col.col-sm-1,.aioseo-col.col-sm-2,.aioseo-col.col-sm-3,.aioseo-col.col-sm-4,.aioseo-col.col-sm-5,.aioseo-col.col-sm-6,.aioseo-col.col-sm-7,.aioseo-col.col-sm-8,.aioseo-col.col-sm-9,.aioseo-col.col-sm-10,.aioseo-col.col-sm-11,.aioseo-col.col-sm-12,.aioseo-col.col-sm-offset-0,.aioseo-col.col-sm-offset-1,.aioseo-col.col-sm-offset-2,.aioseo-col.col-sm-offset-3,.aioseo-col.col-sm-offset-4,.aioseo-col.col-sm-offset-5,.aioseo-col.col-sm-offset-6,.aioseo-col.col-sm-offset-7,.aioseo-col.col-sm-offset-8,.aioseo-col.col-sm-offset-9,.aioseo-col.col-sm-offset-10,.aioseo-col.col-sm-offset-11,.aioseo-col.col-sm-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-sm{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-sm-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-sm-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-sm-3{flex-basis:25%;max-width:25%}.aioseo-col.col-sm-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-sm-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-sm-6{flex-basis:50%;max-width:50%}.aioseo-col.col-sm-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-sm-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-sm-9{flex-basis:75%;max-width:75%}.aioseo-col.col-sm-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-sm-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-sm-12{flex-basis:100%;max-width:100%}.aioseo-col.col-sm-offset-0{margin-left:0}.aioseo-col.col-sm-offset-1{margin-left:8.33333333%}.aioseo-col.col-sm-offset-2{margin-left:16.66666667%}.aioseo-col.col-sm-offset-3{margin-left:25%}.aioseo-col.col-sm-offset-4{margin-left:33.33333333%}.aioseo-col.col-sm-offset-5{margin-left:41.66666667%}.aioseo-col.col-sm-offset-6{margin-left:50%}.aioseo-col.col-sm-offset-7{margin-left:58.33333333%}.aioseo-col.col-sm-offset-8{margin-left:66.66666667%}.aioseo-col.col-sm-offset-9{margin-left:75%}.aioseo-col.col-sm-offset-10{margin-left:83.33333333%}.aioseo-col.col-sm-offset-11{margin-left:91.66666667%}.aioseo-col.first-sm{order:-1}.aioseo-col.last-sm{order:1}.aioseo-col.text-sm-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-sm-center{text-align:center!important;justify-content:center}.aioseo-col.text-sm-right{text-align:right!important;justify-content:flex-end}}@media only screen and (min-width:912px){.aioseo-col.col-md,.aioseo-col.col-md-1,.aioseo-col.col-md-2,.aioseo-col.col-md-3,.aioseo-col.col-md-4,.aioseo-col.col-md-5,.aioseo-col.col-md-6,.aioseo-col.col-md-7,.aioseo-col.col-md-8,.aioseo-col.col-md-9,.aioseo-col.col-md-10,.aioseo-col.col-md-11,.aioseo-col.col-md-12,.aioseo-col.col-md-offset-0,.aioseo-col.col-md-offset-1,.aioseo-col.col-md-offset-2,.aioseo-col.col-md-offset-3,.aioseo-col.col-md-offset-4,.aioseo-col.col-md-offset-5,.aioseo-col.col-md-offset-6,.aioseo-col.col-md-offset-7,.aioseo-col.col-md-offset-8,.aioseo-col.col-md-offset-9,.aioseo-col.col-md-offset-10,.aioseo-col.col-md-offset-11,.aioseo-col.col-md-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-md{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-md-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-md-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-md-3{flex-basis:25%;max-width:25%}.aioseo-col.col-md-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-md-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-md-6{flex-basis:50%;max-width:50%}.aioseo-col.col-md-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-md-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-md-9{flex-basis:75%;max-width:75%}.aioseo-col.col-md-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-md-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-md-12{flex-basis:100%;max-width:100%}.aioseo-col.col-md-offset-0{margin-left:0}.aioseo-col.col-md-offset-1{margin-left:8.33333333%}.aioseo-col.col-md-offset-2{margin-left:16.66666667%}.aioseo-col.col-md-offset-3{margin-left:25%}.aioseo-col.col-md-offset-4{margin-left:33.33333333%}.aioseo-col.col-md-offset-5{margin-left:41.66666667%}.aioseo-col.col-md-offset-6{margin-left:50%}.aioseo-col.col-md-offset-7{margin-left:58.33333333%}.aioseo-col.col-md-offset-8{margin-left:66.66666667%}.aioseo-col.col-md-offset-9{margin-left:75%}.aioseo-col.col-md-offset-10{margin-left:83.33333333%}.aioseo-col.col-md-offset-11{margin-left:91.66666667%}.aioseo-col.first-md{order:-1}.aioseo-col.last-md{order:1}.aioseo-col.text-md-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-md-center{text-align:center!important;justify-content:center}.aioseo-col.text-md-right{text-align:right!important;justify-content:flex-end}}@media only screen and (min-width:1042px){.aioseo-col.col-lg,.aioseo-col.col-lg-1,.aioseo-col.col-lg-2,.aioseo-col.col-lg-3,.aioseo-col.col-lg-4,.aioseo-col.col-lg-5,.aioseo-col.col-lg-6,.aioseo-col.col-lg-7,.aioseo-col.col-lg-8,.aioseo-col.col-lg-9,.aioseo-col.col-lg-10,.aioseo-col.col-lg-11,.aioseo-col.col-lg-12,.aioseo-col.col-lg-offset-0,.aioseo-col.col-lg-offset-1,.aioseo-col.col-lg-offset-2,.aioseo-col.col-lg-offset-3,.aioseo-col.col-lg-offset-4,.aioseo-col.col-lg-offset-5,.aioseo-col.col-lg-offset-6,.aioseo-col.col-lg-offset-7,.aioseo-col.col-lg-offset-8,.aioseo-col.col-lg-offset-9,.aioseo-col.col-lg-offset-10,.aioseo-col.col-lg-offset-11,.aioseo-col.col-lg-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-lg{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-lg-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-lg-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-lg-3{flex-basis:25%;max-width:25%}.aioseo-col.col-lg-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-lg-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-lg-6{flex-basis:50%;max-width:50%}.aioseo-col.col-lg-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-lg-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-lg-9{flex-basis:75%;max-width:75%}.aioseo-col.col-lg-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-lg-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-lg-12{flex-basis:100%;max-width:100%}.aioseo-col.col-lg-offset-0{margin-left:0}.aioseo-col.col-lg-offset-1{margin-left:8.33333333%}.aioseo-col.col-lg-offset-2{margin-left:16.66666667%}.aioseo-col.col-lg-offset-3{margin-left:25%}.aioseo-col.col-lg-offset-4{margin-left:33.33333333%}.aioseo-col.col-lg-offset-5{margin-left:41.66666667%}.aioseo-col.col-lg-offset-6{margin-left:50%}.aioseo-col.col-lg-offset-7{margin-left:58.33333333%}.aioseo-col.col-lg-offset-8{margin-left:66.66666667%}.aioseo-col.col-lg-offset-9{margin-left:75%}.aioseo-col.col-lg-offset-10{margin-left:83.33333333%}.aioseo-col.col-lg-offset-11{margin-left:91.66666667%}.aioseo-col.first-lg{order:-1}.aioseo-col.last-lg{order:1}.aioseo-col.text-lg-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-lg-center{text-align:center!important;justify-content:center}.aioseo-col.text-lg-right{text-align:right!important;justify-content:flex-end}}@media only screen and (min-width:1140px){.aioseo-col.col-xl,.aioseo-col.col-xl-1,.aioseo-col.col-xl-2,.aioseo-col.col-xl-3,.aioseo-col.col-xl-4,.aioseo-col.col-xl-5,.aioseo-col.col-xl-6,.aioseo-col.col-xl-7,.aioseo-col.col-xl-8,.aioseo-col.col-xl-9,.aioseo-col.col-xl-10,.aioseo-col.col-xl-11,.aioseo-col.col-xl-12,.aioseo-col.col-xl-offset-0,.aioseo-col.col-xl-offset-1,.aioseo-col.col-xl-offset-2,.aioseo-col.col-xl-offset-3,.aioseo-col.col-xl-offset-4,.aioseo-col.col-xl-offset-5,.aioseo-col.col-xl-offset-6,.aioseo-col.col-xl-offset-7,.aioseo-col.col-xl-offset-8,.aioseo-col.col-xl-offset-9,.aioseo-col.col-xl-offset-10,.aioseo-col.col-xl-offset-11,.aioseo-col.col-xl-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-xl{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-xl-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-xl-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-xl-3{flex-basis:25%;max-width:25%}.aioseo-col.col-xl-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-xl-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-xl-6{flex-basis:50%;max-width:50%}.aioseo-col.col-xl-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-xl-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-xl-9{flex-basis:75%;max-width:75%}.aioseo-col.col-xl-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-xl-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-xl-12{flex-basis:100%;max-width:100%}.aioseo-col.col-xl-offset-0{margin-left:0}.aioseo-col.col-xl-offset-1{margin-left:8.33333333%}.aioseo-col.col-xl-offset-2{margin-left:16.66666667%}.aioseo-col.col-xl-offset-3{margin-left:25%}.aioseo-col.col-xl-offset-4{margin-left:33.33333333%}.aioseo-col.col-xl-offset-5{margin-left:41.66666667%}.aioseo-col.col-xl-offset-6{margin-left:50%}.aioseo-col.col-xl-offset-7{margin-left:58.33333333%}.aioseo-col.col-xl-offset-8{margin-left:66.66666667%}.aioseo-col.col-xl-offset-9{margin-left:75%}.aioseo-col.col-xl-offset-10{margin-left:83.33333333%}.aioseo-col.col-xl-offset-11{margin-left:91.66666667%}.aioseo-col.first-xl{order:-1}.aioseo-col.last-xl{order:1}.aioseo-col.text-xl-left{text-align:left!important;justify-content:flex-start}.aioseo-col.text-xl-center{text-align:center!important;justify-content:center}.aioseo-col.text-xl-right{text-align:right!important;justify-content:flex-end}}.aioseo-container,.aioseo-container-fluid{margin-right:auto;margin-left:auto}.aioseo-container{padding:0 20px}.aioseo-container-fluid.hero,.aioseo-container.hero{min-height:100vh;display:flex;justify-content:center;align-items:center}.aioseo-container-fluid{padding-right:2rem;padding-left:2rem}@media only screen and (min-width:782px){.aioseo-container{padding:0 30px}}@media only screen and (min-width:1042px){.aioseo-container{max-width:80rem}.aioseo-container.full-width{max-width:100%}.aioseo-container.small{max-width:810px}}.aioseo-masonry{-moz-column-count:0;column-count:0;-moz-column-gap:20px;column-gap:20px;counter-reset:brick-counter}.aioseo-masonry>*{box-sizing:border-box;-moz-column-break-inside:avoid;break-inside:avoid;counter-increment:brick-counter;margin-bottom:20px}@media only screen and (min-width:782px){.aioseo-masonry{-moz-column-count:1;column-count:1}}@media only screen and (min-width:912px){.aioseo-masonry{-moz-column-count:2;column-count:2}}@media only screen and (min-width:1042px){.aioseo-masonry{-moz-column-count:3;column-count:3}}.aioseo-row{box-sizing:border-box;display:flex;flex:0 1 auto;flex-direction:row;flex-wrap:wrap;margin-right:-.5rem;margin-left:-.5rem}.aioseo-row.reverse{flex-direction:row-reverse}.aioseo-row.start-xs{justify-content:flex-start;text-align:start}.aioseo-row.center-xs{justify-content:center;text-align:center}.aioseo-row.end-xs{justify-content:flex-end;text-align:end}.aioseo-row.top-xs{align-items:flex-start}.aioseo-row.middle-xs{align-items:center}.aioseo-row.bottom-xs{align-items:flex-end}.aioseo-row.around-xs{justify-content:space-around}.aioseo-row.between-xs{justify-content:space-between}@media only screen and (min-width:782px){.aioseo-row.start-sm{justify-content:flex-start;text-align:start}.aioseo-row.center-sm{justify-content:center;text-align:center}.aioseo-row.end-sm{justify-content:flex-end;text-align:end}.aioseo-row.top-sm{align-items:flex-start}.aioseo-row.middle-sm{align-items:center}.aioseo-row.bottom-sm{align-items:flex-end}.aioseo-row.around-sm{justify-content:space-around}.aioseo-row.between-sm{justify-content:space-between}}@media only screen and (min-width:912px){.aioseo-row.start-md{justify-content:flex-start;text-align:start}.aioseo-row.center-md{justify-content:center;text-align:center}.aioseo-row.end-md{justify-content:flex-end;text-align:end}.aioseo-row.top-md{align-items:flex-start}.aioseo-row.middle-md{align-items:center}.aioseo-row.bottom-md{align-items:flex-end}.aioseo-row.around-md{justify-content:space-around}.aioseo-row.between-md{justify-content:space-between}}@media only screen and (min-width:1042px){.aioseo-row.start-lg{justify-content:flex-start;text-align:start}.aioseo-row.center-lg{justify-content:center;text-align:center}.aioseo-row.end-lg{justify-content:flex-end;text-align:end}.aioseo-row.top-lg{align-items:flex-start}.aioseo-row.middle-lg{align-items:center}.aioseo-row.bottom-lg{align-items:flex-end}.aioseo-row.around-lg{justify-content:space-around}.aioseo-row.between-lg{justify-content:space-between}}.aioseo-display-info svg.aioseo-new-page{width:100%;height:auto;max-width:45px}.aioseo-display-info .new-page .aioseo-row{margin:0}.aioseo-display-info .new-page svg.aioseo-external{width:14px;height:14px;margin-right:10px}.aioseo-display-info .new-page .aioseo-description{color:#434960}.aioseo-display-info .new-page button.aioseo-html-sitemaps-disabled-button{border:1px solid #dcdde1;color:#8c8f9a;background-color:#f3f4f5;cursor:default}.aioseo-display-info .new-page .aioseo-alert{width:100%;margin:8px 8px 0}.aioseo-exclude-posts{display:block}.aioseo-exclude-posts .aioseo-select{max-width:600px;display:inline-block;margin-right:10px}.aioseo-exclude-posts .aioseo-select button{display:none}.aioseo-exclude-posts .aioseo-select .multiselect__option{display:flex}.aioseo-exclude-posts .aioseo-select .multiselect__option--highlight .option-title{color:#005ae0}.aioseo-exclude-posts .aioseo-button.gray{margin-top:10px}.aioseo-exclude-posts .option{flex:1 0 auto}.aioseo-exclude-posts .option .option-title{font-weight:500;font-size:16px;color:#141b38}.aioseo-exclude-posts .option .option-title .search-term{font-weight:700}.aioseo-exclude-posts .option .option-details{display:flex;align-items:center;font-size:14px;color:#8c8f9a}.aioseo-exclude-posts .option .option-details span{margin-right:15px}.aioseo-exclude-posts .option-permalink{display:flex;align-items:center}.aioseo-exclude-posts .option-permalink svg.aioseo-external{width:15px;height:15px;color:#434960}.aioseo-exclude-posts .multiselect-toggle{padding:10px 13px;width:40px;position:absolute;height:36px;right:2px;top:2px;text-align:center;z-index:1}.aioseo-exclude-posts .multiselect-toggle svg.aioseo-add-plus{width:14px;height:14px;color:#000}.aioseo-sidebar-row .aioseo-included-objects-toggle{margin-top:5px}.aioseo-sidebar-row .aioseo-included-objects-toggle .aioseo-included-list{margin-top:8px}.aioseo-notification{margin-bottom:20px}.aioseo-notification>div{display:flex;align-items:flex-start;padding-bottom:10px;border-bottom:1px solid #e8e8eb}.aioseo-notification>div .icon{margin-right:20px}.aioseo-notification>div .icon svg{width:20px;height:20px;color:#00aa63}.aioseo-notification>div .icon svg.warning{color:#f18200}.aioseo-notification>div .icon svg.info{color:#005ae0}.aioseo-notification>div .icon svg.success{color:#00aa63}.aioseo-notification>div .icon svg.error{color:#df2a4a}.aioseo-notification>div .body{margin-right:20px;flex:1}.aioseo-notification>div .body .title{font-size:16px;font-weight:600;color:#141b38;margin-bottom:7px;display:flex;align-items:center}.aioseo-notification>div .body .title div:first-child{flex:1;margin-right:5px;line-height:1.4}.aioseo-notification>div .body .notification-content{margin-bottom:10px;max-width:400px}.aioseo-notification>div .body .actions{flex-wrap:wrap;display:flex;align-items:center}.aioseo-notification>div .body .actions>*{margin-bottom:10px}.aioseo-notification>div .body .actions .aioseo-button{margin-right:20px}.aioseo-notification>div .body .actions .dismiss{color:#8c8f9a;font-size:14px}.aioseo-seo-site-score__circle{animation:aioseo-seo-site-score-fill 1s reverse;transform:rotate(-180deg);transform-origin:center;stroke:#00aa63}.aioseo-seo-site-score__circle.fast{-webkit-animation-duration:.5s;animation-duration:.5s;stroke:#df2a4a}.aioseo-seo-site-score__circle.medium{-webkit-animation-duration:.75s;animation-duration:.75s;stroke:#f18200}.aioseo-seo-site-score__background{stroke:#e8e8eb}@-webkit-keyframes aioseo-seo-site-score-fill{to{stroke-dasharray:0 100}}@keyframes aioseo-seo-site-score-fill{to{stroke-dasharray:0 100}}.aioseo-seo-site-score-svg-loading{-webkit-animation:aioseo-seo-site-score-svg-animation 2s linear infinite;animation:aioseo-seo-site-score-svg-animation 2s linear infinite}.aioseo-seo-site-score-loading__circle{-webkit-animation:aioseo-seo-site-score-fill-loading 2s ease-in-out infinite both;animation:aioseo-seo-site-score-fill-loading 2s ease-in-out infinite both;transform:rotate(-180deg);transform-origin:center;stroke:#005ae0}@-webkit-keyframes aioseo-seo-site-score-svg-animation{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes aioseo-seo-site-score-svg-animation{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@-webkit-keyframes aioseo-seo-site-score-fill-loading{0%,25%{stroke-dashoffset:90;transform:rotate(0)}50%,75%{stroke-dashoffset:10;transform:rotate(45deg)}to{stroke-dashoffset:90;transform:rotate(1turn)}}@keyframes aioseo-seo-site-score-fill-loading{0%,25%{stroke-dashoffset:90;transform:rotate(0)}50%,75%{stroke-dashoffset:10;transform:rotate(45deg)}to{stroke-dashoffset:90;transform:rotate(1turn)}}.aioseo-table-column{display:flex;flex-direction:column;flex-basis:100%;flex:1;padding:5px;justify-content:center}.aioseo-table-row{display:flex;flex-direction:row;flex-wrap:wrap;width:100%}.aioseo-wizard-body{background-color:#fff;max-width:900px;box-shadow:0 2px 5px rgba(0,0,0,.05)}.aioseo-wizard-body .body-content{padding:80px 140px}@media screen and (max-width:782px){.aioseo-wizard-body .body-content{padding:40px}}.aioseo-wizard-body .body-content .header{line-height:1.4}.aioseo-wizard-body .body-footer{border-top:1px solid #e8e8eb;padding:30px;display:flex;align-items:center}.aioseo-wizard-body .body-footer>*{margin-right:10px}.aioseo-wizard-body .body-footer>:last-child{margin-right:0}.aioseo-wizard-body .body-footer .spacer{flex:1 0 auto}.aioseo-wizard-close-and-exit{margin:96px 0;min-height:96px;text-align:center;font-size:14px}.aioseo-wizard-close-and-exit a{color:#8c8f9a!important}.aioseo-wizard-container{margin:40px auto;max-width:900px}@media screen and (max-width:782px){.aioseo-wizard-container{margin:0 20px}}.aioseo-wizard-header{display:flex;align-items:center;justify-content:center;flex-direction:column}.aioseo-wizard-header svg.aioseo-logo{width:100%;max-width:140px;height:auto;margin:60px 10px 40px 0}.aioseo-wizard-progress{display:flex;align-items:center;justify-content:center}@media screen and (max-width:782px){.aioseo-wizard-progress{display:none}}.aioseo-wizard-progress .circle{background-color:#dcdde1;width:16px;height:16px;border-radius:50%}.aioseo-wizard-progress .circle.active{background-color:#005ae0}.aioseo-wizard-progress .spacer{width:59px;border:1px solid #dcdde1;margin:0 12px}.aioseo-wizard-progress .spacer.active{border-color:#005ae0}.aioseo-wizard-steps{color:#8c8f9a;font-size:14px;margin-bottom:20px}.block-editor-block-card{align-items:center}.block-editor-block-card__title.block-editor-block-card__title{margin:0}.aioseo-sidebar-row{margin-bottom:16px}.aioseo-sidebar-row .aioseo-sidebar-title{font-weight:500}
dist/Lite/assets/css/chunk-common.rtl.css CHANGED
@@ -1 +1 @@
1
- .aioseo-app .aioseo-cta{margin-top:30px;background:#fff;width:100%;padding:40px;box-shadow:0 2px 5px rgba(0,0,0,.05);border:1px solid #e8e8eb}.aioseo-app .aioseo-cta.floating{margin-top:0;position:absolute;max-width:850px;right:50%;top:50%;transform:translateX(50%) translateY(-50%);box-shadow:0 5px 20px rgba(0,0,0,.1);border-radius:3px}.aioseo-app .aioseo-cta .header-text{line-height:1.4;font-weight:600;font-size:24px;text-align:center;color:#141b38}.aioseo-app .aioseo-cta .header-text span.large{line-height:1.4;font-size:32px}.aioseo-app .aioseo-cta .description{margin:30px 0 50px;width:100%;max-width:600px;text-align:center;font-size:16px;color:#141b38;line-height:1.4}.aioseo-app .aioseo-cta .description .aioseo-alert{margin-bottom:30px;text-align:right}.aioseo-app .aioseo-cta .feature-list{color:#141b38;font-size:16px;width:100%;max-width:500px;margin-bottom:50px}.aioseo-app .aioseo-cta .feature-list .aioseo-col{display:flex;align-items:flex-start}.aioseo-app .aioseo-cta .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:18px;min-width:18px;min-height:18px;margin-left:10px}.aioseo-app .aioseo-cta a.learn-more{margin-top:20px;color:#8c8f9a;font-size:14px}.aioseo-app .aioseo-cta .type-1{display:flex;flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2{margin:30px 50px 30px 0;display:flex}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:right}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-2>div{margin-left:20px;flex:0 0 50%}.aioseo-app .aioseo-cta .type-2 .featured-image{max-height:540px;border:1px solid #e8e8eb;flex:1;overflow:hidden;margin-left:-41px;margin-bottom:-71px;border-radius:0 5px 0 0}.aioseo-app .aioseo-cta .type-2 .featured-image img{max-height:600px}@media only screen and (max-width:912px){.aioseo-app .aioseo-cta .type-2{flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:center}.aioseo-app .aioseo-cta .type-2>div{text-align:center;margin-left:0;margin-bottom:30px;flex:1 0 100%;width:100%}.aioseo-app .aioseo-cta .type-2 .featured-image{margin:0 -10px -41px;border-radius:5px 5px 0 0;max-height:300px}}.aioseo-app .aioseo-cta .type-3 .sub-header{line-height:1.4;font-size:16px;font-weight:600;color:#005ae0;margin-bottom:5px}.aioseo-app .aioseo-cta .type-3 .header-text{text-align:right}.aioseo-app .aioseo-cta .type-3 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-3 .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:21px;min-width:21px;min-height:21px;margin-left:5px}.aioseo-app .aioseo-cta .type-3 .aioseo-button{margin-left:12px}.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:calc(200px + 1em)}@media only screen and (max-width:48em){.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:100%}}.aioseo-box-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-box-toggle input:checked+label{background-color:#fff;box-shadow:0 5px 10px rgba(0,90,224,.1);border:2px solid #005ae0;font-weight:600}.aioseo-box-toggle label{background-color:#f9f9fa;color:#141b38;font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;border:1px solid #f9f9fa;transition:all .1s ease-in-out;border-radius:3px;height:165px;position:relative}.aioseo-box-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-box-toggle label:hover{cursor:pointer}.aioseo-button{flex-shrink:0;line-height:1;display:inline-flex;align-items:center;justify-content:center;font-size:16px;font-weight:600;padding:0 24px;border-radius:4px;-webkit-appearance:none;cursor:pointer;height:48px;transition:background-color .2s ease;position:relative;overflow:hidden;text-decoration:none;color:#141b38;white-space:nowrap}.aioseo-button.small{height:30px;font-size:14px;padding:0 12px}.aioseo-button.small .loading-spinner{width:25px;height:25px}.aioseo-button.medium{height:40px;font-size:14px;padding:0 18px}.aioseo-button.medium .loading-spinner{width:35px;height:35px}.aioseo-button.xl{height:66px;border-radius:4px;font-size:18px;padding:0 48px}.aioseo-button.gray{border:1px solid #dcdde1;background-color:#f3f4f5}.aioseo-button.gray:hover{background-color:#fff;color:#141b38}.aioseo-button.gray:active{background-color:#f3f4f5}.aioseo-button.green{border:none;background-color:#00aa63;color:#fff}.aioseo-button.green:hover{background-color:#07c575}.aioseo-button.green:active{background-color:#15955f}.aioseo-button.blue{border:none;background-color:#005ae0;color:#fff}.aioseo-button.blue:hover{background-color:#1a82ea}.aioseo-button.blue:active{background-color:#004f9d}.aioseo-button.wp-blue{border:1px solid #005ae0;background-color:#f3f5f6;color:#005ae0}.aioseo-button.wp-blue:hover{background-color:#1a82ea;border-color:#1a82ea;color:#fff}.aioseo-button.wp-blue:active{background-color:#004f9d;border-color:#004f9d;color:#fff}.aioseo-button.black{border:none;background-color:#434960;color:#fff}.aioseo-button.black:hover{background-color:#2c324c}.aioseo-button.black:active{background-color:#141b38}.aioseo-button.red{border:1px solid #df2a4a;background-color:#fff;color:#df2a4a}.aioseo-button.red:hover{background-color:#df2a4a;color:#fff}.aioseo-button.red:active{background-color:#ab2039}.aioseo-button.loading.blue,.aioseo-button.loading.blue:hover{background-color:#004f9d;color:#004f9d}.aioseo-button.loading.green,.aioseo-button.loading.green:hover{background-color:#15955f;color:#15955f}.aioseo-button.loading.gray,.aioseo-button.loading.gray:hover{background-color:#f3f4f5;color:#f3f4f5}.aioseo-button.loading.black,.aioseo-button.loading.black:hover{background-color:#141b38;color:#141b38}.aioseo-button:disabled{color:#8c8f9a;background-color:#f3f4f5;cursor:default}.aioseo-button:disabled.gray:hover{color:#8c8f9a}.aioseo-button:disabled.wp-blue{border-color:#ddd;background-color:#f7f7f7}.aioseo-button:disabled.wp-blue:hover{border-color:#ddd;color:#8c8f9a}.aioseo-button:disabled:hover{background-color:#f3f4f5}.aioseo-checkbox{display:inline-flex;align-items:center}.aioseo-checkbox.disabled,.aioseo-checkbox.disabled .form-checkbox .fancy-checkbox,.aioseo-checkbox.no-clicks,.aioseo-checkbox.no-clicks .form-checkbox .fancy-checkbox{cursor:default}.aioseo-checkbox .form-checkbox-wrapper{margin-left:10px;display:flex}.aioseo-checkbox.medium .form-checkbox{width:20px;height:20px}.aioseo-checkbox.medium .form-checkbox .fancy-checkbox svg{width:12px;height:12px}.aioseo-checkbox.medium .form-checkbox span:before{height:18px;width:18px;line-height:20px}.aioseo-checkbox.round .form-checkbox span,.aioseo-checkbox.round .form-checkbox span:before{border-radius:50%}.aioseo-checkbox .form-checkbox{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-checkbox .form-checkbox input{display:none}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.blue{background:#005ae0}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.green{background:#00aa63}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox:before{background:transparent}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox{background:#e8e8eb!important;border:1px solid #d0d1d7;cursor:default}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox svg{color:#8c8f9a}.aioseo-checkbox .form-checkbox input:not(:checked):disabled+.fancy-checkbox:before{right:0;bottom:0;background:#e8e8eb}.aioseo-checkbox .form-checkbox .fancy-checkbox svg{color:#fff;width:16px;height:16px}.aioseo-checkbox .form-checkbox span{position:absolute;cursor:pointer;top:0;right:0;left:0;bottom:0;background-color:#d0d1d7;transition:.2s;border-radius:3px;display:flex;align-items:center;justify-content:center}.aioseo-checkbox .form-checkbox span:before{position:absolute;content:"";height:26px;width:26px;right:1px;bottom:1px;background-color:#fff;transition:.2s;font-size:18px;line-height:28px;border-radius:2px}.aioseo-date-picker.vue-daterange-picker{width:100%}.aioseo-date-picker.vue-daterange-picker .form-control{display:flex;align-items:center;color:#141b38;font-size:16px;height:48px;border-radius:3px;border:1px solid #d0d1d7;position:relative}.aioseo-date-picker.vue-daterange-picker .form-control svg.aioseo-circle-close{position:absolute;left:10px;color:#434960;width:15px;height:15px}.aioseo-date-picker.vue-daterange-picker.small .form-control{height:30px}.aioseo-date-picker.vue-daterange-picker.medium .form-control{height:40px}body[class*=all-in-one-seo_page] .daterangepicker .yearselect{width:75px}.aioseo-editor{position:relative}.aioseo-editor .aioseo-editor-description .ql-editor{min-height:100px}.aioseo-editor .aioseo-editor-line-numbers .ql-editor{padding:15px 45px 15px 15px}.aioseo-editor .aioseo-editor-single .ql-editor{padding:8px 10px}.aioseo-editor .aioseo-editor-single.aioseo-editor-line-numbers .ql-editor{padding:8px 45px 8px 10px}.aioseo-editor .aioseo-editor-monospace .ql-editor{font-family:monospace}.aioseo-editor .aioseo-line-numbers{background:#f7f6f7;position:absolute;text-align:left;top:1px;width:29px;right:1px;border-radius:0 3px 3px 0;padding:15px 0 0 9px;display:flex;height:calc(100% - 2px);flex-direction:column;overflow:hidden}.aioseo-editor .aioseo-line-numbers div{min-height:25px;color:#8c8f9a;font-size:12px;line-height:1.9}.aioseo-editor .ql-disabled{pointer-events:none;background-color:#f9f9fa}.aioseo-editor .ql-editor{padding:15px;border-radius:3px;font-size:16px;color:#141b38;border:1px solid #d0d1d7}.aioseo-editor .ql-editor:focus{border:1px solid #005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-editor .ql-editor .mention .ql-mention-denotation-char{display:none}.aioseo-editor .ql-editor .mention .aioseo-tag{height:25px;margin:0 1px;color:#434960;font-weight:600;font-size:14px;padding:3px 10px 3px 25px;background-color:#f3f4f5;border-radius:3px;cursor:pointer;position:relative;display:inline-flex;align-items:center}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle{display:inline-flex;align-items:center;background-color:#e8e8eb;position:absolute;top:0;left:0;bottom:0;border-radius:3px 0 0 3px}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret{width:18px;height:18px;transition:transform .3s}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret.rotated{transform:rotate(-180deg)}.aioseo-editor .ql-mention-list-container{color:#141b38;background-color:#fff;max-width:250px;width:100%;margin-top:3px;border:1px solid #d0d1d7;border-radius:3px;box-shadow:0 3px 15px rgba(0,0,0,.1);z-index:9001}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom,.aioseo-editor .ql-mention-list-container .aioseo-tag-search{padding:12px;border-bottom:1px solid #e8e8eb}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom{display:none}.aioseo-editor .ql-mention-list-container .ql-mention-list{list-style:none;margin:0;padding:0;max-height:210px;overflow:auto}.aioseo-editor .ql-mention-list-container .ql-mention-list li{color:#141b38;margin:0;background-color:transparent;border-bottom:1px solid #e8e8eb;padding:15px;cursor:pointer;font-size:14px}.aioseo-editor .ql-mention-list-container .ql-mention-list li:last-child{border-bottom:0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover{color:#005ae0;background-color:#f2f7fd}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected .aioseo-tag-description,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover .aioseo-tag-description{color:initial}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item{display:flex}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item>div:first-child{margin-left:10px}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item .aioseo-tag-title{font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match{cursor:default;padding:12px;font-size:16px;font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match.highlight,.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match:hover{color:initial;background-color:transparent}.aioseo-editor .ql-toolbar{display:none}.aioseo-editor .ql-clipboard{right:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.aioseo-editor .ql-snow .ql-hidden{display:none}.aioseo-editor .ql-container.ql-snow{border:none}.aioseo-editor .ql-container p{font-size:16px;margin:0;line-height:25px}.aioseo-highlight-toggle{border:1px solid #e8e8eb;border-radius:3px;min-height:48px;display:flex;align-items:center;padding:5px 10px;cursor:pointer}.aioseo-highlight-toggle>*{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-highlight-toggle.active{border-color:#005ae0;box-shadow:0 5px 10px rgba(0,90,224,.1)}.aioseo-highlight-toggle.medium{min-height:40px}.aioseo-highlight-toggle .icon{display:flex;align-items:center;margin-left:5px}.aioseo-input[data-v-20c03142]{position:relative;width:100%}.aioseo-input.file[data-v-20c03142],.aioseo-input.file input[type=file][data-v-20c03142]{position:absolute;top:0;left:0;right:0;bottom:0;margin:0;padding:0}.aioseo-input.file input[type=file][data-v-20c03142]{cursor:pointer;opacity:0}.aioseo-input.file input[type=file][data-v-20c03142]::-webkit-file-upload-button{visibility:hidden}.aioseo-input.file input[type=file][data-v-20c03142]:focus{box-shadow:none}.aioseo-input input[data-v-20c03142]{height:48px;width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:3px;padding:15px;font-size:18px;position:relative;overflow:hidden;margin:0}.aioseo-input input[data-v-20c03142]:disabled{background:#f9f9fa}.aioseo-input input[data-v-20c03142]:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-input input[data-v-20c03142]::-moz-placeholder{color:#8c8f9a}.aioseo-input input[data-v-20c03142]:-ms-input-placeholder{color:#8c8f9a}.aioseo-input input[data-v-20c03142]::placeholder{color:#8c8f9a}.aioseo-input input.prepend[data-v-20c03142]{padding-right:50px}.aioseo-input input.append[data-v-20c03142]{padding-left:50px}.aioseo-input input.small[data-v-20c03142]{height:30px;padding:10px;font-size:14px}.aioseo-input input.small.prepend[data-v-20c03142]{padding-right:30px}.aioseo-input input.small.append[data-v-20c03142]{padding-left:30px}.aioseo-input input.medium[data-v-20c03142]{height:40px;padding:12px;font-size:16px}.aioseo-input input.medium.prepend[data-v-20c03142]{padding-right:35px}.aioseo-input input.medium.append[data-v-20c03142]{padding-left:35px}.aioseo-input.aioseo-active input[data-v-20c03142]{border-color:#00aa63}.aioseo-input.aioseo-active input[data-v-20c03142]:active,.aioseo-input.aioseo-active input[data-v-20c03142]:focus{box-shadow:0 0 0 1px #00aa63}.aioseo-input.aioseo-active .append-icon[data-v-20c03142],.aioseo-input.aioseo-active .prepend-icon[data-v-20c03142]{color:#00aa63}.aioseo-input.aioseo-error input[data-v-20c03142]{border-color:#df2a4a}.aioseo-input.aioseo-error input[data-v-20c03142]:active,.aioseo-input.aioseo-error input[data-v-20c03142]:focus{box-shadow:0 0 0 1px #df2a4a}.aioseo-input.aioseo-error .append-icon[data-v-20c03142],.aioseo-input.aioseo-error .prepend-icon[data-v-20c03142]{color:#df2a4a}.aioseo-input.aioseo-warning input[data-v-20c03142]{border-color:#f18200}.aioseo-input.aioseo-warning input[data-v-20c03142]:active,.aioseo-input.aioseo-warning input[data-v-20c03142]:focus{box-shadow:0 0 0 1px #f18200}.aioseo-input.aioseo-warning .append-icon[data-v-20c03142],.aioseo-input.aioseo-warning .prepend-icon[data-v-20c03142]{color:#f18200}.aioseo-input .prepend-icon[data-v-20c03142]{position:absolute;top:0;right:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .prepend-icon svg[data-v-20c03142]{width:30px;height:30px}.aioseo-input .prepend-icon.small[data-v-20c03142]{width:20px}.aioseo-input .prepend-icon.small svg[data-v-20c03142]{width:10px;height:10px}.aioseo-input .prepend-icon.medium[data-v-20c03142]{width:15px}.aioseo-input .prepend-icon.medium svg[data-v-20c03142]{width:15px;height:15px}.aioseo-input .append-icon[data-v-20c03142]{position:absolute;top:0;left:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .append-icon svg[data-v-20c03142]{width:30px;height:30px}.aioseo-input .append-icon.small[data-v-20c03142]{width:10px}.aioseo-input .append-icon.medium[data-v-20c03142]{width:15px}.aioseo-input .append-icon.clickable[data-v-20c03142]{cursor:pointer;padding:0 5px;background:#f3f4f5;border:1px solid #d0d1d7;color:#434960;left:0;width:30px;border-radius:3px 0 0 3px}.aioseo-input .append-icon.clickable.small[data-v-20c03142]{width:15px}.aioseo-input .append-icon.clickable.medium[data-v-20c03142]{padding:0 10px;width:40px}.aioseo-phone-number{max-width:600px}.aioseo-phone-number label{display:none}.aioseo-phone-number .maz-input__input{height:40px;min-height:40px;padding-top:0!important;border:1px solid #d0d1d7}.aioseo-phone-number .maz-input__input:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .country-selector{flex:0 0 140px;width:140px;min-width:140px;max-width:140px}.aioseo-phone-number .country-selector:hover{z-index:1}.aioseo-phone-number .country-selector>div.maz-base-component.maz-input.has-value.has-1-right-icon.maz-input--primary>input{padding-right:50px!important}.aioseo-phone-number .country-selector .maz-input.is-focused{border-color:#005ae0}.aioseo-phone-number .country-selector .maz-select__options-list__item.selected.keyboard-selected{background-color:#005ae0}.aioseo-phone-number .maz-phone-number-input__country-flag{right:20px;bottom:12px}.aioseo-phone-number .maz-select__options-list input{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .maz-input__input{border-radius:3px}.aioseo-phone-number .input-phone-number,.aioseo-phone-number .input-phone-number:focus{z-index:2}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input{border-color:red}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input:focus{border-color:#df2a4a;box-shadow:0 0 0 1px #df2a4a}.aioseo-phone-number.validNumber div.maz-flex-1>div>input:focus{border-color:#00aa63;box-shadow:0 0 0 1px #00aa63}.aioseo-radio{display:inline-flex;align-items:center}.aioseo-radio .form-radio-wrapper{margin-left:10px;display:flex}.aioseo-radio.medium .form-radio{width:20px;height:20px}.aioseo-radio.medium .form-radio .fancy-radio svg{width:12px;height:12px}.aioseo-radio.medium.type-1 .form-radio span:before{height:18px;width:18px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:before{height:16px;width:16px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:after{height:6px;width:6px;right:6px;bottom:6px}.aioseo-radio .form-radio{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-radio .form-radio input{opacity:0}.aioseo-radio .form-radio input:checked+.fancy-radio{background:#005ae0;border-color:#005ae0}.aioseo-radio .form-radio input:checked+.fancy-radio:before{background:transparent}.aioseo-radio .form-radio input:checked+.fancy-radio:after{display:block}.aioseo-radio .form-radio input:disabled+.fancy-radio{cursor:default}.aioseo-radio .form-radio input:focus+.fancy-radio{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-radio .form-radio .fancy-radio{border-radius:50%}.aioseo-radio .form-radio .fancy-radio svg{color:#fff;width:16px;height:16px}.aioseo-radio .form-radio span{position:absolute;cursor:pointer;top:0;right:0;left:0;bottom:0;transition:.2s;border-radius:50%;display:flex;align-items:center;justify-content:center}.aioseo-radio .form-radio span:before{position:absolute;content:"";height:26px;width:26px;right:1px;bottom:1px;transition:.2s;font-size:18px;line-height:28px;border-radius:50%}.aioseo-radio.type-1 .form-radio span,.aioseo-radio.type-1 .form-radio span:before{background-color:#f3f4f5}.aioseo-radio.type-2 .form-radio span{border:1px solid #d0d1d7;background-color:#fff}.aioseo-radio.type-2 .form-radio span:before{background-color:#fff}.aioseo-radio.type-2 .form-radio span:after{display:none;position:absolute;content:"";height:10px;width:10px;right:8px;bottom:8px;background-color:#fff;transition:.2s;border-radius:50%}.aioseo-radio.disabled{cursor:default}.aioseo-radio.disabled.type-2 .form-radio input:checked+.fancy-radio{background-color:#e8e8eb;border-color:#d0d1d7}.aioseo-radio.disabled.type-2 .form-radio span,.aioseo-radio.disabled.type-2 .form-radio span:before{background-color:#e8e8eb}.aioseo-radio.disabled.type-2 .form-radio span:after{background-color:#8c8f9a}.aioseo-radio-toggle{display:flex;align-items:center;height:40px}.aioseo-radio-toggle div{height:100%}.aioseo-radio-toggle.inline{display:inline-flex}.aioseo-radio-toggle div:first-child{overflow:hidden;border-radius:0 3px 3px 0}.aioseo-radio-toggle div:first-child label{border-radius:0 3px 3px 0}.aioseo-radio-toggle div:last-child{overflow:hidden;border-radius:3px 0 0 3px}.aioseo-radio-toggle div:last-child label{border-radius:3px 0 0 3px}.aioseo-radio-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-radio-toggle input:checked+label{background-color:#005ae0;color:#fff}.aioseo-radio-toggle input:checked+label.dark{background-color:#434960;color:#fff}.aioseo-radio-toggle label{height:100%;background-color:#e8e8eb;color:#141b38;font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;transition:all .1s ease-in-out;position:relative;padding:11px 20px;font-weight:600}.aioseo-radio-toggle label.disabled{cursor:default;pointer-events:none;opacity:.5}.aioseo-radio-toggle label:hover{background-color:#dadadf;cursor:pointer}.aioseo-radio-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-radio-toggle.circle label{background:#fff;color:#8c8f9a}.aioseo-radio-toggle.circle input+label{border-radius:50%;width:36px;height:36px;padding:8px}.aioseo-radio-toggle.circle input:checked+label{background:#e8e8eb;color:#2c324c}.aioseo-select{height:48px}.aioseo-select.multiselect--disabled .multiselect__select{background:none}.aioseo-select .multiselect__select{display:flex;align-items:center;justify-content:center;min-height:46px}.aioseo-select .multiselect__select:before{display:none}.aioseo-select .multiselect__select svg.aioseo-caret{color:#141b38;width:18px;height:18px;transition:transform .3s}.aioseo-select .multiselect__tags{height:100%;border:1px solid #d0d1d7;border-radius:3px;display:flex;justify-content:center;flex-direction:column;padding:16px 16px 16px 40px}.aioseo-select .multiselect__tags .multiselect__spinner{height:calc(100% - 2px);border:2px solid transparent}.aioseo-select .multiselect__tags .multiselect__spinner:after,.aioseo-select .multiselect__tags .multiselect__spinner:before{border-top-color:#434960}.aioseo-select .multiselect__tags .multiselect__single{display:inline-flex;margin:0;padding:0;color:#141b38;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.aioseo-select .multiselect__tags .multiselect__placeholder{color:#8c8f9a;font-size:16px;line-height:20px;margin:0;padding:0}.aioseo-select .multiselect__tags .multiselect__input{padding:0;margin:0 0 0 10px;border-radius:0;border:none;color:#141b38;min-height:auto;line-height:20px}.aioseo-select .multiselect__tags .multiselect__input:focus{outline:0;box-shadow:none;border:none}.aioseo-select .multiselect__tags .multiselect__input::-moz-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input:-ms-input-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input::placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__tags-wrap{display:flex;align-items:center;flex-wrap:wrap}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag{padding:0;display:inline-flex;align-items:center;font-size:14px;font-weight:600;color:#434960;margin:0 0 0 3px;height:24px;background-color:#f3f4f5;flex-shrink:0}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-value{padding:0 10px 0 5px}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove{padding:0 10px;height:100%;cursor:pointer;background-color:#f3f4f5;display:flex;align-items:center}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover{background-color:#434960;color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover svg.aioseo-close{color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove svg.aioseo-close{color:#434960;width:10px;height:10px}.aioseo-select.multiselect--active .multiselect__tags-wrap{margin-bottom:7px}.aioseo-select.small{height:30px;min-height:30px}.aioseo-select.small .multiselect__tags{min-height:30px;padding:8px 8px 8px 38px}.aioseo-select.small .multiselect__tags .multiselect__placeholder{font-size:14px}.aioseo-select.small .multiselect__select{height:28px;min-height:28px}.aioseo-select.small .multiselect__input{font-size:14px}.aioseo-select.small .multiselect__content-wrapper li.multiselect__element .multiselect__option{font-size:14px;padding:8px;min-height:30px}.aioseo-select.medium{height:40px}.aioseo-select.medium .multiselect__tags{padding:7px 7px 7px 40px}.aioseo-select.medium .multiselect__select{min-height:38px}.aioseo-select.multiple{min-height:48px;height:auto}.aioseo-select.multiple.small{min-height:30px}.aioseo-select.multiple.medium{min-height:40px}.aioseo-select.multiselect--above .multiselect__content-wrapper{border-top:1px solid #d0d1d7;border-bottom:none}.aioseo-select .multiselect__content-wrapper{border:1px solid #d0d1d7;border-top:none;border-bottom-right-radius:3px;border-bottom-left-radius:3px;z-index:50;-webkit-overflow-scrolling:touch}.aioseo-select .multiselect__content-wrapper .multiselect__content{max-width:100%}.aioseo-select .multiselect__content-wrapper li.multiselect__element{margin:0;border-bottom:1px solid #e8e8eb}.aioseo-select .multiselect__content-wrapper li.multiselect__element.last{border-bottom:none}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight:after{background-color:#005ae0;color:#fff}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--selected{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--disabled{font-weight:400;background-color:#fff!important;color:#8c8f9a}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option .docLink{font-size:13px;float:left}.aioseo-textarea-autosize{width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:4px;font-size:16px;padding:12px}.aioseo-toggle{display:inline-flex}.aioseo-toggle:active,.aioseo-toggle:focus{outline:2px solid transparent}.aioseo-toggle.disabled{pointer-events:none}.aioseo-toggle.disabled .toggle-content{opacity:.5}.aioseo-toggle .toggle-content{position:relative;display:inline-block;width:36px;height:20px;margin-left:10px}.aioseo-toggle .toggle-content input{display:none}.aioseo-toggle .toggle-content input:checked+.toggle-switch{border:1px solid #005ae0;background-color:#005ae0}.aioseo-toggle .toggle-content input:checked+.toggle-switch:focus{outline:2px solid transparent}.aioseo-toggle .toggle-content input:checked+.toggle-switch:before{background-color:#fff;transform:translateX(-15px)}.aioseo-toggle .toggle-content input:focus+.toggle-switch{box-shadow:0 0 1px #005ae0;outline:2px solid transparent}.aioseo-toggle .toggle-content .toggle-switch{position:absolute;cursor:pointer;top:0;right:0;left:0;bottom:0;background-color:#fff;border:1px solid #d0d1d7;border-radius:15px;transition:.2s}.aioseo-toggle .toggle-content .toggle-switch:before{position:absolute;content:"";height:14px;width:14px;right:3px;bottom:2px;background-color:#d0d1d7;border-radius:50%;transition:.2s}.aioseo-wp-table input[type=search],.aioseo-wp-table select{border-color:#d0d1d7}.aioseo-wp-table select:focus{border-color:#005ae0;color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-wp-table select:hover{color:#005ae0}.aioseo-wp-table input.button,.aioseo-wp-table input.button:hover{color:#005ae0;border-color:#005ae0}.aioseo-wp-table .header .subsubsub{color:#555d66;font-size:13px;font-weight:600}.aioseo-wp-table .header .subsubsub>span{display:inline-flex}.aioseo-wp-table .header .subsubsub .separator{margin:0 5px}.aioseo-wp-table .header .subsubsub .active{font-weight:700;color:#141b38}.aioseo-wp-table .header .subsubsub a{text-decoration:none}.aioseo-wp-table .header .subsubsub a:hover{text-decoration:underline}.aioseo-wp-table .header .search{display:flex;justify-content:flex-end}.aioseo-wp-table .header .search .aioseo-input{width:100%;max-width:215px;margin-left:6px}.aioseo-wp-table .header .pagination{color:#555d66}.aioseo-wp-table .header .pagination .button,.aioseo-wp-table .header .pagination input{margin-right:6px}.aioseo-wp-table .tablenav-pages .current-page{padding:0 8px 0 0}.aioseo-wp-table .wp-table{width:100%;position:relative}.aioseo-wp-table .wp-table .loader-overlay{position:absolute;top:46px;left:0;bottom:36px;right:0;background:rgba(0,0,0,.3);z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-wp-table .wp-table .no-results{color:#8c8f9a;min-height:200px;display:flex;align-items:center;justify-content:center;font-weight:400;font-size:24px}.aioseo-wp-table .wp-table tr.even{background-color:#f9f9fa}.aioseo-wp-table .wp-table tr.enabled td,.aioseo-wp-table .wp-table tr.enabled td strong a{color:#141b38}.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td,.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td a.edit-link{color:#8c8f9a}.aioseo-wp-table .wp-table tr.edit-row th{padding:0 3px 0 0}.aioseo-wp-table .wp-table tr.edit-row td{padding:0 10px 0 30px}.aioseo-wp-table .wp-table tr td strong a{font-weight:400}.aioseo-wp-table .wp-table tr td .row-actions .edit a,.aioseo-wp-table .wp-table tr td strong a:hover{color:#005ae0}.aioseo-wp-table .wp-table tr td .row-actions .edit .trash a{color:#df2a4a}.aioseo-wp-table .wp-table tr td.edit-row-content .wrapper .border{padding:8px 0;border-top:1px solid #e8e8eb}.aioseo-add-404-redirection .generic-error{margin-bottom:20px}.aioseo-add-404-redirection .aioseo-settings-row .settings-name .name{font-size:14px}.aioseo-add-404-redirection .urls{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap}.aioseo-add-404-redirection .urls .target{flex:1;display:flex;align-items:center;max-width:480px;min-width:400px;margin-left:20px}.aioseo-add-404-redirection .urls .target>*{flex:1}.aioseo-add-404-redirection .urls .target .aioseo-input{margin-bottom:10px}.aioseo-add-404-redirection .urls .target .aioseo-description{height:30px}.aioseo-add-404-redirection .urls .target .append-icon{width:60px;justify-content:flex-end}.aioseo-add-404-redirection .urls .target .append-icon svg{max-width:16px;margin-left:5px}.aioseo-add-404-redirection .urls .target .append-icon svg:last-of-type{margin-left:0}.aioseo-add-404-redirection .urls .target .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-add-404-redirection .urls .target .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-add-404-redirection .urls .target .target-url-error,.aioseo-add-404-redirection .urls .target .target-url-warning{margin-bottom:10px}.aioseo-add-404-redirection .urls .redirect-type{flex:1;align-self:flex-start}.aioseo-add-404-redirection .urls .redirect-type .aioseo-select{max-width:220px}.aioseo-add-404-redirection .settings{display:flex;flex-direction:row;align-items:center;margin-top:30px}.aioseo-add-404-redirection .settings .all-settings{flex:1}.aioseo-add-404-redirection .settings .all-settings .all-settings-content{display:flex;align-items:center}.aioseo-add-404-redirection .settings .redirect-type{width:100%;max-width:350px;margin-left:24px}.aioseo-add-404-redirection .settings .redirect-type .aioseo-select{margin-top:5px}.aioseo-add-404-redirection .settings .aioseo-button{align-self:flex-end}.aioseo-add-404-redirection .settings .cancel-edit-row{margin-right:10px}.custom-rules[data-v-7e05ebd5]{width:100%}.custom-rules .rule-table[data-v-7e05ebd5]{margin-top:5px;border:1px solid #d0d1d7;border-radius:3px;width:100%;font-family:Helvetica;font-size:14px;font-style:normal;font-weight:400;line-height:21px;letter-spacing:0;text-align:right}.custom-rules .rule-table .rule[data-v-7e05ebd5]{padding:13px;background:#f9f9fa}.custom-rules .rule-table .rule.even[data-v-7e05ebd5]{background-color:#fff}.custom-rules .rule[data-v-7e05ebd5]{display:flex;flex-direction:row;align-items:center;padding-top:10px}.custom-rules .rule[data-v-7e05ebd5]:first-child{border-radius:3px 3px 0 0}.custom-rules .rule[data-v-7e05ebd5]:last-child{border-radius:0 0 3px 3px}.custom-rules .rule .rule-settings>.aioseo-select[data-v-7e05ebd5]:first-child{width:250px;min-width:250px}.custom-rules .rule .rule-settings[data-v-7e05ebd5]{display:flex;flex-direction:row;align-items:center;flex:1}.custom-rules .rule .rule-settings>[data-v-7e05ebd5]{margin:0 0 0 6px}.custom-rules .rule .rule-settings>.aioseo-toggle[data-v-7e05ebd5]{margin:0 4px 0 10px}.custom-rules .rule .actions[data-v-7e05ebd5],.custom-rules .rule .logical[data-v-7e05ebd5]{flex:0}.custom-rules svg[data-v-7e05ebd5]{width:14px;height:14px;cursor:pointer}.custom-rules svg.aioseo-trash[data-v-7e05ebd5]{color:#dadada}.custom-rules svg.aioseo-trash[data-v-7e05ebd5]:hover{color:#df2a4a}.custom-rules .aioseo-tooltip[data-v-7e05ebd5]{margin:0;display:flex}.custom-rules .aioseo-button svg[data-v-7e05ebd5]{color:#fff}.custom-rules .add-rule[data-v-7e05ebd5]{margin-top:10px}.custom-rules .add-rule svg[data-v-7e05ebd5]{margin-left:6px}.aioseo-add-redirection.edit-url{margin-bottom:30px}.aioseo-add-redirection.edit-url .urls{align-items:flex-start}.aioseo-add-redirection.edit-url .urls .url-arrow{margin:-8px 30px 0}.aioseo-add-redirection.edit-url .advanced-settings-link{text-decoration:underline;margin-top:21px}.aioseo-add-redirection.log-404 .urls .source{min-height:103px;align-items:flex-start}.aioseo-add-redirection .generic-error{margin-bottom:20px}.aioseo-add-redirection .aioseo-settings-row .settings-name .name{font-size:14px}.aioseo-add-redirection .urls{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .urls .break{flex-basis:100%;height:0}.aioseo-add-redirection .urls .url-arrow{width:36px;margin:-15px 30px 0;display:flex;align-items:center;justify-content:center}.aioseo-add-redirection .urls .url-arrow svg{height:103px;color:#005ae0}.aioseo-add-redirection .urls .source,.aioseo-add-redirection .urls .target{flex:1;display:flex;align-items:center}.aioseo-add-redirection .urls .source>*,.aioseo-add-redirection .urls .target>*{flex:1}.aioseo-add-redirection .urls .source .aioseo-input,.aioseo-add-redirection .urls .target .aioseo-input{margin-bottom:10px}.aioseo-add-redirection .urls .target .aioseo-description{height:30px}.aioseo-add-redirection .urls .target .append-icon{width:60px;justify-content:flex-end}.aioseo-add-redirection .urls .target .append-icon svg{max-width:16px;margin-left:5px}.aioseo-add-redirection .urls .target .append-icon svg:last-of-type{margin-left:0}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-add-redirection .urls .target .target-url-error,.aioseo-add-redirection .urls .target .target-url-warning{margin-bottom:10px}.aioseo-add-redirection .settings{display:flex;flex-direction:column;align-items:center;margin-top:30px}.aioseo-add-redirection .settings .all-settings{width:100%}.aioseo-add-redirection .settings .all-settings .all-settings-content{display:flex;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .settings .all-settings .all-settings-content .advanced-settings-link{margin:16px 16px 0 0;color:#8c8f9a}@media (max-width:767px){.aioseo-add-redirection .settings .all-settings .all-settings-content{align-items:start}}.aioseo-add-redirection .settings>.actions{align-self:flex-end;margin-top:-50px}.aioseo-add-redirection .settings>.actions.advanced{margin-top:-40px}.aioseo-add-redirection .settings .query-params,.aioseo-add-redirection .settings .redirect-type{margin-bottom:10px;flex:0 1 auto}.aioseo-add-redirection .settings .query-params .aioseo-select,.aioseo-add-redirection .settings .redirect-type .aioseo-select{margin-top:5px}.aioseo-add-redirection .settings .query-params{width:340px}.aioseo-add-redirection .settings .redirect-type{width:300px;margin-left:24px}.aioseo-add-redirection .settings .aioseo-button{align-self:flex-end}.aioseo-add-redirection .settings .cancel-edit-row{margin-right:10px}.aioseo-add-redirection-target-url,.aioseo-redirect-source-url{position:relative}.aioseo-redirect-source-url .aioseo-input input{padding-left:76px}.aioseo-redirect-source-url .aioseo-input .append-icon{width:60px;justify-content:flex-end}.aioseo-redirect-source-url .aioseo-input .append-icon svg{max-width:16px;margin-left:5px}.aioseo-redirect-source-url .aioseo-input .append-icon svg:last-of-type{margin-left:0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear:hover{color:#005ae0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash:hover{color:#df2a4a}.aioseo-redirect-source-url .source-url-error,.aioseo-redirect-source-url .source-url-warning{margin-bottom:10px}.aioseo-redirect-source-url .source-url-options>div{padding-bottom:5px}.aioseo-redirect-source-url .source-url-options>div>div{margin-bottom:5px}.aioseo-add-redirection-url-results{display:flex;position:absolute;background:#fff;width:100%;max-height:300px;overflow:auto;border:1px solid #d0d1d7;border-radius:3px;z-index:50;right:1px;margin-top:-9px}.aioseo-add-redirection-url-results ul{display:inline-block;max-width:100%;list-style:none;padding:0;margin:0;min-width:100%;vertical-align:top}.aioseo-add-redirection-url-results ul li{margin:0;border-bottom:1px solid #e8e8eb;display:block}.aioseo-add-redirection-url-results ul li:last-of-type{border-bottom:none}.aioseo-add-redirection-url-results ul li>span{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4;display:flex;padding:12px;min-height:40px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer}.aioseo-add-redirection-url-results ul li>span:hover{background-color:#f2f7fd}.aioseo-add-redirection-url-results ul li>span:hover .option-title{color:#005ae0}.aioseo-add-redirection-url-results .option{flex:1}.aioseo-add-redirection-url-results .option .option-title{font-weight:500;display:flex;font-size:16px;color:#141b38}.aioseo-add-redirection-url-results .option .option-title>div{margin-left:5px}.aioseo-add-redirection-url-results .option .option-title>div:first-of-type{display:inline-block}.aioseo-add-redirection-url-results .option .option-title .search-term{font-weight:700}.aioseo-add-redirection-url-results .option .option-details{display:flex;align-items:center;font-size:14px;color:#8c8f9a}.aioseo-add-redirection-url-results .option .option-details span{margin-left:15px}.aioseo-add-redirection-url-results .option-permalink{display:flex;align-items:center}.aioseo-add-redirection-url-results .option-permalink svg.aioseo-external{width:15px;height:15px;color:#434960}.aioseo-add-template-tag{border-radius:3px;padding:5px 10px;color:#141b38;font-size:14px;border:1px solid #e8e8eb;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-weight:600}.aioseo-add-template-tag:hover{background-color:#f3f4f5}.aioseo-add-template-tag svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-additional-pages .additional-pages-table{border:1px solid #d0d1d7;border-radius:3px;margin-bottom:20px}.aioseo-additional-pages .additional-pages-table .page-priority{max-width:110px}.aioseo-additional-pages .additional-pages-table .page-frequency{max-width:166px}.aioseo-additional-pages .additional-pages-table .page-last-modified{max-width:155px}.aioseo-additional-pages .additional-pages-table .page-actions{max-width:20px}.aioseo-additional-pages .additional-pages-table .page-actions .aioseo-tooltip{display:inline-block;margin:0}.aioseo-additional-pages .additional-pages-table .pages-header{height:50px;display:flex;font-size:14px;padding:0 30px;align-items:center;border-bottom:1px solid #d0d1d7}.aioseo-additional-pages .additional-pages-table .pages-header>div{flex:1 0 auto}.aioseo-additional-pages .additional-pages-table .pages-rows{font-size:14px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row{background-color:#fff;height:70px;display:flex;align-items:center;padding:0 30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row:last-of-type{border-radius:0 0 3px 3px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row.even{background-color:#f9f9fa}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div{flex:1 0 auto;padding-left:30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div:last-child{padding-left:0}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash{width:20px;height:20px;color:#8c8f9a;cursor:pointer;transition:color .1s ease}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash:hover{color:#df2a4a}.aioseo-additional-pages svg.aioseo-circle-plus{width:14px;height:14px;margin-left:10px}.aioseo-alert{position:relative;border-radius:3px;padding:24px;font-size:16px;color:#141b38;line-height:1.4}.aioseo-alert.small{padding:8px;font-size:13px}.aioseo-alert .aioseo-alert-close{cursor:pointer;position:absolute;top:-9px;left:-9px;width:18px;height:18px;border-radius:50%;padding:5px;display:inline-flex;justify-content:center;align-content:center}.aioseo-alert .aioseo-alert-close svg{width:100%;height:100%}.aioseo-alert.blue{border:1px solid #005ae0;background-color:#f2f7fd}.aioseo-alert.blue .aioseo-alert-close{background-color:#005ae0;color:#fff}.aioseo-alert.green{border:1px solid #00aa63;background-color:#f2fdf8}.aioseo-alert.green .aioseo-alert-close{background-color:#00aa63;color:#fff}.aioseo-alert.red{border:1px solid #df2a4a;background-color:#fbe9ec}.aioseo-alert.red .aioseo-alert-close{background-color:#df2a4a;color:#fff}.aioseo-alert.yellow{border:1px solid #f18200;background-color:#fcfae8}.aioseo-alert.yellow .aioseo-alert-close{background-color:#f18200;color:#fff}.aioseo-alert.no-border{border-width:0}.aioseo-alert.text-center{text-align:center}.aioseo-analyze-competitor-site-score{border:1px solid #00aa63;border-radius:3px;color:#00aa63;font-size:14px;padding:0 8px;height:24px;display:inline-flex;align-items:center;justify-content:center;margin-left:14px}.aioseo-analyze-competitor-site-score.red{color:#df2a4a;border-color:#df2a4a}.aioseo-analyze-competitor-site-score.orange{color:#f18200;border-color:#f18200}.aioseo-animated-dannie{display:flex;align-content:center;align-items:center;justify-content:center}.aioseo-animated-dannie svg{max-width:250px}.aioseo-blur{filter:blur(3px);pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-card{color:#141b38;background-color:#fff;border:1px solid #e8e8eb;box-shadow:0 2px 5px rgba(0,0,0,.05);margin:30px 0}.aioseo-card.disabled .content{background:#f9f9fa;font-size:16px;line-height:24px}@media only screen and (max-width:782px){.aioseo-card{margin:20px 0}}.aioseo-card svg.aioseo-circle-question-mark{width:17px;height:17px;color:#8c8f99;transition:background-color .2s ease}.aioseo-card svg.aioseo-circle-question-mark:hover{color:#5a5c65}.aioseo-card .header{display:flex;align-items:center;height:70px;padding:0 30px;font-weight:600;font-size:18px;border-bottom:1px solid #e8e8eb}.aioseo-card .header .header-icon{display:flex}.aioseo-card .header .header-icon svg{width:24px;height:24px;margin-left:16px}.aioseo-card .header .text{flex:1 0 auto;display:flex;align-items:center}.aioseo-card .header .text svg.aioseo-circle-question-mark{cursor:pointer;width:17px;height:17px}.aioseo-card .header .text .aioseo-pro-badge{margin-right:10px}.aioseo-card .header .text .card-score{display:flex;flex:1;align-items:center;justify-content:flex-end;padding-left:18px;font-size:13px}.aioseo-card .header .text .card-score.green{color:#00aa63}.aioseo-card .header .text .card-score.orange{color:#f18200}.aioseo-card .header .text .card-score.red{color:#df2a4a}.aioseo-card .header .text .card-score svg{margin-left:7px}.aioseo-card .header svg.aioseo-caret{width:24px;height:24px;cursor:pointer;transform:rotate(180deg);transition:transform .3s}.aioseo-card .header svg.aioseo-caret.rotated{transform:rotate(90deg)}.aioseo-card .header svg.aioseo-close{width:14px;height:14px;cursor:pointer}.aioseo-card .content{padding:30px;position:relative}.aioseo-card div.aioseo-settings-row:last-child{margin-bottom:0;border-bottom:none;padding-bottom:0}.aioseo-copy-block{display:flex}.aioseo-copy-block .message{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-radius:0 3px 3px 0;padding:10px 24px;font-weight:600}.aioseo-copy-block .copy-tooltip{display:flex}.aioseo-copy-block .copy{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-right-width:0;border-radius:3px 0 0 3px;padding:10px 16px;font-weight:600;cursor:pointer}.aioseo-copy-block .copy:hover svg.aioseo-copy{color:#a7a7a7}.aioseo-copy-block .copy svg.aioseo-copy{width:20px;height:20px;color:#dadada}.aioseo-copy-block .copy svg.aioseo-circle-check-solid{width:20px;height:20px;color:#00aa63}.aioseo-display-info .aioseo-box-toggle svg{margin-top:-15px;color:#434960}.aioseo-display-info svg.aioseo-shortcode,.aioseo-display-info svg.aioseo-widget{width:100%;height:auto;max-width:60px}.aioseo-display-info svg.aioseo-gutenberg-block{width:59px;height:54px}.aioseo-display-info svg.aioseo-gutenberg-block rect{width:100%;width:56px;height:51px}.aioseo-display-info svg.aioseo-php{width:110px}.aioseo-display-info .copy-box{padding-top:.5rem}.aioseo-display-info .copy-box>div{padding:30px;border-radius:3px;background-color:#f9f9fa}.aioseo-display-info .copy-box .aioseo-description{margin:0}.aioseo-display-info .copy-box .aioseo-copy-block{margin:20px 0 0}.aioseo-display-info .aioseo-tooltip{margin-right:0}.aioseo-exclude-posts{display:flex}.aioseo-exclude-posts .aioseo-select{max-width:600px;display:inline-block;margin-left:10px}.aioseo-exclude-posts .aioseo-select .multiselect__option{display:flex}.aioseo-exclude-posts .aioseo-select .multiselect__option--highlight .option-title{color:#005ae0}.aioseo-exclude-posts .option{flex:1 0 auto}.aioseo-exclude-posts .option .option-title{font-weight:500;font-size:16px;color:#141b38}.aioseo-exclude-posts .option .option-title .search-term{font-weight:700}.aioseo-exclude-posts .option .option-details{display:flex;align-items:center;font-size:14px;color:#8c8f9a}.aioseo-exclude-posts .option .option-details span{margin-left:15px}.aioseo-exclude-posts .option-permalink{display:flex;align-items:center}.aioseo-exclude-posts .option-permalink svg.aioseo-external{width:15px;height:15px;color:#434960}.aioseo-exclude-posts .multiselect-toggle{padding:10px 13px;width:40px;position:absolute;height:36px;left:2px;top:2px;text-align:center;z-index:1}.aioseo-exclude-posts .multiselect-toggle svg.aioseo-add-plus{width:14px;height:14px;color:#000}.aioseo-facebook-preview{background-color:#f0f2f5;padding:30px;display:flex;align-items:center;justify-content:center}.aioseo-facebook-preview .facebook-post{width:100%;max-width:525px;border-radius:10px;box-shadow:0 2px 5px rgba(0,0,0,.1);background-color:#fff}.aioseo-facebook-preview .facebook-post .facebook-header{height:65px;padding:0 18px;display:flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo{overflow:hidden;width:40px;height:40px;border:1px solid #e8e8eb;border-radius:50%}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo img{height:100%;width:100%}.aioseo-facebook-preview .facebook-post .facebook-header .poster{margin-right:10px;flex:1 0 auto}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-name{font-size:15px;color:#050505;font-weight:500}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-date{color:#65676b;font-size:13px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis{display:inline-flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div{background-color:#5e666f;width:4px;height:4px;border-radius:50%;margin:0 2px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:first-child{margin-right:0}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:last-child{margin-left:0}.aioseo-facebook-preview .facebook-post .facebook-content{display:flex;flex-direction:column}.aioseo-facebook-preview .facebook-post .facebook-content img{width:100%;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content.vertical{flex-direction:row}.aioseo-facebook-preview .facebook-post .facebook-content.vertical img{max-width:158px;max-height:158px;width:auto;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description{flex:1;background-color:#f2f3f5;padding:9px 13px;color:#606770}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-domain{font-size:13px;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-title{color:#1d2129;font-size:17px;font-weight:600;margin:5px 0}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-description{font-size:14px}.aioseo-facebook-preview .facebook-post .facebook-footer{height:24px}.aioseo-feature-card{height:100%;border:1px solid #e8e8eb;background:#fff;box-shadow:0 2px 5px rgba(0,0,0,.05);color:#141b38;display:flex;flex-direction:column}.aioseo-feature-card .feature-card-body{padding:30px 30px 20px;flex:1}.aioseo-feature-card .feature-card-body.static{padding:30px}.aioseo-feature-card .feature-card-body .feature-card-header{display:flex;align-items:center;font-size:18px;font-weight:600;margin-bottom:16px}.aioseo-feature-card .feature-card-body .feature-card-header img,.aioseo-feature-card .feature-card-body .feature-card-header svg{width:28px;height:28px;margin-left:10px}.aioseo-feature-card .feature-card-body .feature-card-description{color:#434960;font-size:15px}.aioseo-feature-card .feature-card-body .feature-card-description .learn-more{margin-top:10px}.aioseo-feature-card .feature-card-footer{padding:15px}.aioseo-feature-card .feature-card-footer:not(.upgrade-required){border:2px solid #fff;background-color:#f9f9fa;padding:12px;min-height:43px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate{display:flex;align-items:center;justify-content:flex-end;height:30px;position:relative}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-loading-spinner{position:absolute;right:0}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .status{font-weight:600;font-size:14px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-toggle .toggle-content{margin-left:0;margin-right:10px}.aioseo-feature-card .feature-card-footer .feature-card-upgrade-cta{display:flex;align-items:center;justify-content:flex-end}.aioseo-feature-card .feature-card-footer.installed .feature-card-install-activate .status{color:#8c8f9a}.aioseo-setup-wizard-container{margin-top:30px;margin-bottom:50px;padding:30px;color:#fff;position:relative;background-color:#005ae0}@media only screen and (max-width:782px){.aioseo-setup-wizard-container{margin-top:20px}}.aioseo-setup-wizard-container p{color:#fff}.aioseo-setup-wizard-container .getting-started-wrapper{display:flex}.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 533px;margin:20px 20px 0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{padding-bottom:56.25%;margin-bottom:-60px;position:relative;height:0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper iframe{width:100%;height:100%;position:absolute;top:0;right:0}@media only screen and (max-width:1350px){.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 593px;margin:20px;align-self:center}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{margin-bottom:0}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}@media only screen and (max-width:1300px){.aioseo-setup-wizard-container .getting-started-wrapper{flex-direction:row;flex-wrap:wrap}.aioseo-setup-wizard-container .getting-started-wrapper .video{margin:20px 0 -60px}.aioseo-setup-wizard-container .getting-started-wrapper .text,.aioseo-setup-wizard-container .getting-started-wrapper .video{flex-basis:100%;width:100%}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions{justify-content:center}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:inherit;max-width:inherit;justify-content:center}}@media only screen and (max-width:782px){.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}.aioseo-setup-wizard-container .aioseo-row{position:relative;z-index:1}.aioseo-setup-wizard-container .wizard-actions .aioseo-col{display:flex;align-items:center}.aioseo-setup-wizard-container .wizard-actions .aioseo-button svg{width:16px;height:16px;margin-left:10px}.aioseo-setup-wizard-container .setup-wizard-bg{width:100%;height:100%;overflow:hidden;z-index:0;position:absolute;top:0;right:0}.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg,.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg rect{width:auto;height:100%}.aioseo-setup-wizard-container .close-wizard{color:#fff;width:20px;height:20px;position:absolute;left:20px;top:20px;z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-setup-wizard-container .close-wizard:hover{color:#ccc}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close{width:12px;height:12px;cursor:pointer;color:#fff}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close:hover{color:#dadada}.aioseo-setup-wizard-container p.how-to-get-started{margin:0}.aioseo-setup-wizard-container p.welcome-text{line-height:1.6}.aioseo-setup-wizard-container h2{color:#fff;line-height:1.4}.aioseo-setup-wizard-container a{color:#fff}.aioseo-setup-wizard-container svg.aioseo-book{width:20px;height:20px;margin:0 0 0 10px}.aioseo-setup-wizard-container .getting-started-video{padding-left:20px;margin-bottom:-60px;position:relative;height:0;padding-bottom:56.25%}.aioseo-setup-wizard-container .getting-started-video iframe{width:100%;height:100%;position:absolute;top:0;right:0}.aioseo-google-search-preview{padding:32px 30px;border:1px solid #e8e8eb}.aioseo-google-search-preview .domain{font-size:14px;line-height:1.3;color:#3c4043;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-google-search-preview .site-title{font-size:20px;line-height:1.3;color:#1a0dab;margin:3px 0}.aioseo-google-search-preview .meta-description{max-width:600px;font-size:14px;line-height:1.4;color:#52565a}.edit-post-sidebar .domain{font-size:13px}.edit-post-sidebar .site-title{font-size:16px}.edit-post-sidebar .meta-description{font-size:12px}.aioseo-modal-content .domain,.aioseo-modal-content .meta-description{font-size:14px}.aioseo-modal-content .site-title{font-size:20px}html:not([data-scroll="0"]) .aioseo-header{box-shadow:0 2px 5px rgba(0,0,0,.05);transition:box-shadow .6s}.aioseo-header{position:fixed;z-index:1051;top:0;left:0;right:0;background-color:#fff;height:72px;color:#141b38}.aioseo-header .mascot{width:35px;height:auto;margin-left:10px}.aioseo-header .aioseo-header-content{padding:0;display:flex;height:72px;align-items:center}.aioseo-header .aioseo-header-content svg.aioseo-logo{height:26px;margin-left:10px}.aioseo-header .aioseo-header-content .spacer{display:inline-flex;width:26.25px;height:0;border:1px solid #d0d1d7;transform:rotate(72.26deg)}.aioseo-header .aioseo-header-content .page-name{display:inline-flex;margin-right:10px;font-size:18px;font-weight:400;flex:1 0 auto}.aioseo-header .aioseo-header-content .header-actions{display:flex}.aioseo-header .aioseo-header-content .header-actions .round{position:relative;background-color:#f3f4f5;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:10px;cursor:pointer;transition:background-color .2s ease}.aioseo-header .aioseo-header-content .header-actions .round svg{width:20px;height:20px}.aioseo-header .aioseo-header-content .header-actions .round:hover{background-color:#e5e7e9}.aioseo-header .aioseo-header-content .header-actions .number{position:absolute;background-color:#df2a4a;width:16px;height:16px;font-weight:600;font-size:10px;color:#fff;top:-8px;right:50%;transform:translateX(50%);margin:0;-webkit-animation:bounce 2s 5;animation:bounce 2s 5}.aioseo-header .aioseo-header-content .header-actions .number:hover{background-color:#df2a4a}@-webkit-keyframes bounce{0%,25%,50%,75%,to{transform:translateX(50%) translateY(0)}40%{transform:translateX(50%) translateY(-8px)}60%{transform:translateX(50%) translateY(-4px)}}@keyframes bounce{0%,25%,50%,75%,to{transform:translateX(50%) translateY(0)}40%{transform:translateX(50%) translateY(-8px)}60%{transform:translateX(50%) translateY(-4px)}}body.modal-open{overflow:hidden}.aioseo-help{display:block;position:fixed;top:0;bottom:0;right:0;left:0;height:100%;width:100vw;background-color:#fff;color:#8c8f9a;opacity:0;max-height:100vh;overflow-y:auto;transition:opacity .3s ease-in 0s;z-index:-999}.aioseo-help.visible{opacity:1;z-index:100000}.aioseo-help .aioseo-help-header{background:#fff;width:100%;height:60px;position:fixed;z-index:1;top:0;right:0}.aioseo-help .aioseo-help-docs{margin-bottom:25px;display:none}.aioseo-help .aioseo-help-docs li{padding:0 4px 14px 0;margin:0}.aioseo-help .aioseo-help-docs .aioseo-help-docs-viewall{margin:10px 0 0}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs{display:none}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs.opened{display:block}.aioseo-help .aioseo-help-docs .icon .aioseo-description{width:20px;margin-top:0;position:relative;top:5px;right:-5px;color:#8c8f9a}.aioseo-help .help-content{background-color:#fff;width:100%;max-width:740px;margin:0 auto 50px;padding:0 20px;box-sizing:border-box;z-index:1}.aioseo-help .help-content .aioseo-help-category{border-top:1px solid #e8e8eb;margin:0}.aioseo-help .help-content .aioseo-help-category:last-child{border-bottom:1px solid #e8e8eb}.aioseo-help .help-content .aioseo-help-category header{display:block;position:relative;cursor:pointer;width:100%;height:68px}.aioseo-help .help-content .aioseo-help-category header .title{display:block;font-size:16px;color:#8c8f9a;font-weight:600;padding:23px 30px 23px 11px}.aioseo-help .help-content .aioseo-help-category .folder-open{position:absolute;top:24px;width:20px;height:20px;color:#8c8f9a}.aioseo-help .help-content .aioseo-help-category .dashicons-arrow-right-alt2{position:absolute;top:20px;left:0;transition:transform .3s ease-out}.aioseo-help .help-content .aioseo-help-category.opened .aioseo-help-docs{display:block}.aioseo-help .help-content .aioseo-help-category.opened .dashicons-arrow-right-alt2{transform:rotate(-90deg)}.aioseo-help .help-content #aioseo-help-search{position:relative;background-color:#fff;text-align:center;top:0;padding:74px 0 50px}.aioseo-help .help-content #aioseo-help-result .aioseo-help-docs{display:block}.aioseo-help .help-content #aioseo-help-footer{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;margin:50px 0 0}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer{display:block}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{box-sizing:border-box;max-width:325px;border:1px solid #8c8f9a;border-radius:6px;text-align:center}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{max-width:100%}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin-left:20px}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin:0 0 20px}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a{display:block;padding:25px;text-decoration:none;color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a h3{color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a span{font-size:16px;color:#005ae0;text-decoration:underline}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a:hover span{text-decoration:none}.aioseo-help .help-content #aioseo-help-footer .aioseo-description,.aioseo-help .help-content #aioseo-help-footer .aioseo-support{width:48px;margin-top:0;color:#8c8f9a}#aioseo-help-logo{position:fixed;width:132px;height:26px;top:20px;right:20px;z-index:2}#aioseo-help-close{position:fixed;width:20px;height:20px;top:30px;left:30px;cursor:pointer;opacity:.7;transition:all .05s;z-index:2}@media screen and (max-width:750px){#aioseo-help-close{top:20px;left:20px}}.aioseo-html-tags-editor .no-access{margin-bottom:20px}.aioseo-html-tags-editor .aioseo-description.tags-description{margin:0 0 20px}.aioseo-html-tags-editor .add-tags{display:flex;align-items:center;margin-bottom:20px}.aioseo-html-tags-editor .add-tags div{margin-left:10px}.aioseo-html-tags-editor .add-tags a{font-size:14px}.aioseo-html-tags-editor .add-tags a.no-underline{padding-right:10px}.aioseo-loading-spinner{width:35px;height:35px;position:absolute}.aioseo-loading-spinner .double-bounce1,.aioseo-loading-spinner .double-bounce2{width:100%;height:100%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;right:0;-webkit-animation:sk-bounce 1.3s ease-in-out infinite;animation:sk-bounce 1.3s ease-in-out infinite}.aioseo-loading-spinner.dark .double-bounce1,.aioseo-loading-spinner.dark .double-bounce2{background-color:#8c8f9a}.aioseo-loading-spinner .double-bounce2{-webkit-animation-delay:-.65s;animation-delay:-.65s}@-webkit-keyframes sk-bounce{0%,to{-webkit-transform:scale(0)}50%{-webkit-transform:scale(1)}}@keyframes sk-bounce{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}body.vue-build{margin:0}body.vue-build .aioseo-app{min-height:calc(100vh - 88px)}body.vue-build .aioseo-app .aioseo-main{padding-bottom:30px}body.aioseo-setup-wizard{margin:0;padding:0}body.aioseo-setup-wizard .aioseo-app{min-height:100vh;width:100%}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay{right:160px}body[class*=page_aioseo].folded .aioseo-header,body[class*=page_aioseo].folded .aioseo-notifications .overlay{right:36px}body[class*=page_aioseo] #wpcontent{padding:0;background-color:#f3f4f5}body[class*=page_aioseo] .update-nag{display:none}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 185px)}body[class*=page_aioseo].admin-bar.aioseo-has-bar .aioseo-app{min-height:calc(100vh - 225px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:32px}body[class*=page_aioseo] .aioseo-app{min-height:calc(100vh - 153px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-app{min-height:calc(100vh - 193px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:112px}@media screen and (max-width:782px){body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:132px}}@media screen and (max-width:960px){body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{right:36px}}@media screen and (max-width:782px){body[class*=page_aioseo] #wpbody-content{padding-bottom:20px}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 199px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:46px}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay,body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{right:0}}@media screen and (max-width:600px){body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{position:absolute;top:46px}}body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:128px}@media screen and (max-width:782px){body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:148px}}.aioseo-app{box-sizing:border-box;background-color:#f3f4f5}.aioseo-app .route-fade-enter-active,.aioseo-app .route-fade-leave-active{transition:all .2s}.aioseo-app .route-fade-enter,.aioseo-app .route-fade-leave-active{opacity:0}.aioseo-app .route-fade-enter{transform:translateX(-30px)}.aioseo-app .route-fade-leave-active{transform:translateX(30px)}.aioseo-app *,.aioseo-app :after,.aioseo-app :before{box-sizing:inherit}.aioseo-app * :not(.aioseo-button):not(.aioseo-input),.aioseo-app :after :not(.aioseo-button):not(.aioseo-input),.aioseo-app :before :not(.aioseo-button):not(.aioseo-input){line-height:1.4}.aioseo-app p{font-size:16px}.aioseo-app a:not(.aioseo-button){color:#005ae0}.aioseo-app a:not(.aioseo-button).text-white{color:#fff}.aioseo-app a:not(.aioseo-button).no-underline,.aioseo-app a:not(.aioseo-button):hover{text-decoration:none}.aioseo-app h2{font-size:32px;margin:0}.aioseo-app .aioseo-main{height:100%}.aioseo-app .aioseo-main>.aioseo-container{margin-top:88px}.aioseo-app .aioseo-main .save-changes{display:flex;justify-content:flex-end}.aioseo-app .d-flex{display:flex}.aioseo-app .aioseo-section-description{font-size:16px;color:#141b38;line-height:1.8;padding-bottom:30px}.aioseo-app .aioseo-description-text{font-size:14px;line-height:1.8;color:#141b38}.aioseo-app .aioseo-description-text.aioseo-error{color:#df2a4a}.aioseo-app .aioseo-description{font-size:14px;line-height:1.8;margin:8px 0 0;color:#141b38}.aioseo-app .aioseo-description.no-margin{margin:0}.aioseo-app .aioseo-description.aioseo-error{color:#df2a4a}.aioseo-app .max-recommended-count{color:#434960;text-align:left;margin-top:10px;font-size:14px}.aioseo-app .max-recommended-count strong.error{color:#df2a4a}.aioseo-app .popper{text-align:right;font-size:12px;padding:20px;background-color:#fff;border:none;border-radius:3px;box-shadow:0 3px 4.8px 0 rgba(32,71,102,.27);z-index:9999;max-width:350px;line-height:1.4}.aioseo-app .popper.action{padding:8px 12px;background-color:#141b38;color:#fff}.aioseo-app .popper.action .popper__arrow{border-top-color:#141b38}.aioseo-app .popper[x-placement^=bottom]{box-shadow:0 -2px 4.8px 0 rgba(32,71,102,.27)}.aioseo-app .popper .aioseo-description{margin:0}.aioseo-app .aioseo-row-highlight{-webkit-animation-name:color;animation-name:color;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-iteration-count:2;animation-iteration-count:2}@-webkit-keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}@keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}.aioseo-seo-site-score .aioseo-blur{display:flex;align-items:center}.aioseo-seo-site-score .aioseo-seo-site-score-cta{position:absolute;right:50%;top:50%;transform:translateX(50%) translateY(-50%);background-color:#fff;padding:24px 30px;border:1px solid #e8e8eb;box-shadow:0 2px 10px rgba(0,90,224,.2);color:#141b38;font-size:16px;font-weight:600;width:82%;max-width:500px;text-align:center}.aioseo-app .aioseo-upgrade-bar{height:40px;background-color:#00aa63;display:flex;align-items:center;justify-content:center;color:#fff;font-size:13px;padding:0 40px 0 14px}.aioseo-app .aioseo-upgrade-bar .upgrade-text{display:flex;align-items:center;flex:1;justify-content:center}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow{font-size:15px;text-decoration:none}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow:hover{text-decoration:none}.aioseo-app .aioseo-upgrade-bar strong{font-weight:600}.aioseo-app .aioseo-upgrade-bar svg.aioseo-logo-gear{width:20px;height:20px;min-width:20px;margin-left:14px}.aioseo-app .aioseo-upgrade-bar svg.aioseo-close{cursor:pointer;width:12px;height:12px}.aioseo-app .aioseo-upgrade-bar a{color:#fff;text-decoration:underline}.aioseo-app .aioseo-upgrade-bar a:hover{text-decoration:none}@media screen and (max-width:782px){.aioseo-app .aioseo-upgrade-bar{padding:0 10px;height:60px}}.field-description[data-v-2bfc1de2]{display:inline-block;margin-top:10px;font-size:14px}.aioseo-address-wrapper[data-v-4bc9bbe6]{display:flex;max-width:500px}.field-description[data-v-4bc9bbe6]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4bc9bbe6]{margin-top:8px}.field-description[data-v-a0a894b8]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-a0a894b8]{margin-top:8px}.field-description[data-v-4fb4e044]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4fb4e044]{margin-top:8px}.field-description[data-v-85733554]{display:inline-block;margin-top:10px;font-size:14px}.field-description[data-v-515336a2]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-515336a2]{margin-top:8px}.field-description[data-v-78337de7]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-78337de7]{margin-top:8px}.aioseo-general-settings .more-tooltip-text strong{color:#00aa63}.aioseo-general-settings .license-cta-box{border-radius:3px;background-color:#f2f7fd;padding:20px;max-width:630px;margin:10px 0 30px}.aioseo-general-settings .license-cta-box a{color:#00aa63}.aioseo-general-settings .license-cta-box div{font-weight:600}.aioseo-general-settings .license-cta-box span{font-size:14px;font-style:italic}.aioseo-general-settings .license-key{margin-top:10px;display:flex;max-width:560px}.aioseo-general-settings .license-key .aioseo-input{margin-left:10px}.aioseo-app .aioseo-tabs.internal{margin-bottom:0}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation{margin-top:5px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button{height:60px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 25px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-ripple-wave{display:none}.aioseo-app .aioseo-tabs.skinny .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 16px}.aioseo-app .md-tabs{display:flex;flex-direction:column}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation{margin-top:2px;background:transparent;display:flex;position:relative;justify-content:flex-start}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation.md-elevation-0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button{color:#141b38;max-width:264px;min-width:72px;height:60px;margin:0;border-radius:0;font-size:15px;font-weight:500;padding:0;display:inline-block;position:relative;overflow:hidden;outline:none;background:transparent;border:0;transition:.4s cubic-bezier(.4,0,.2,1);font-family:inherit;line-height:normal;text-decoration:none;vertical-align:top;white-space:nowrap}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:before{position:absolute;top:0;left:0;bottom:0;right:0;opacity:0;transition:.4s cubic-bezier(.4,0,.2,1);will-change:background-color,opacity;content:" "}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 18px;display:flex;justify-content:center;align-items:center;width:100%;height:100%;position:relative;overflow:hidden;-webkit-mask-image:radial-gradient(circle,#fff 100%,#000 0);mask-image:radial-gradient(circle,#fff 100%,#000 0)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-button-content{position:static;z-index:2}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]){cursor:pointer}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]):active:before,.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]):hover:before{background-color:currentColor;opacity:.12}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button.md-active{color:#005ae0}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button.md-active:focus{outline:none;box-shadow:none}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator{height:2px;background-color:#005ae0;bottom:-2px;position:absolute;right:0;transform:translateZ(0);will-change:left,right}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator.md-tabs-indicator-left{transition:right .3s cubic-bezier(.4,0,.2,1),left .35s cubic-bezier(.4,0,.2,1)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-tabs-indicator.md-tabs-indicator-right{transition:left .3s cubic-bezier(.4,0,.2,1),right .35s cubic-bezier(.4,0,.2,.1)}.aioseo-app .aioseo-tabs{display:flex;border-bottom:2px solid #e8e8eb;position:relative;margin-bottom:38px}.aioseo-app .aioseo-tabs .save-changes{position:absolute;left:0;bottom:10px}.aioseo-app .aioseo-tabs .tab-score{display:inline-flex;align-items:center;justify-content:flex-end;font-size:11px;font-weight:700;padding-right:12px}.aioseo-app .aioseo-tabs .tab-score.green{color:#00aa63}.aioseo-app .aioseo-tabs .tab-score.orange{color:#f18200}.aioseo-app .aioseo-tabs .tab-score.red{color:#df2a4a}.aioseo-app .aioseo-tabs .tab-score svg{display:inline;margin-left:7px}.aioseo-app .aioseo-mobile-tabs{position:relative;height:40px;margin-top:20px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.aioseo-app .aioseo-mobile-tabs .active-tab{color:#005ae0;padding-right:18px;min-height:100%;display:flex;align-items:center;cursor:pointer}.aioseo-app .aioseo-mobile-tabs .active-tab div{position:relative}.aioseo-app .aioseo-mobile-tabs .active-tab div span{height:2px;background-color:#005ae0;bottom:-7px;position:absolute;right:-18px;left:-18px;z-index:10}.aioseo-app .aioseo-mobile-tabs .active-tab svg.aioseo-caret{width:24px;height:24px;position:relative;top:6px;cursor:pointer;transition:transform .3s}.aioseo-app .aioseo-mobile-tabs .active-tab svg.aioseo-caret.rotated{transform:rotate(-180deg)}.aioseo-app .aioseo-mobile-tabs .tab-dropdown{border:1px solid #e8e8eb;border-top:none}.aioseo-app .aioseo-mobile-tabs .tab-links{background:#fff;position:relative;z-index:3;padding:8px;width:100%;max-width:300px}@media screen and (max-width:782px){.aioseo-app .aioseo-mobile-tabs .tab-links{max-width:100%}}.aioseo-app .aioseo-mobile-tabs .tab-links a{padding:10px;display:block;color:#141b38;text-decoration:none}.aioseo-app .aioseo-mobile-tabs .tab-links a:hover{color:#005ae0}.md-tooltip{background-color:#141b38!important;color:#fff!important;border-radius:2px;padding:6px 12px;font-size:14px}.md-tooltip:after{content:"";position:absolute;top:100%;right:50%;margin-right:-5px;border:5px solid transparent;border-top-color:#141b38}.modal-mask{position:fixed;z-index:9998;top:0;right:0;width:100%;height:100%;background-color:rgba(20,27,56,.3);display:table;transition:opacity .3s ease}@media screen and (max-width:520px){.modal-mask{display:block;top:46px}}.modal-mask .modal-wrapper{display:table-cell;vertical-align:middle}@media screen and (max-width:520px){.modal-mask .modal-wrapper{display:block;height:100%}}.modal-mask .modal-wrapper .modal-container{width:100%;max-width:750px;max-height:90vh;overflow-y:hidden;overflow-x:hidden;margin:0 auto;background-color:#fff;box-shadow:0 10px 30px rgba(0,0,0,.15);transition:all .3s ease}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container{width:100%;max-width:100%;max-height:calc(100vh - 46px);height:100%}}.modal-mask .modal-wrapper .modal-container .modal-header{color:#141b38;position:sticky;top:0;z-index:15;padding:0 40px 0 0;height:70px;font-size:20px;font-weight:700;line-height:1.4;border-bottom:1px solid #e8e8eb;background-color:#fff;display:flex;align-items:center}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container .modal-header{padding:15px 20px 0 0}}.modal-mask .modal-wrapper .modal-container .modal-header button.close{position:absolute;left:11px;top:11px;width:24px;height:24px;background-color:#fff;border:none;display:flex;align-items:center}.modal-mask .modal-wrapper .modal-container .modal-header button.close svg.aioseo-close{cursor:pointer;width:14px;height:14px}.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-post-general,.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-post-social{height:calc(90vh - 120px);max-height:600px;overflow-y:auto;overflow-x:hidden}.modal-mask .modal-wrapper .modal-container .modal-body .aioseo-modal-content.has-padding{padding:40px}@media screen and (max-width:520px){.modal-mask .modal-wrapper .modal-container .aioseo-modal-content,.modal-mask .modal-wrapper .modal-container .aioseo-modal-content>.component-wrapper,.modal-mask .modal-wrapper .modal-container .modal-body,.modal-mask .modal-wrapper .modal-container .modal-body>div{height:100%}.modal-mask .modal-wrapper .modal-container .aioseo-modal-content>.component-wrapper{display:flex;align-items:flex-end}.modal-mask .modal-wrapper .modal-container .aioseo-post-general,.modal-mask .modal-wrapper .modal-container .aioseo-post-social{height:100%!important;max-height:100%!important;padding:20px!important}.modal-mask .modal-wrapper .modal-container .aioseo-post-general .mobile-radio-buttons,.modal-mask .modal-wrapper .modal-container .aioseo-post-social .mobile-radio-buttons{margin-bottom:0}.modal-mask .modal-wrapper .modal-container .aioseo-add-template-tag{display:none}.modal-mask .modal-wrapper .modal-container .tab-facebook .aioseo-settings-row:last-of-type,.modal-mask .modal-wrapper .modal-container .tab-twitter .aioseo-settings-row:last-of-type{margin-bottom:64px!important;padding-bottom:32px!important}}.modal-enter,.modal-leave-active{opacity:0}.modal-enter .modal-container,.modal-leave-active .modal-container{transform:scale(1.1)}.aioseo-notification>div .body .title .date{font-weight:400;color:#8c8f9a;font-size:12px}.aioseo-notification-cards .aioseo-notification:last-child>div{border-bottom:none;margin-bottom:none}.aioseo-notification-cards .no-notifications{display:flex;align-items:center;flex-direction:column;padding-top:100px;font-size:16px;color:#8c8f9a}.aioseo-notification-cards .no-notifications img{width:30%;height:auto}.aioseo-notification-cards .no-notifications .great-scott{margin:20px 0 10px;font-size:24px;font-weight:600;color:#434960}.aioseo-notification-cards .no-notifications .no-new-notifications{margin-bottom:10px}.aioseo-notification{margin-bottom:20px}.aioseo-notification>div{display:flex;align-items:flex-start;padding-bottom:10px;border-bottom:1px solid #e8e8eb}.aioseo-notification>div .icon{margin-left:20px}.aioseo-notification>div .icon svg{width:20px;height:20px;color:#00aa63}.aioseo-notification>div .icon svg.warning{color:#f18200}.aioseo-notification>div .icon svg.info{color:#005ae0}.aioseo-notification>div .icon svg.success{color:#00aa63}.aioseo-notification>div .icon svg.error{color:#df2a4a}.aioseo-notification>div .body{margin-left:20px;flex:1}.aioseo-notification>div .body .title{font-size:16px;font-weight:600;color:#141b38;margin-bottom:7px;display:flex;align-items:center}.aioseo-notification>div .body .title div:first-child{flex:1;margin-left:5px;line-height:1.4}.aioseo-notification>div .body .notification-content{margin-bottom:10px;max-width:400px}.aioseo-notification>div .body .actions{flex-wrap:wrap;display:flex;align-items:center}.aioseo-notification>div .body .actions>*{margin-bottom:10px}.aioseo-notification>div .body .actions .aioseo-button{margin-left:20px}.aioseo-notification>div .body .actions .dismiss{color:#8c8f9a;font-size:14px}body.aioseo-show-notifications .aioseo-main{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-notifications a.dismiss{color:#8c8f9a;font-size:14px}.aioseo-notifications .notification-menu{height:100%;width:100%;max-width:570px;position:fixed;z-index:1053;top:0;left:0;bottom:0;background-color:#fff;overflow-x:hidden;transition:.5s}.aioseo-notifications .notification-menu .notification-header{height:70px;display:flex;align-items:center;padding:0 30px;color:#fff;background-color:#005ae0}.aioseo-notifications .notification-menu .notification-header .new-notifications{font-size:18px;font-weight:600}.aioseo-notifications .notification-menu .notification-header .dismissed-notifications{margin-right:25px;flex:1 1 auto}.aioseo-notifications .notification-menu .notification-header .dismissed-notifications a{font-size:14px;color:#fff}.aioseo-notifications .notification-menu .notification-header svg.aioseo-close{width:14px;height:14px;cursor:pointer}.aioseo-notifications .notification-menu .notification-header svg.aioseo-close:hover{color:#ccc}.aioseo-notifications .notification-menu .notification-cards{padding:30px;height:calc(100% - 192px);overflow:auto}.aioseo-notifications .notification-menu .notification-footer{height:90px;padding:30px;display:flex;align-items:center}.aioseo-notifications .notification-menu .notification-footer div.pagination{flex:1;display:flex;align-items:center}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number{font-size:13px;color:#141b38;background:#e8e8eb;height:30px;width:30px;display:flex;align-items:center;justify-content:center;border-radius:2px;margin-left:4px;cursor:pointer}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number:last-child{margin-left:0}.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number.active,.aioseo-notifications .notification-menu .notification-footer div.pagination .page-number:hover{color:#fff;background-color:#005ae0}.aioseo-notifications .overlay{position:fixed;z-index:1052;top:0;left:0;bottom:0;right:160px;background-color:#141b38;opacity:.5;transition:.5s}.aioseo-notifications .notifications-fade-enter-active,.aioseo-notifications .notifications-fade-leave-active{transition:opacity .5s}.aioseo-notifications .notifications-fade-enter,.aioseo-notifications .notifications-fade-leave-to{opacity:0}.aioseo-notifications .notifications-slide-enter-active,.aioseo-notifications .notifications-slide-leave-active{transition:all .5s ease-in-out}.aioseo-notifications .notifications-slide-enter,.aioseo-notifications .notifications-slide-leave-to{left:-570px}.aioseo-post-type-options-toggle{margin-top:20px}.aioseo-priority-score{max-width:350px}.aioseo-priority-score .header-row{font-size:14px}.aioseo-pro-badge{height:24px;border-radius:3px;background:#e8e8eb;color:#434960;font-size:14px;font-weight:600;display:inline-flex;padding:0 8px;align-items:center}.aioseo-score-settings{display:flex;align-items:center;padding-bottom:14px}.aioseo-score-settings svg{margin-left:7px}.aioseo-score-settings span{margin-left:12px}.aioseo-score-button{display:inline-block;padding:5px 8px;font-size:14px;font-weight:700;color:#a1a1a1;border:1px solid #a1a1a1;border-radius:3px}.aioseo-score-button.score-none,.aioseo-score-button.score-red{border-color:#df2a4a;color:#df2a4a!important}.aioseo-score-button.score-orange{border-color:#f18200;color:#f18200!important}.aioseo-score-button.score-green{border-color:#00aa63;color:#00aa63!important}.aioseo-score-button.classic-editor{background:#fff!important;display:inline-block!important;height:auto!important}.aioseo-score-button.classic-editor span{margin-left:0}.aioseo-seo-site-analysis-result{border:1px solid #dcdde1;margin-top:10px}.aioseo-seo-site-analysis-result .result-header{height:66px;padding:0 20px;display:flex;align-items:center}.aioseo-seo-site-analysis-result .result-header .result-icon{display:flex;align-items:center;margin-left:16px}.aioseo-seo-site-analysis-result .result-header .result-icon svg{width:24px;height:24px;color:#8c8f9a}.aioseo-seo-site-analysis-result .result-header .result-icon svg.passed{color:#00aa63}.aioseo-seo-site-analysis-result .result-header .result-icon svg.error{color:#df2a4a}.aioseo-seo-site-analysis-result .result-header .result-icon svg.warning{color:#005ae0}.aioseo-seo-site-analysis-result .result-header .result-content{font-size:16px;font-weight:600;flex:1}.aioseo-seo-site-analysis-result .result-header .result-toggle{width:30px;height:26px;border:1px solid #dcdde1;border-radius:3px;display:flex;align-items:center;justify-content:center;cursor:pointer}.aioseo-seo-site-analysis-result .result-header .result-toggle.active,.aioseo-seo-site-analysis-result .result-header .result-toggle:hover{background-color:#434960}.aioseo-seo-site-analysis-result .result-header .result-toggle.active svg,.aioseo-seo-site-analysis-result .result-header .result-toggle:hover svg{color:#fff}.aioseo-seo-site-analysis-result .result-header .result-toggle.active svg{transform:rotate(180deg)}.aioseo-seo-site-analysis-result .result-header .result-toggle svg{width:100%;max-width:20px;height:auto;color:#8c8f9a;transform:rotate(90deg);transition:transform .3s}.aioseo-seo-site-analysis-result .result-body{padding:0 60px 24px}.aioseo-seo-site-analysis-result .result-body .result-message{color:#434960;font-size:16px}.aioseo-seo-site-analysis-result .result-body .result-code-alt pre,.aioseo-seo-site-analysis-result .result-body .result-code pre{background:#f3f4f5;border-radius:3px;max-width:100%;padding:10px;overflow:auto}.aioseo-seo-site-analysis-result .result-body .result-code-alt pre code,.aioseo-seo-site-analysis-result .result-body .result-code pre code{padding:0;background:transparent}.aioseo-seo-site-analysis-result .result-body .result-code pre{white-space:pre-wrap}.aioseo-seo-site-analysis-result .result-body .result-action{margin-top:20px}.aioseo-seo-site-analysis-results .group-header{font-size:16px;font-weight:600}.aioseo-seo-site-analysis-results .group-header:not(:first-child){margin-top:30px}.aioseo-seo-site-analysis-results .group-keywords{display:flex;margin-top:5px;flex-wrap:wrap;align-items:center}.aioseo-seo-site-analysis-results .group-keywords .keyword{font-size:14px;color:#434960;font-weight:600;background:#f3f4f5;padding:9px 10px;border-radius:3px;margin:0 0 5px 10px}.aioseo-seo-site-analysis-results .group-keywords .keyword:first-child{font-size:20px}.aioseo-settings-row{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid #e8e8eb}.aioseo-settings-row.no-margin{margin-bottom:0}.aioseo-settings-row.small-padding{padding-bottom:5px}.aioseo-settings-row.medium-margin{margin-bottom:15px}.aioseo-settings-row.no-border{border:none}.aioseo-settings-row.no-side-margin{margin-right:0!important;margin-left:0!important}.aioseo-settings-row .settings-name{color:#141b38}.aioseo-settings-row .settings-name .name{font-weight:600;font-size:16px;display:flex;align-items:center}.aioseo-settings-row .settings-name .name.small-margin{margin-bottom:5px}.aioseo-settings-row .settings-name .name.align{line-height:40px}.aioseo-settings-row .settings-name .name.align-small{line-height:30px}.aioseo-settings-row .settings-name .name .aioseo-pro-badge{margin-right:10px}.aioseo-settings-row .settings-name .aioseo-description{margin-top:20px}.aioseo-settings-row .settings-content{font-size:16px}.aioseo-settings-row p.description{font-size:14px}.aioseo-separators{margin-top:-.5rem}.aioseo-separators .aioseo-col .separator{background-color:#f3f4f5;display:flex;align-items:center;justify-content:center;min-height:51px;font-weight:600;font-size:25px;border:1px solid #dcdde1;border-radius:3px;cursor:pointer}.aioseo-separators .aioseo-col .separator:hover{background-color:#e5e7e9}.aioseo-separators .aioseo-col .separator.active{background-color:#005ae0;border-color:#005ae0;color:#fff}.aioseo-separators .aioseo-col .separator.active:hover{background-color:#005ae0}.aioseo-separators .aioseo-col .show-more{height:100%;display:flex;align-items:center}.aioseo-separators .aioseo-col .show-more a{color:#8c8f9a}.aioseo-separators .aioseo-col .custom-separator{margin:20px 0;display:flex;align-items:center}.aioseo-separators .aioseo-col .custom-separator .aioseo-input{margin-right:10px;max-width:100px}.aioseo-sidebar-card .header{height:46px}.aioseo-sidebar-card .header:hover{cursor:pointer}.aioseo-sidebar-card .content{padding-bottom:8px!important}.aioseo-sidebar-card ul{margin-bottom:0}.aioseo-sidebar-card ul li{margin-bottom:16px;padding-right:25px}.aioseo-sidebar-card ul .description{margin:0}.aioseo-robots-meta .global-robots-settings{margin:0;padding-top:24px}.aioseo-robots-meta .global-robots-settings>.settings{padding:8px 0 16px}.aioseo-robots-meta .global-robots-settings-options{display:flex}.aioseo-robots-meta .global-robots-settings-options .max-snippet{margin-left:30px}.aioseo-robots-meta .global-robots-settings-options .max-snippet .aioseo-input{max-width:90px}.aioseo-robots-meta .global-robots-settings-options .max-video-preview{margin-left:30px}.aioseo-robots-meta .global-robots-settings-options .max-video-preview .aioseo-input{max-width:90px}.aioseo-robots-meta .global-robots-settings-options .max-image-preview .aioseo-select{min-width:155px}.aioseo-robots-meta .global-robots-settings-options>span{display:inline-block;margin-bottom:4px}@media screen and (max-width:782px){.aioseo-robots-meta .global-robots-settings-options{display:block}.aioseo-robots-meta .global-robots-settings-options .max-snippet,.aioseo-robots-meta .global-robots-settings-options .max-video-preview{margin-left:0;margin-bottom:20px}.aioseo-robots-meta .global-robots-settings-options>div .aioseo-input,.aioseo-robots-meta .global-robots-settings-options>div .aioseo-select{min-width:100%}}.edit-post-sidebar .global-robots-settings{padding-top:12px}.edit-post-sidebar .global-robots-settings>.settings{padding:4px 0 12px}.edit-post-sidebar .global-robots-settings>.settings label{font-size:16px}.edit-post-sidebar .global-robots-settings .robots-meta-title{padding-top:4px;display:inline-block}.edit-post-sidebar .global-robots-settings-options{flex-wrap:wrap}.edit-post-sidebar .max-snippet{margin-left:30px!important}.edit-post-sidebar .max-video-preview{margin-left:0!important}.edit-post-sidebar .max-image-preview{margin-top:20px!important}.aioseo-score-amount-wrapper{position:absolute;right:0;top:0;left:0;bottom:0;display:flex;align-items:center;justify-content:center;flex-direction:column;color:#141b38;margin:20px}.aioseo-score-amount-wrapper .aioseo-score-amount .score{font-size:64px;font-weight:600}.aioseo-score-amount-wrapper .aioseo-score-amount .total{font-size:18px;color:#8c8f9a;padding-right:3px}.aioseo-score-amount-wrapper .score-description{max-width:80%;text-align:center;font-size:17px;font-weight:600;line-height:1.1}.aioseo-score-amount-wrapper .score-analyzing{margin-top:20px;font-size:30px}.aioseo-site-score-analyze{position:relative;display:flex;align-items:center;justify-content:center;flex:1}.aioseo-site-score-analyze .analyze-errors{text-align:center;margin-bottom:1em}.aioseo-site-score-analyze .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-left:5em}.aioseo-site-score-analyze .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-analyze .aioseo-seo-site-score-description h2{line-height:1.4}.aioseo-site-score-analyze .aioseo-seo-site-score-description svg.aioseo-book{width:20px;height:20px;margin:0 0 0 10px;color:#005ae0}.aioseo-site-score-analyze .aioseo-seo-site-score-description>div{font-size:16px;color:#141b38;margin-bottom:10px}.aioseo-site-score-analyze .aioseo-seo-site-score-description .links{margin-top:30px;font-size:14px;font-weight:600}.aioseo-site-score-analyze .aioseo-seo-site-score-description .links .no-underline{padding-right:5px}.aioseo-site-score-competitor{position:relative;display:flex;align-items:center;justify-content:center;flex-direction:column}.aioseo-site-score-competitor .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-left:1em}.aioseo-site-score-competitor .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations{margin:20px 0}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links){display:flex;align-items:center;font-size:14px;color:#141b38;font-weight:600;margin-bottom:10px}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round{position:relative;border-radius:50%;width:24px;min-width:24px;max-width:24px;height:24px;display:flex;align-items:center;justify-content:center;margin-left:10px;font-size:12px;color:#fff;font-weight:600}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.red{background-color:#df2a4a}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.blue{background-color:#005ae0}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.orange{background-color:#f18200}.aioseo-site-score-competitor .aioseo-seo-site-score-recommendations>div:not(.links) .round.green{background-color:#00aa63}.aioseo-site-score-competitor .refresh-results .aioseo-refresh{width:14px;height:14px;margin-left:10px}.aioseo-site-score-competitor .mobile-snapshot{margin-top:60px;max-width:250px}.aioseo-site-score-competitor .mobile-snapshot div{font-weight:600;font-size:16px;margin-bottom:10px}.aioseo-site-score-competitor .mobile-snapshot img{width:100%;height:auto}.aioseo-site-score-dashboard{position:relative;display:flex;align-items:center;justify-content:center}.aioseo-site-score-dashboard .analyze-errors{text-align:center;margin-bottom:1em}.aioseo-site-score-dashboard .aioseo-seo-site-score-score{position:relative;min-width:175px;max-width:217px;margin-left:1em}.aioseo-site-score-dashboard .aioseo-seo-site-score-score svg{width:100%;height:auto}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links){display:flex;align-items:center;font-size:14px;color:#141b38;font-weight:600;margin-bottom:10px}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round{position:relative;border-radius:50%;width:24px;min-width:24px;max-width:24px;height:24px;display:flex;align-items:center;justify-content:center;margin-left:10px;font-size:12px;color:#fff;font-weight:600}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.red{background-color:#df2a4a}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.blue{background-color:#005ae0}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.orange{background-color:#f18200}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations>div:not(.links) .round.green{background-color:#00aa63}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations .links{margin-top:30px;font-size:14px;font-weight:600}.aioseo-site-score-dashboard .aioseo-seo-site-score-recommendations .links .no-underline{padding-right:5px}.aioseo-social-profiles .same-username .use-same{padding:30px;background:#f9f9fa}.aioseo-social-profiles .same-username .use-same .aioseo-checkbox{font-size:16px}.aioseo-social-profiles .aioseo-social-profile-list,.aioseo-social-profiles .same-username .use-same .aioseo-settings-row,.aioseo-social-profiles .same-username .use-same .profiles{margin-top:20px}.aioseo-social-profiles .aioseo-social-profile-list .social-profile{margin-bottom:0;padding-bottom:0;border-bottom:none}.aioseo-social-profiles .aioseo-social-profile-list .social-profile .profile-error{margin-top:10px}.aioseo-social-profiles .aioseo-social-profile-list .social-profile .name{margin-bottom:0}.aioseo-social-profiles .aioseo-social-profile-list .social-profile img{height:16px;width:auto;margin-left:10px}.aioseo-tooltip{margin-right:14px;display:inline-flex}.aioseo-tooltip,.aioseo-twitter-preview{align-items:center;justify-content:center}.aioseo-twitter-preview{background-color:#f0f2f5;padding:30px;display:flex}.aioseo-twitter-preview .twitter-post{width:100%;max-width:500px;border-radius:5px;border:1px solid #e1e8ed;background-color:#fff}.aioseo-twitter-preview .twitter-post .twitter-header{height:65px;padding:0 18px;display:flex;align-items:center}.aioseo-twitter-preview .twitter-post .twitter-header .profile-photo{overflow:hidden;width:40px;height:40px;border:1px solid #e8e8eb;border-radius:50%}.aioseo-twitter-preview .twitter-post .twitter-header .profile-photo img{height:100%;width:100%}.aioseo-twitter-preview .twitter-post .twitter-header .poster{margin-right:10px;flex:1 0 auto}.aioseo-twitter-preview .twitter-post .twitter-header .poster .poster-name{font-size:15px;color:#1c2022;font-weight:600}.aioseo-twitter-preview .twitter-post .twitter-header .poster .poster-username{color:#697882;font-weight:500;font-size:13px}.aioseo-twitter-preview .twitter-post .twitter-container{padding:0 20px 20px}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content{flex-direction:row}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content .twitter-image-preview{display:flex;align-items:center;justify-content:center;background-color:#e1e8ed;min-width:125px;min-height:125px;background-size:cover;background-repeat:no-repeat;background-position:50%}.aioseo-twitter-preview .twitter-post .twitter-container.summary .twitter-content .twitter-image-preview svg.aioseo-book{width:50px;height:50px;color:#8999a5}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content{border-radius:10px;overflow:hidden;display:flex;flex-direction:column;border:1px solid #e1e8ed}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content img{width:100%;height:auto}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description{padding:18px;color:#1c2022}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-domain{font-size:14px;color:#8899a6;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-title{font-size:15px;font-weight:600}.aioseo-twitter-preview .twitter-post .twitter-container .twitter-content .twitter-site-description .site-description{font-size:14px;margin:5px 0}.aioseo-col .reverse{flex-direction:column-reverse}.aioseo-col.col-xs,.aioseo-col.col-xs-1,.aioseo-col.col-xs-2,.aioseo-col.col-xs-3,.aioseo-col.col-xs-4,.aioseo-col.col-xs-5,.aioseo-col.col-xs-6,.aioseo-col.col-xs-7,.aioseo-col.col-xs-8,.aioseo-col.col-xs-9,.aioseo-col.col-xs-10,.aioseo-col.col-xs-11,.aioseo-col.col-xs-12,.aioseo-col.col-xs-offset-0,.aioseo-col.col-xs-offset-1,.aioseo-col.col-xs-offset-2,.aioseo-col.col-xs-offset-3,.aioseo-col.col-xs-offset-4,.aioseo-col.col-xs-offset-5,.aioseo-col.col-xs-offset-6,.aioseo-col.col-xs-offset-7,.aioseo-col.col-xs-offset-8,.aioseo-col.col-xs-offset-9,.aioseo-col.col-xs-offset-10,.aioseo-col.col-xs-offset-11,.aioseo-col.col-xs-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-xs{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-xs-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-xs-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-xs-3{flex-basis:25%;max-width:25%}.aioseo-col.col-xs-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-xs-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-xs-6{flex-basis:50%;max-width:50%}.aioseo-col.col-xs-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-xs-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-xs-9{flex-basis:75%;max-width:75%}.aioseo-col.col-xs-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-xs-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-xs-12{flex-basis:100%;max-width:100%}.aioseo-col.col-xs-offset-0{margin-right:0}.aioseo-col.col-xs-offset-1{margin-right:8.33333333%}.aioseo-col.col-xs-offset-2{margin-right:16.66666667%}.aioseo-col.col-xs-offset-3{margin-right:25%}.aioseo-col.col-xs-offset-4{margin-right:33.33333333%}.aioseo-col.col-xs-offset-5{margin-right:41.66666667%}.aioseo-col.col-xs-offset-6{margin-right:50%}.aioseo-col.col-xs-offset-7{margin-right:58.33333333%}.aioseo-col.col-xs-offset-8{margin-right:66.66666667%}.aioseo-col.col-xs-offset-9{margin-right:75%}.aioseo-col.col-xs-offset-10{margin-right:83.33333333%}.aioseo-col.col-xs-offset-11{margin-right:91.66666667%}.aioseo-col.first-xs{order:-1}.aioseo-col.last-xs{order:1}.aioseo-col.text-xs-left{text-align:right!important;justify-content:flex-start}.aioseo-col.text-xs-center{text-align:center!important;justify-content:center}.aioseo-col.text-xs-right{text-align:left!important;justify-content:flex-end}.aioseo-col.p-0{padding:0!important}.aioseo-col.pt-0,.aioseo-col.py-0{padding-top:0!important}.aioseo-col.pr-0,.aioseo-col.px-0{padding-left:0!important}.aioseo-col.pb-0,.aioseo-col.py-0{padding-bottom:0!important}.aioseo-col.pl-0,.aioseo-col.px-0{padding-right:0!important}.aioseo-col.p-1{padding:.25rem!important}.aioseo-col.pt-1,.aioseo-col.py-1{padding-top:.25rem!important}.aioseo-col.pr-1,.aioseo-col.px-1{padding-left:.25rem!important}.aioseo-col.pb-1,.aioseo-col.py-1{padding-bottom:.25rem!important}.aioseo-col.pl-1,.aioseo-col.px-1{padding-right:.25rem!important}.aioseo-col.p-2{padding:.5rem!important}.aioseo-col.pt-2,.aioseo-col.py-2{padding-top:.5rem!important}.aioseo-col.pr-2,.aioseo-col.px-2{padding-left:.5rem!important}.aioseo-col.pb-2,.aioseo-col.py-2{padding-bottom:.5rem!important}.aioseo-col.pl-2,.aioseo-col.px-2{padding-right:.5rem!important}.aioseo-col.p-3{padding:1rem!important}.aioseo-col.pt-3,.aioseo-col.py-3{padding-top:1rem!important}.aioseo-col.pr-3,.aioseo-col.px-3{padding-left:1rem!important}.aioseo-col.pb-3,.aioseo-col.py-3{padding-bottom:1rem!important}.aioseo-col.pl-3,.aioseo-col.px-3{padding-right:1rem!important}.aioseo-col.p-4{padding:1.5rem!important}.aioseo-col.pt-4,.aioseo-col.py-4{padding-top:1.5rem!important}.aioseo-col.pr-4,.aioseo-col.px-4{padding-left:1.5rem!important}.aioseo-col.pb-4,.aioseo-col.py-4{padding-bottom:1.5rem!important}.aioseo-col.pl-4,.aioseo-col.px-4{padding-right:1.5rem!important}.aioseo-col.p-5{padding:3rem!important}.aioseo-col.pt-5,.aioseo-col.py-5{padding-top:3rem!important}.aioseo-col.pr-5,.aioseo-col.px-5{padding-left:3rem!important}.aioseo-col.pb-5,.aioseo-col.py-5{padding-bottom:3rem!important}.aioseo-col.pl-5,.aioseo-col.px-5{padding-right:3rem!important}@media only screen and (min-width:782px){.aioseo-col.col-sm,.aioseo-col.col-sm-1,.aioseo-col.col-sm-2,.aioseo-col.col-sm-3,.aioseo-col.col-sm-4,.aioseo-col.col-sm-5,.aioseo-col.col-sm-6,.aioseo-col.col-sm-7,.aioseo-col.col-sm-8,.aioseo-col.col-sm-9,.aioseo-col.col-sm-10,.aioseo-col.col-sm-11,.aioseo-col.col-sm-12,.aioseo-col.col-sm-offset-0,.aioseo-col.col-sm-offset-1,.aioseo-col.col-sm-offset-2,.aioseo-col.col-sm-offset-3,.aioseo-col.col-sm-offset-4,.aioseo-col.col-sm-offset-5,.aioseo-col.col-sm-offset-6,.aioseo-col.col-sm-offset-7,.aioseo-col.col-sm-offset-8,.aioseo-col.col-sm-offset-9,.aioseo-col.col-sm-offset-10,.aioseo-col.col-sm-offset-11,.aioseo-col.col-sm-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-sm{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-sm-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-sm-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-sm-3{flex-basis:25%;max-width:25%}.aioseo-col.col-sm-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-sm-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-sm-6{flex-basis:50%;max-width:50%}.aioseo-col.col-sm-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-sm-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-sm-9{flex-basis:75%;max-width:75%}.aioseo-col.col-sm-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-sm-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-sm-12{flex-basis:100%;max-width:100%}.aioseo-col.col-sm-offset-0{margin-right:0}.aioseo-col.col-sm-offset-1{margin-right:8.33333333%}.aioseo-col.col-sm-offset-2{margin-right:16.66666667%}.aioseo-col.col-sm-offset-3{margin-right:25%}.aioseo-col.col-sm-offset-4{margin-right:33.33333333%}.aioseo-col.col-sm-offset-5{margin-right:41.66666667%}.aioseo-col.col-sm-offset-6{margin-right:50%}.aioseo-col.col-sm-offset-7{margin-right:58.33333333%}.aioseo-col.col-sm-offset-8{margin-right:66.66666667%}.aioseo-col.col-sm-offset-9{margin-right:75%}.aioseo-col.col-sm-offset-10{margin-right:83.33333333%}.aioseo-col.col-sm-offset-11{margin-right:91.66666667%}.aioseo-col.first-sm{order:-1}.aioseo-col.last-sm{order:1}.aioseo-col.text-sm-left{text-align:right!important;justify-content:flex-start}.aioseo-col.text-sm-center{text-align:center!important;justify-content:center}.aioseo-col.text-sm-right{text-align:left!important;justify-content:flex-end}}@media only screen and (min-width:912px){.aioseo-col.col-md,.aioseo-col.col-md-1,.aioseo-col.col-md-2,.aioseo-col.col-md-3,.aioseo-col.col-md-4,.aioseo-col.col-md-5,.aioseo-col.col-md-6,.aioseo-col.col-md-7,.aioseo-col.col-md-8,.aioseo-col.col-md-9,.aioseo-col.col-md-10,.aioseo-col.col-md-11,.aioseo-col.col-md-12,.aioseo-col.col-md-offset-0,.aioseo-col.col-md-offset-1,.aioseo-col.col-md-offset-2,.aioseo-col.col-md-offset-3,.aioseo-col.col-md-offset-4,.aioseo-col.col-md-offset-5,.aioseo-col.col-md-offset-6,.aioseo-col.col-md-offset-7,.aioseo-col.col-md-offset-8,.aioseo-col.col-md-offset-9,.aioseo-col.col-md-offset-10,.aioseo-col.col-md-offset-11,.aioseo-col.col-md-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-md{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-md-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-md-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-md-3{flex-basis:25%;max-width:25%}.aioseo-col.col-md-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-md-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-md-6{flex-basis:50%;max-width:50%}.aioseo-col.col-md-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-md-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-md-9{flex-basis:75%;max-width:75%}.aioseo-col.col-md-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-md-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-md-12{flex-basis:100%;max-width:100%}.aioseo-col.col-md-offset-0{margin-right:0}.aioseo-col.col-md-offset-1{margin-right:8.33333333%}.aioseo-col.col-md-offset-2{margin-right:16.66666667%}.aioseo-col.col-md-offset-3{margin-right:25%}.aioseo-col.col-md-offset-4{margin-right:33.33333333%}.aioseo-col.col-md-offset-5{margin-right:41.66666667%}.aioseo-col.col-md-offset-6{margin-right:50%}.aioseo-col.col-md-offset-7{margin-right:58.33333333%}.aioseo-col.col-md-offset-8{margin-right:66.66666667%}.aioseo-col.col-md-offset-9{margin-right:75%}.aioseo-col.col-md-offset-10{margin-right:83.33333333%}.aioseo-col.col-md-offset-11{margin-right:91.66666667%}.aioseo-col.first-md{order:-1}.aioseo-col.last-md{order:1}.aioseo-col.text-md-left{text-align:right!important;justify-content:flex-start}.aioseo-col.text-md-center{text-align:center!important;justify-content:center}.aioseo-col.text-md-right{text-align:left!important;justify-content:flex-end}}@media only screen and (min-width:1042px){.aioseo-col.col-lg,.aioseo-col.col-lg-1,.aioseo-col.col-lg-2,.aioseo-col.col-lg-3,.aioseo-col.col-lg-4,.aioseo-col.col-lg-5,.aioseo-col.col-lg-6,.aioseo-col.col-lg-7,.aioseo-col.col-lg-8,.aioseo-col.col-lg-9,.aioseo-col.col-lg-10,.aioseo-col.col-lg-11,.aioseo-col.col-lg-12,.aioseo-col.col-lg-offset-0,.aioseo-col.col-lg-offset-1,.aioseo-col.col-lg-offset-2,.aioseo-col.col-lg-offset-3,.aioseo-col.col-lg-offset-4,.aioseo-col.col-lg-offset-5,.aioseo-col.col-lg-offset-6,.aioseo-col.col-lg-offset-7,.aioseo-col.col-lg-offset-8,.aioseo-col.col-lg-offset-9,.aioseo-col.col-lg-offset-10,.aioseo-col.col-lg-offset-11,.aioseo-col.col-lg-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-lg{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-lg-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-lg-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-lg-3{flex-basis:25%;max-width:25%}.aioseo-col.col-lg-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-lg-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-lg-6{flex-basis:50%;max-width:50%}.aioseo-col.col-lg-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-lg-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-lg-9{flex-basis:75%;max-width:75%}.aioseo-col.col-lg-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-lg-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-lg-12{flex-basis:100%;max-width:100%}.aioseo-col.col-lg-offset-0{margin-right:0}.aioseo-col.col-lg-offset-1{margin-right:8.33333333%}.aioseo-col.col-lg-offset-2{margin-right:16.66666667%}.aioseo-col.col-lg-offset-3{margin-right:25%}.aioseo-col.col-lg-offset-4{margin-right:33.33333333%}.aioseo-col.col-lg-offset-5{margin-right:41.66666667%}.aioseo-col.col-lg-offset-6{margin-right:50%}.aioseo-col.col-lg-offset-7{margin-right:58.33333333%}.aioseo-col.col-lg-offset-8{margin-right:66.66666667%}.aioseo-col.col-lg-offset-9{margin-right:75%}.aioseo-col.col-lg-offset-10{margin-right:83.33333333%}.aioseo-col.col-lg-offset-11{margin-right:91.66666667%}.aioseo-col.first-lg{order:-1}.aioseo-col.last-lg{order:1}.aioseo-col.text-lg-left{text-align:right!important;justify-content:flex-start}.aioseo-col.text-lg-center{text-align:center!important;justify-content:center}.aioseo-col.text-lg-right{text-align:left!important;justify-content:flex-end}}@media only screen and (min-width:1140px){.aioseo-col.col-xl,.aioseo-col.col-xl-1,.aioseo-col.col-xl-2,.aioseo-col.col-xl-3,.aioseo-col.col-xl-4,.aioseo-col.col-xl-5,.aioseo-col.col-xl-6,.aioseo-col.col-xl-7,.aioseo-col.col-xl-8,.aioseo-col.col-xl-9,.aioseo-col.col-xl-10,.aioseo-col.col-xl-11,.aioseo-col.col-xl-12,.aioseo-col.col-xl-offset-0,.aioseo-col.col-xl-offset-1,.aioseo-col.col-xl-offset-2,.aioseo-col.col-xl-offset-3,.aioseo-col.col-xl-offset-4,.aioseo-col.col-xl-offset-5,.aioseo-col.col-xl-offset-6,.aioseo-col.col-xl-offset-7,.aioseo-col.col-xl-offset-8,.aioseo-col.col-xl-offset-9,.aioseo-col.col-xl-offset-10,.aioseo-col.col-xl-offset-11,.aioseo-col.col-xl-offset-12{box-sizing:border-box;flex:0 0 auto;padding:.5rem}.aioseo-col.col-xl{flex-grow:1;flex-basis:0;max-width:100%}.aioseo-col.col-xl-1{flex-basis:8.33333333%;max-width:8.33333333%}.aioseo-col.col-xl-2{flex-basis:16.66666667%;max-width:16.66666667%}.aioseo-col.col-xl-3{flex-basis:25%;max-width:25%}.aioseo-col.col-xl-4{flex-basis:33.33333333%;max-width:33.33333333%}.aioseo-col.col-xl-5{flex-basis:41.66666667%;max-width:41.66666667%}.aioseo-col.col-xl-6{flex-basis:50%;max-width:50%}.aioseo-col.col-xl-7{flex-basis:58.33333333%;max-width:58.33333333%}.aioseo-col.col-xl-8{flex-basis:66.66666667%;max-width:66.66666667%}.aioseo-col.col-xl-9{flex-basis:75%;max-width:75%}.aioseo-col.col-xl-10{flex-basis:83.33333333%;max-width:83.33333333%}.aioseo-col.col-xl-11{flex-basis:91.66666667%;max-width:91.66666667%}.aioseo-col.col-xl-12{flex-basis:100%;max-width:100%}.aioseo-col.col-xl-offset-0{margin-right:0}.aioseo-col.col-xl-offset-1{margin-right:8.33333333%}.aioseo-col.col-xl-offset-2{margin-right:16.66666667%}.aioseo-col.col-xl-offset-3{margin-right:25%}.aioseo-col.col-xl-offset-4{margin-right:33.33333333%}.aioseo-col.col-xl-offset-5{margin-right:41.66666667%}.aioseo-col.col-xl-offset-6{margin-right:50%}.aioseo-col.col-xl-offset-7{margin-right:58.33333333%}.aioseo-col.col-xl-offset-8{margin-right:66.66666667%}.aioseo-col.col-xl-offset-9{margin-right:75%}.aioseo-col.col-xl-offset-10{margin-right:83.33333333%}.aioseo-col.col-xl-offset-11{margin-right:91.66666667%}.aioseo-col.first-xl{order:-1}.aioseo-col.last-xl{order:1}.aioseo-col.text-xl-left{text-align:right!important;justify-content:flex-start}.aioseo-col.text-xl-center{text-align:center!important;justify-content:center}.aioseo-col.text-xl-right{text-align:left!important;justify-content:flex-end}}.aioseo-container,.aioseo-container-fluid{margin-left:auto;margin-right:auto}.aioseo-container{padding:0 20px}.aioseo-container-fluid.hero,.aioseo-container.hero{min-height:100vh;display:flex;justify-content:center;align-items:center}.aioseo-container-fluid{padding-left:2rem;padding-right:2rem}@media only screen and (min-width:782px){.aioseo-container{padding:0 30px}}@media only screen and (min-width:1042px){.aioseo-container{max-width:80rem}.aioseo-container.full-width{max-width:100%}.aioseo-container.small{max-width:810px}}.aioseo-masonry{-moz-column-count:0;column-count:0;-moz-column-gap:20px;column-gap:20px;counter-reset:brick-counter}.aioseo-masonry>*{box-sizing:border-box;-moz-column-break-inside:avoid;break-inside:avoid;counter-increment:brick-counter;margin-bottom:20px}@media only screen and (min-width:782px){.aioseo-masonry{-moz-column-count:1;column-count:1}}@media only screen and (min-width:912px){.aioseo-masonry{-moz-column-count:2;column-count:2}}@media only screen and (min-width:1042px){.aioseo-masonry{-moz-column-count:3;column-count:3}}.aioseo-row{box-sizing:border-box;display:flex;flex:0 1 auto;flex-direction:row;flex-wrap:wrap;margin-left:-.5rem;margin-right:-.5rem}.aioseo-row.reverse{flex-direction:row-reverse}.aioseo-row.start-xs{justify-content:flex-start;text-align:start}.aioseo-row.center-xs{justify-content:center;text-align:center}.aioseo-row.end-xs{justify-content:flex-end;text-align:end}.aioseo-row.top-xs{align-items:flex-start}.aioseo-row.middle-xs{align-items:center}.aioseo-row.bottom-xs{align-items:flex-end}.aioseo-row.around-xs{justify-content:space-around}.aioseo-row.between-xs{justify-content:space-between}@media only screen and (min-width:782px){.aioseo-row.start-sm{justify-content:flex-start;text-align:start}.aioseo-row.center-sm{justify-content:center;text-align:center}.aioseo-row.end-sm{justify-content:flex-end;text-align:end}.aioseo-row.top-sm{align-items:flex-start}.aioseo-row.middle-sm{align-items:center}.aioseo-row.bottom-sm{align-items:flex-end}.aioseo-row.around-sm{justify-content:space-around}.aioseo-row.between-sm{justify-content:space-between}}@media only screen and (min-width:912px){.aioseo-row.start-md{justify-content:flex-start;text-align:start}.aioseo-row.center-md{justify-content:center;text-align:center}.aioseo-row.end-md{justify-content:flex-end;text-align:end}.aioseo-row.top-md{align-items:flex-start}.aioseo-row.middle-md{align-items:center}.aioseo-row.bottom-md{align-items:flex-end}.aioseo-row.around-md{justify-content:space-around}.aioseo-row.between-md{justify-content:space-between}}@media only screen and (min-width:1042px){.aioseo-row.start-lg{justify-content:flex-start;text-align:start}.aioseo-row.center-lg{justify-content:center;text-align:center}.aioseo-row.end-lg{justify-content:flex-end;text-align:end}.aioseo-row.top-lg{align-items:flex-start}.aioseo-row.middle-lg{align-items:center}.aioseo-row.bottom-lg{align-items:flex-end}.aioseo-row.around-lg{justify-content:space-around}.aioseo-row.between-lg{justify-content:space-between}}.aioseo-seo-site-score__circle{animation:aioseo-seo-site-score-fill 1s reverse;transform:rotate(180deg);transform-origin:center;stroke:#00aa63}.aioseo-seo-site-score__circle.fast{-webkit-animation-duration:.5s;animation-duration:.5s;stroke:#df2a4a}.aioseo-seo-site-score__circle.medium{-webkit-animation-duration:.75s;animation-duration:.75s;stroke:#f18200}.aioseo-seo-site-score__background{stroke:#e8e8eb}@-webkit-keyframes aioseo-seo-site-score-fill{to{stroke-dasharray:0 100}}@keyframes aioseo-seo-site-score-fill{to{stroke-dasharray:0 100}}.aioseo-seo-site-score-svg-loading{-webkit-animation:aioseo-seo-site-score-svg-animation 2s linear infinite;animation:aioseo-seo-site-score-svg-animation 2s linear infinite}.aioseo-seo-site-score-loading__circle{-webkit-animation:aioseo-seo-site-score-fill-loading 2s ease-in-out infinite both;animation:aioseo-seo-site-score-fill-loading 2s ease-in-out infinite both;transform:rotate(180deg);transform-origin:center;stroke:#005ae0}@-webkit-keyframes aioseo-seo-site-score-svg-animation{0%{transform:rotate(0deg)}to{transform:rotate(-1turn)}}@keyframes aioseo-seo-site-score-svg-animation{0%{transform:rotate(0deg)}to{transform:rotate(-1turn)}}@-webkit-keyframes aioseo-seo-site-score-fill-loading{0%,25%{stroke-dashoffset:90;transform:rotate(0)}50%,75%{stroke-dashoffset:10;transform:rotate(-45deg)}to{stroke-dashoffset:90;transform:rotate(-1turn)}}@keyframes aioseo-seo-site-score-fill-loading{0%,25%{stroke-dashoffset:90;transform:rotate(0)}50%,75%{stroke-dashoffset:10;transform:rotate(-45deg)}to{stroke-dashoffset:90;transform:rotate(-1turn)}}.aioseo-table-column{display:flex;flex-direction:column;flex-basis:100%;flex:1;padding:5px;justify-content:center}.aioseo-table-row{display:flex;flex-direction:row;flex-wrap:wrap;width:100%}.aioseo-wizard-body{background-color:#fff;max-width:900px;box-shadow:0 2px 5px rgba(0,0,0,.05)}.aioseo-wizard-body .body-content{padding:80px 140px}@media screen and (max-width:782px){.aioseo-wizard-body .body-content{padding:40px}}.aioseo-wizard-body .body-content .header{line-height:1.4}.aioseo-wizard-body .body-footer{border-top:1px solid #e8e8eb;padding:30px;display:flex;align-items:center}.aioseo-wizard-body .body-footer>*{margin-left:10px}.aioseo-wizard-body .body-footer>:last-child{margin-left:0}.aioseo-wizard-body .body-footer .spacer{flex:1 0 auto}.aioseo-wizard-close-and-exit{margin:96px 0;min-height:96px;text-align:center;font-size:14px}.aioseo-wizard-close-and-exit a{color:#8c8f9a!important}.aioseo-wizard-container{margin:40px auto;max-width:900px}@media screen and (max-width:782px){.aioseo-wizard-container{margin:0 20px}}.aioseo-wizard-header{display:flex;align-items:center;justify-content:center;flex-direction:column}.aioseo-wizard-header svg.aioseo-logo{width:100%;max-width:140px;height:auto;margin:60px 0 40px 10px}.aioseo-wizard-progress{display:flex;align-items:center;justify-content:center}@media screen and (max-width:782px){.aioseo-wizard-progress{display:none}}.aioseo-wizard-progress .circle{background-color:#dcdde1;width:16px;height:16px;border-radius:50%}.aioseo-wizard-progress .circle.active{background-color:#005ae0}.aioseo-wizard-progress .spacer{width:59px;border:1px solid #dcdde1;margin:0 12px}.aioseo-wizard-progress .spacer.active{border-color:#005ae0}.aioseo-wizard-steps{color:#8c8f9a;font-size:14px;margin-bottom:20px}.aioseo-localseo-info .aioseo-input,.aioseo-localseo-info .aioseo-multiselect,.aioseo-localseo-info .aioseo-select{max-width:480px}.aioseo-localseo-info .field-description{font-size:14px}.aioseo-localseo-info .info-businessaddress-row .columns{display:flex;flex:0 1 auto;flex-direction:row;flex-wrap:wrap}.aioseo-localseo-opening .field-description{display:inline-block;margin:10px 0;font-size:14px}.aioseo-localseo-opening .field-description.mt-8{margin-top:8px}.aioseo-localseo-opening .aioseo-input,.aioseo-localseo-opening .aioseo-multiselect,.aioseo-localseo-opening .aioseo-select{max-width:480px}.aioseo-localseo-opening .aioseo-col-flex{display:flex;align-items:center;padding:12px 0;border-bottom:1px solid #e8e8eb}.aioseo-localseo-opening .aioseo-col-flex:first-of-type{padding-top:0}.aioseo-localseo-opening .aioseo-col-flex:last-of-type{padding-bottom:0;border:none}.aioseo-localseo-opening .aioseo-col-flex .aioseo-col-day{flex:1}.aioseo-localseo-opening .aioseo-col-flex .aioseo-col-alwaysopen,.aioseo-localseo-opening .aioseo-col-flex .aioseo-col-hours{flex:2}.aioseo-localseo-opening .aioseo-col-flex span.separator{margin:0 5px}.aioseo-localseo-opening .aioseo-col-flex .aioseo-select{display:inline-block;max-width:120px;margin-bottom:5px}.aioseo-localseo-opening .aioseo-col-flex .multiselect--disabled .multiselect__single,.aioseo-localseo-opening .aioseo-col-flex .multiselect--disabled .multiselect__tags{background:#f3f4f5}.aioseo-localseo-opening .aioseo-col-alwaysopen .aioseo-checkbox{padding:0 10px}.sidebar-row{margin-bottom:16px}.sidebar-row .title{font-weight:700}
1
+ .aioseo-app .aioseo-cta{margin-top:30px;background:#fff;width:100%;padding:40px;box-shadow:0 2px 5px rgba(0,0,0,.05);border:1px solid #e8e8eb}.aioseo-app .aioseo-cta.floating{margin-top:0;position:absolute;max-width:850px;right:50%;top:50%;transform:translateX(50%) translateY(-50%);box-shadow:0 5px 20px rgba(0,0,0,.1);border-radius:3px}.aioseo-app .aioseo-cta .header-text{line-height:1.4;font-weight:600;font-size:24px;text-align:center;color:#141b38}.aioseo-app .aioseo-cta .header-text span.large{line-height:1.4;font-size:32px}.aioseo-app .aioseo-cta .description{margin:30px 0 50px;width:100%;max-width:600px;text-align:center;font-size:16px;color:#141b38;line-height:1.4}.aioseo-app .aioseo-cta .description .aioseo-alert{margin-bottom:30px;text-align:right}.aioseo-app .aioseo-cta .feature-list{color:#141b38;font-size:16px;width:100%;max-width:500px;margin-bottom:50px}.aioseo-app .aioseo-cta .feature-list .aioseo-col{display:flex;align-items:flex-start}.aioseo-app .aioseo-cta .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:18px;min-width:18px;min-height:18px;margin-left:10px}.aioseo-app .aioseo-cta a.learn-more{margin-top:20px;color:#8c8f9a;font-size:14px}.aioseo-app .aioseo-cta .type-1{display:flex;flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2{margin:30px 50px 30px 0;display:flex}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:right}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-2>div{margin-left:20px;flex:0 0 50%}.aioseo-app .aioseo-cta .type-2 .featured-image{max-height:540px;border:1px solid #e8e8eb;flex:1;overflow:hidden;margin-left:-41px;margin-bottom:-71px;border-radius:0 5px 0 0}.aioseo-app .aioseo-cta .type-2 .featured-image img{max-height:600px}@media only screen and (max-width:912px){.aioseo-app .aioseo-cta .type-2{flex-direction:column;align-items:center}.aioseo-app .aioseo-cta .type-2 .description,.aioseo-app .aioseo-cta .type-2 .header-text{text-align:center}.aioseo-app .aioseo-cta .type-2>div{text-align:center;margin-left:0;margin-bottom:30px;flex:1 0 100%;width:100%}.aioseo-app .aioseo-cta .type-2 .featured-image{margin:0 -10px -41px;border-radius:5px 5px 0 0;max-height:300px}}.aioseo-app .aioseo-cta .type-3 .sub-header{line-height:1.4;font-size:16px;font-weight:600;color:#005ae0;margin-bottom:5px}.aioseo-app .aioseo-cta .type-3 .header-text{text-align:right}.aioseo-app .aioseo-cta .type-3 .feature-list{margin:30px 0}.aioseo-app .aioseo-cta .type-3 .feature-list .aioseo-col svg.aioseo-circle-check{color:#00aa63;width:21px;min-width:21px;min-height:21px;margin-left:5px}.aioseo-app .aioseo-cta .type-3 .aioseo-button{margin-left:12px}.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:calc(200px + 1em)}@media only screen and (max-width:48em){.aioseo-box-toggle .aioseo-row .aioseo-col{max-width:100%}}.aioseo-box-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-box-toggle input:checked+label{background-color:#fff;box-shadow:0 5px 10px rgba(0,90,224,.1);border:2px solid #005ae0;font-weight:600}.aioseo-box-toggle label{background-color:#f9f9fa;color:#141b38;font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;border:1px solid #f9f9fa;transition:all .1s ease-in-out;border-radius:3px;height:165px;position:relative}.aioseo-box-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-box-toggle label:hover{cursor:pointer}.aioseo-button{flex-shrink:0;line-height:1;display:inline-flex;align-items:center;justify-content:center;font-size:16px;font-weight:600;padding:0 24px;border-radius:4px;-webkit-appearance:none;cursor:pointer;height:48px;transition:background-color .2s ease;position:relative;overflow:hidden;text-decoration:none;color:#141b38;white-space:nowrap}.aioseo-button.small,.aioseo-button.small-table{height:30px;font-size:14px;padding:0 12px}.aioseo-button.small-table .loading-spinner,.aioseo-button.small .loading-spinner{width:25px;height:25px}.aioseo-button.small-table{font-size:12px;border-radius:3px}.aioseo-button.medium{height:40px;font-size:14px;padding:0 18px}.aioseo-button.medium .loading-spinner{width:35px;height:35px}.aioseo-button.xl{height:66px;border-radius:4px;font-size:18px;padding:0 48px}.aioseo-button.gray{border:1px solid #dcdde1;background-color:#f3f4f5}.aioseo-button.gray:hover{background-color:#fff;color:#141b38}.aioseo-button.gray:active{background-color:#f3f4f5}.aioseo-button.green{border:none;background-color:#00aa63;color:#fff}.aioseo-button.green:hover{background-color:#07c575}.aioseo-button.green:active{background-color:#15955f}.aioseo-button.blue{border:none;background-color:#005ae0;color:#fff}.aioseo-button.blue:hover{background-color:#1a82ea}.aioseo-button.blue:active{background-color:#004f9d}.aioseo-button.wp-blue{border:1px solid #005ae0;background-color:#f3f5f6;color:#005ae0}.aioseo-button.wp-blue:hover{background-color:#1a82ea;border-color:#1a82ea;color:#fff}.aioseo-button.wp-blue:active{background-color:#004f9d;border-color:#004f9d;color:#fff}.aioseo-button.black{border:none;background-color:#434960;color:#fff}.aioseo-button.black:hover{background-color:#2c324c}.aioseo-button.black:active{background-color:#141b38}.aioseo-button.red{border:1px solid #df2a4a;background-color:#fff;color:#df2a4a}.aioseo-button.red:hover{background-color:#df2a4a;color:#fff}.aioseo-button.red:active{background-color:#ab2039}.aioseo-button.loading.blue,.aioseo-button.loading.blue:hover{background-color:#004f9d;color:#004f9d}.aioseo-button.loading.green,.aioseo-button.loading.green:hover{background-color:#15955f;color:#15955f}.aioseo-button.loading.gray,.aioseo-button.loading.gray:hover{background-color:#f3f4f5;color:#f3f4f5}.aioseo-button.loading.black,.aioseo-button.loading.black:hover{background-color:#141b38;color:#141b38}.aioseo-button:disabled{border:1px solid #dcdde1;color:#8c8f9a;background-color:#f3f4f5;cursor:default}.aioseo-button:disabled.gray:hover{color:#8c8f9a}.aioseo-button:disabled.wp-blue{border-color:#ddd;background-color:#f7f7f7}.aioseo-button:disabled.wp-blue:hover{border-color:#ddd;color:#8c8f9a}.aioseo-button:disabled:hover{background-color:#f3f4f5}.aioseo-checkbox{display:inline-flex;align-items:center}.aioseo-checkbox.disabled,.aioseo-checkbox.disabled .form-checkbox .fancy-checkbox,.aioseo-checkbox.no-clicks,.aioseo-checkbox.no-clicks .form-checkbox .fancy-checkbox{cursor:default}.aioseo-checkbox .form-checkbox-wrapper{margin-left:10px;display:flex}.aioseo-checkbox.medium .form-checkbox{width:20px;height:20px}.aioseo-checkbox.medium .form-checkbox .fancy-checkbox svg{width:12px;height:12px}.aioseo-checkbox.medium .form-checkbox span:before{height:18px;width:18px;line-height:20px}.aioseo-checkbox.round .form-checkbox span,.aioseo-checkbox.round .form-checkbox span:before{border-radius:50%}.aioseo-checkbox .form-checkbox{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-checkbox .form-checkbox input{display:none}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.blue{background:#005ae0}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox.green{background:#00aa63}.aioseo-checkbox .form-checkbox input:checked+.fancy-checkbox:before{background:transparent}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox{background:#e8e8eb!important;border:1px solid #d0d1d7;cursor:default}.aioseo-checkbox .form-checkbox input:disabled+.fancy-checkbox svg{color:#8c8f9a}.aioseo-checkbox .form-checkbox input:not(:checked):disabled+.fancy-checkbox:before{right:0;bottom:0;background:#e8e8eb}.aioseo-checkbox .form-checkbox .fancy-checkbox svg{color:#fff;width:16px;height:16px}.aioseo-checkbox .form-checkbox span{position:absolute;cursor:pointer;top:0;right:0;left:0;bottom:0;background-color:#d0d1d7;transition:.2s;border-radius:3px;display:flex;align-items:center;justify-content:center}.aioseo-checkbox .form-checkbox span:before{position:absolute;content:"";height:26px;width:26px;right:1px;bottom:1px;background-color:#fff;transition:.2s;font-size:18px;line-height:28px;border-radius:2px}.aioseo-date-picker.vue-daterange-picker{width:100%}.aioseo-date-picker.vue-daterange-picker .form-control{display:flex;align-items:center;color:#141b38;font-size:16px;height:48px;border-radius:3px;border:1px solid #d0d1d7;position:relative}.aioseo-date-picker.vue-daterange-picker .form-control svg.aioseo-circle-close{position:absolute;left:10px;color:#434960;width:15px;height:15px}.aioseo-date-picker.vue-daterange-picker.small .form-control{height:30px}.aioseo-date-picker.vue-daterange-picker.medium .form-control{height:40px}body[class*=all-in-one-seo_page] .daterangepicker .yearselect{width:75px}.aioseo-editor{position:relative}.aioseo-editor .aioseo-editor-description .ql-editor{min-height:100px}.aioseo-editor .aioseo-editor-line-numbers .ql-editor{padding:15px 45px 15px 15px}.aioseo-editor .aioseo-editor-single .ql-editor{padding:8px 10px}.aioseo-editor .aioseo-editor-single.aioseo-editor-line-numbers .ql-editor{padding:8px 45px 8px 10px}.aioseo-editor .aioseo-editor-monospace .ql-editor{font-family:monospace}.aioseo-editor .aioseo-line-numbers{background:#f7f6f7;position:absolute;text-align:left;top:1px;width:29px;right:1px;border-radius:0 3px 3px 0;padding:15px 0 0 9px;display:flex;height:calc(100% - 2px);flex-direction:column;overflow:hidden}.aioseo-editor .aioseo-line-numbers div{min-height:25px;color:#8c8f9a;font-size:12px;line-height:1.9}.aioseo-editor .ql-disabled{pointer-events:none;background-color:#f9f9fa}.aioseo-editor .ql-editor{padding:15px;border-radius:3px;font-size:16px;color:#141b38;border:1px solid #d0d1d7}.aioseo-editor .ql-editor:focus{border:1px solid #005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-editor .ql-editor .mention .ql-mention-denotation-char{display:none}.aioseo-editor .ql-editor .mention .aioseo-tag{height:25px;margin:0 1px;color:#434960;font-weight:600;font-size:14px;padding:3px 10px 3px 25px;background-color:#f3f4f5;border-radius:3px;cursor:pointer;position:relative;display:inline-flex;align-items:center}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle{display:inline-flex;align-items:center;background-color:#e8e8eb;position:absolute;top:0;left:0;bottom:0;border-radius:3px 0 0 3px}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret{width:18px;height:18px;transition:transform .3s}.aioseo-editor .ql-editor .mention .aioseo-tag .tag-toggle svg.aioseo-caret.rotated{transform:rotate(-180deg)}.aioseo-editor .ql-mention-list-container{color:#141b38;background-color:#fff;max-width:250px;width:100%;margin-top:3px;border:1px solid #d0d1d7;border-radius:3px;box-shadow:0 3px 15px rgba(0,0,0,.1);z-index:9001}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom,.aioseo-editor .ql-mention-list-container .aioseo-tag-search{padding:12px;border-bottom:1px solid #e8e8eb}.aioseo-editor .ql-mention-list-container .aioseo-tag-custom{display:none}.aioseo-editor .ql-mention-list-container .ql-mention-list{list-style:none;margin:0;padding:0;max-height:210px;overflow:auto}.aioseo-editor .ql-mention-list-container .ql-mention-list li{color:#141b38;margin:0;background-color:transparent;border-bottom:1px solid #e8e8eb;padding:15px;cursor:pointer;font-size:14px}.aioseo-editor .ql-mention-list-container .ql-mention-list li:last-child{border-bottom:0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover{color:#005ae0;background-color:#f2f7fd}.aioseo-editor .ql-mention-list-container .ql-mention-list li.selected .aioseo-tag-description,.aioseo-editor .ql-mention-list-container .ql-mention-list li:hover .aioseo-tag-description{color:initial}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item{display:flex}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item>div:first-child{margin-left:10px}.aioseo-editor .ql-mention-list-container .ql-mention-list li .aioseo-tag-item .aioseo-tag-title{font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match{cursor:default;padding:12px;font-size:16px;font-weight:600}.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match.highlight,.aioseo-editor .ql-mention-list-container .ql-mention-list li.aioseo-tag-no-match:hover{color:initial;background-color:transparent}.aioseo-editor .ql-toolbar{display:none}.aioseo-editor .ql-clipboard{right:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.aioseo-editor .ql-snow .ql-hidden{display:none}.aioseo-editor .ql-container.ql-snow{border:none}.aioseo-editor .ql-container p{font-size:16px;margin:0;line-height:25px}.aioseo-highlight-toggle{border:1px solid #e8e8eb;border-radius:3px;min-height:48px;display:flex;align-items:center;padding:5px 10px;cursor:pointer}.aioseo-highlight-toggle>*{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-highlight-toggle.active{border-color:#005ae0;box-shadow:0 5px 10px rgba(0,90,224,.1)}.aioseo-highlight-toggle.medium{min-height:40px}.aioseo-highlight-toggle .icon{display:flex;align-items:center;margin-left:5px}.aioseo-input[data-v-3f0a80a7]{position:relative;width:100%}.aioseo-input.file[data-v-3f0a80a7],.aioseo-input.file input[type=file][data-v-3f0a80a7]{position:absolute;top:0;left:0;right:0;bottom:0;margin:0;padding:0}.aioseo-input.file input[type=file][data-v-3f0a80a7]{cursor:pointer;opacity:0}.aioseo-input.file input[type=file][data-v-3f0a80a7]::-webkit-file-upload-button{visibility:hidden}.aioseo-input.file input[type=file][data-v-3f0a80a7]:focus{box-shadow:none}.aioseo-input input[data-v-3f0a80a7]{height:48px;width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:3px;padding:15px;font-size:18px;position:relative;overflow:hidden;margin:0}.aioseo-input input[data-v-3f0a80a7]:disabled{background:#f9f9fa}.aioseo-input input[data-v-3f0a80a7]:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-input input[data-v-3f0a80a7]::-moz-placeholder{color:#8c8f9a}.aioseo-input input[data-v-3f0a80a7]:-ms-input-placeholder{color:#8c8f9a}.aioseo-input input[data-v-3f0a80a7]::placeholder{color:#8c8f9a}.aioseo-input input.prepend[data-v-3f0a80a7]{padding-right:50px}.aioseo-input input.append[data-v-3f0a80a7]{padding-left:50px}.aioseo-input input.small[data-v-3f0a80a7]{height:30px;padding:10px;font-size:14px}.aioseo-input input.small.prepend[data-v-3f0a80a7]{padding-right:30px}.aioseo-input input.small.append[data-v-3f0a80a7]{padding-left:30px}.aioseo-input input.medium[data-v-3f0a80a7]{height:40px;padding:12px;font-size:16px}.aioseo-input input.medium.prepend[data-v-3f0a80a7]{padding-right:35px}.aioseo-input input.medium.append[data-v-3f0a80a7]{padding-left:35px}.aioseo-input.aioseo-active input[data-v-3f0a80a7]{border-color:#00aa63}.aioseo-input.aioseo-active input[data-v-3f0a80a7]:active,.aioseo-input.aioseo-active input[data-v-3f0a80a7]:focus{box-shadow:0 0 0 1px #00aa63}.aioseo-input.aioseo-active .append-icon[data-v-3f0a80a7],.aioseo-input.aioseo-active .prepend-icon[data-v-3f0a80a7]{color:#00aa63}.aioseo-input.aioseo-error input[data-v-3f0a80a7]{border-color:#df2a4a}.aioseo-input.aioseo-error input[data-v-3f0a80a7]:active,.aioseo-input.aioseo-error input[data-v-3f0a80a7]:focus{box-shadow:0 0 0 1px #df2a4a}.aioseo-input.aioseo-error .append-icon[data-v-3f0a80a7],.aioseo-input.aioseo-error .prepend-icon[data-v-3f0a80a7]{color:#df2a4a}.aioseo-input.aioseo-warning input[data-v-3f0a80a7]{border-color:#f18200}.aioseo-input.aioseo-warning input[data-v-3f0a80a7]:active,.aioseo-input.aioseo-warning input[data-v-3f0a80a7]:focus{box-shadow:0 0 0 1px #f18200}.aioseo-input.aioseo-warning .append-icon[data-v-3f0a80a7],.aioseo-input.aioseo-warning .prepend-icon[data-v-3f0a80a7]{color:#f18200}.aioseo-input .prepend-icon[data-v-3f0a80a7]{position:absolute;top:0;right:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .prepend-icon svg[data-v-3f0a80a7]{width:30px;height:30px}.aioseo-input .prepend-icon.small[data-v-3f0a80a7]{width:20px}.aioseo-input .prepend-icon.small svg[data-v-3f0a80a7]{width:10px;height:10px}.aioseo-input .prepend-icon.medium[data-v-3f0a80a7]{width:15px}.aioseo-input .prepend-icon.medium svg[data-v-3f0a80a7]{width:15px;height:15px}.aioseo-input .append-icon[data-v-3f0a80a7]{position:absolute;top:0;left:10px;width:30px;height:100%;color:#d0d1d7;display:flex;align-items:center;z-index:1}.aioseo-input .append-icon svg[data-v-3f0a80a7]{width:30px;height:30px}.aioseo-input .append-icon.small[data-v-3f0a80a7]{width:10px}.aioseo-input .append-icon.medium[data-v-3f0a80a7]{width:15px}.aioseo-input .append-icon.clickable[data-v-3f0a80a7]{cursor:pointer;padding:0 5px;background:#f3f4f5;border:1px solid #d0d1d7;color:#434960;left:0;width:30px;border-radius:3px 0 0 3px}.aioseo-input .append-icon.clickable.small[data-v-3f0a80a7]{width:15px}.aioseo-input .append-icon.clickable.medium[data-v-3f0a80a7]{padding:0 10px;width:40px}.aioseo-phone-number{max-width:600px}.aioseo-phone-number label{display:none}.aioseo-phone-number .maz-input__input{height:40px;min-height:40px;padding-top:0!important;border:1px solid #d0d1d7}.aioseo-phone-number .maz-input__input:focus{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .country-selector{flex:0 0 140px;width:140px;min-width:140px;max-width:140px}.aioseo-phone-number .country-selector:hover{z-index:1}.aioseo-phone-number .country-selector>div.maz-base-component.maz-input.has-value.has-1-right-icon.maz-input--primary>input{padding-right:50px!important}.aioseo-phone-number .country-selector .maz-input.is-focused{border-color:#005ae0}.aioseo-phone-number .country-selector .maz-select__options-list__item.selected.keyboard-selected{background-color:#005ae0}.aioseo-phone-number .maz-phone-number-input__country-flag{right:20px;bottom:12px;z-index:auto}.aioseo-phone-number .maz-input__icon{z-index:auto}.aioseo-phone-number .maz-select__options-list input{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-phone-number .maz-input__input{border-radius:3px}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input{border-color:red}.aioseo-phone-number.invalidNumber div.maz-flex-1>div>input:focus{border-color:#df2a4a;box-shadow:0 0 0 1px #df2a4a}.aioseo-phone-number.validNumber div.maz-flex-1>div>input:focus{border-color:#00aa63;box-shadow:0 0 0 1px #00aa63}.aioseo-radio{display:inline-flex;align-items:center}.aioseo-radio .form-radio-wrapper{margin-left:10px;display:flex}.aioseo-radio.medium .form-radio{width:20px;height:20px}.aioseo-radio.medium .form-radio .fancy-radio svg{width:12px;height:12px}.aioseo-radio.medium.type-1 .form-radio span:before{height:18px;width:18px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:before{height:16px;width:16px;line-height:20px}.aioseo-radio.medium.type-2 .form-radio span:after{height:6px;width:6px;right:6px;bottom:6px}.aioseo-radio .form-radio{position:relative;display:inline-block;width:28px;height:28px;color:#fff;vertical-align:bottom;text-align:center}.aioseo-radio .form-radio input{opacity:0}.aioseo-radio .form-radio input:checked+.fancy-radio{background:#005ae0;border-color:#005ae0}.aioseo-radio .form-radio input:checked+.fancy-radio:before{background:transparent}.aioseo-radio .form-radio input:checked+.fancy-radio:after{display:block}.aioseo-radio .form-radio input:disabled+.fancy-radio{cursor:default}.aioseo-radio .form-radio input:focus+.fancy-radio{border-color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-radio .form-radio .fancy-radio{border-radius:50%}.aioseo-radio .form-radio .fancy-radio svg{color:#fff;width:16px;height:16px}.aioseo-radio .form-radio span{position:absolute;cursor:pointer;top:0;right:0;left:0;bottom:0;transition:.2s;border-radius:50%;display:flex;align-items:center;justify-content:center}.aioseo-radio .form-radio span:before{position:absolute;content:"";height:26px;width:26px;right:1px;bottom:1px;transition:.2s;font-size:18px;line-height:28px;border-radius:50%}.aioseo-radio.type-1 .form-radio span,.aioseo-radio.type-1 .form-radio span:before{background-color:#f3f4f5}.aioseo-radio.type-2 .form-radio span{border:1px solid #d0d1d7;background-color:#fff}.aioseo-radio.type-2 .form-radio span:before{background-color:#fff}.aioseo-radio.type-2 .form-radio span:after{display:none;position:absolute;content:"";height:10px;width:10px;right:8px;bottom:8px;background-color:#fff;transition:.2s;border-radius:50%}.aioseo-radio.disabled{cursor:default}.aioseo-radio.disabled.type-2 .form-radio input:checked+.fancy-radio{background-color:#e8e8eb;border-color:#d0d1d7}.aioseo-radio.disabled.type-2 .form-radio span,.aioseo-radio.disabled.type-2 .form-radio span:before{background-color:#e8e8eb}.aioseo-radio.disabled.type-2 .form-radio span:after{background-color:#8c8f9a}.aioseo-radio-toggle{display:flex;align-items:center;height:40px}.aioseo-radio-toggle div{height:100%}.aioseo-radio-toggle.inline{display:inline-flex}.aioseo-radio-toggle div:first-child{overflow:hidden;border-radius:0 3px 3px 0}.aioseo-radio-toggle div:first-child label{border-radius:0 3px 3px 0}.aioseo-radio-toggle div:last-child{overflow:hidden;border-radius:3px 0 0 3px}.aioseo-radio-toggle div:last-child label{border-radius:3px 0 0 3px}.aioseo-radio-toggle input{position:absolute!important;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.aioseo-radio-toggle input:checked+label{background-color:#005ae0;color:#fff}.aioseo-radio-toggle input:checked+label.dark{background-color:#434960;color:#fff}.aioseo-radio-toggle label{height:100%;background-color:#e8e8eb;color:#141b38;font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;flex-direction:column;transition:all .1s ease-in-out;position:relative;padding:11px 20px;font-weight:600}.aioseo-radio-toggle label.disabled{cursor:default;pointer-events:none;opacity:.5}.aioseo-radio-toggle label:hover{background-color:#dadadf;cursor:pointer}.aioseo-radio-toggle label p{position:absolute;bottom:15px;margin:0}.aioseo-radio-toggle.circle label{background:#fff;color:#8c8f9a}.aioseo-radio-toggle.circle input+label{border-radius:50%;width:36px;height:36px;padding:8px}.aioseo-radio-toggle.circle input:checked+label{background:#e8e8eb;color:#2c324c}.aioseo-select{height:48px}.aioseo-select.multiselect--disabled .multiselect__select{background:none}.aioseo-select .multiselect__select{display:flex;align-items:center;justify-content:center;min-height:46px}.aioseo-select .multiselect__select:before{display:none}.aioseo-select .multiselect__select svg.aioseo-caret{color:#141b38;width:18px;height:18px;transition:transform .3s}.aioseo-select .multiselect__tags{height:100%;border:1px solid #d0d1d7;border-radius:3px;display:flex;justify-content:center;flex-direction:column;padding:16px 16px 16px 40px}.aioseo-select .multiselect__tags .multiselect__spinner{height:calc(100% - 2px);border:2px solid transparent}.aioseo-select .multiselect__tags .multiselect__spinner:after,.aioseo-select .multiselect__tags .multiselect__spinner:before{border-top-color:#434960}.aioseo-select .multiselect__tags .multiselect__single{display:inline-flex;margin:0;padding:0;color:#141b38;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.aioseo-select .multiselect__tags .multiselect__placeholder{color:#8c8f9a;font-size:16px;line-height:20px;margin:0;padding:0}.aioseo-select .multiselect__tags .multiselect__input{padding:0;margin:0 0 0 10px;border-radius:0;border:none;color:#141b38;min-height:auto;line-height:20px}.aioseo-select .multiselect__tags .multiselect__input:focus{outline:0;box-shadow:none;border:none}.aioseo-select .multiselect__tags .multiselect__input::-moz-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input:-ms-input-placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__input::placeholder{color:#8c8f9a}.aioseo-select .multiselect__tags .multiselect__tags-wrap{display:flex;align-items:center;flex-wrap:wrap}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag{padding:0;display:inline-flex;align-items:center;font-size:14px;font-weight:600;color:#434960;margin:0 0 0 3px;height:24px;background-color:#f3f4f5;flex-shrink:0}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-value{padding:0 10px 0 5px}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove{padding:0 10px;height:100%;cursor:pointer;background-color:#f3f4f5;display:flex;align-items:center}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover{background-color:#434960;color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove:hover svg.aioseo-close{color:#fff}.aioseo-select .multiselect__tags .multiselect__tags-wrap .multiselect__tag .multiselect__tag-remove svg.aioseo-close{color:#434960;width:10px;height:10px}.aioseo-select.multiselect--active .multiselect__tags-wrap{margin-bottom:7px}.aioseo-select.small{height:30px;min-height:30px}.aioseo-select.small .multiselect__tags{min-height:30px;padding:8px 8px 8px 38px}.aioseo-select.small .multiselect__tags .multiselect__placeholder{font-size:14px}.aioseo-select.small .multiselect__select{height:28px;min-height:28px}.aioseo-select.small .multiselect__input{font-size:14px}.aioseo-select.small .multiselect__content-wrapper li.multiselect__element .multiselect__option{font-size:14px;padding:8px;min-height:30px}.aioseo-select.medium{height:40px}.aioseo-select.medium .multiselect__tags{padding:7px 7px 7px 40px}.aioseo-select.medium .multiselect__select{min-height:38px}.aioseo-select.multiple{min-height:48px;height:auto}.aioseo-select.multiple.small{min-height:30px}.aioseo-select.multiple.medium{min-height:40px}.aioseo-select.multiselect--above .multiselect__content-wrapper{border-top:1px solid #d0d1d7;border-bottom:none}.aioseo-select .multiselect__content-wrapper{border:1px solid #d0d1d7;border-top:none;border-bottom-right-radius:3px;border-bottom-left-radius:3px;z-index:50;-webkit-overflow-scrolling:touch}.aioseo-select .multiselect__content-wrapper .multiselect__content{max-width:100%}.aioseo-select .multiselect__content-wrapper li.multiselect__element{margin:0;border-bottom:1px solid #e8e8eb}.aioseo-select .multiselect__content-wrapper li.multiselect__element.last{border-bottom:none}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--highlight:after{background-color:#005ae0;color:#fff}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--selected{background-color:#f2f7fd}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option--disabled{font-weight:400;background-color:#fff!important;color:#8c8f9a}.aioseo-select .multiselect__content-wrapper li.multiselect__element .multiselect__option .docLink{font-size:13px;float:left}.aioseo-textarea-autosize{width:100%;background-color:#fff;border:1px solid #d0d1d7;border-radius:4px;font-size:16px;padding:12px}.aioseo-toggle{display:inline-flex}.aioseo-toggle:active,.aioseo-toggle:focus{outline:2px solid transparent}.aioseo-toggle.disabled{pointer-events:none}.aioseo-toggle.disabled .toggle-content{opacity:.5}.aioseo-toggle .toggle-content{position:relative;display:inline-block;width:36px;height:20px;margin-left:10px}.aioseo-toggle .toggle-content input{display:none}.aioseo-toggle .toggle-content input:checked+.toggle-switch{border:1px solid #005ae0;background-color:#005ae0}.aioseo-toggle .toggle-content input:checked+.toggle-switch:focus{outline:2px solid transparent}.aioseo-toggle .toggle-content input:checked+.toggle-switch:before{background-color:#fff;transform:translateX(-15px)}.aioseo-toggle .toggle-content input:focus+.toggle-switch{box-shadow:0 0 1px #005ae0;outline:2px solid transparent}.aioseo-toggle .toggle-content .toggle-switch{position:absolute;cursor:pointer;top:0;right:0;left:0;bottom:0;background-color:#fff;border:1px solid #d0d1d7;border-radius:15px;transition:.2s}.aioseo-toggle .toggle-content .toggle-switch:before{position:absolute;content:"";height:14px;width:14px;right:3px;bottom:2px;background-color:#d0d1d7;border-radius:50%;transition:.2s}.aioseo-wp-table input[type=search],.aioseo-wp-table select{border-color:#d0d1d7}.aioseo-wp-table select:focus{border-color:#005ae0;color:#005ae0;box-shadow:0 0 0 1px #005ae0}.aioseo-wp-table select:hover{color:#005ae0}.aioseo-wp-table input.button,.aioseo-wp-table input.button:hover{color:#005ae0;border-color:#005ae0}.aioseo-wp-table .header .subsubsub{color:#555d66;font-size:13px;font-weight:600}.aioseo-wp-table .header .subsubsub>span{display:inline-flex}.aioseo-wp-table .header .subsubsub .separator{margin:0 5px}.aioseo-wp-table .header .subsubsub .active{font-weight:700;color:#141b38}.aioseo-wp-table .header .subsubsub a{text-decoration:none}.aioseo-wp-table .header .subsubsub a:hover{text-decoration:underline}.aioseo-wp-table .header .search{display:flex;justify-content:flex-end}.aioseo-wp-table .header .search .aioseo-input{width:100%;max-width:215px;margin-left:6px}.aioseo-wp-table .header .pagination{color:#555d66}.aioseo-wp-table .header .pagination .button,.aioseo-wp-table .header .pagination input{margin-right:6px}.aioseo-wp-table .tablenav-pages .current-page{padding:0 8px 0 0}.aioseo-wp-table .wp-table{width:100%;position:relative}.aioseo-wp-table .wp-table .loader-overlay{position:absolute;top:46px;left:0;bottom:36px;right:0;background:rgba(0,0,0,.3);z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-wp-table .wp-table .no-results{color:#8c8f9a;min-height:200px;display:flex;align-items:center;justify-content:center;font-weight:400;font-size:24px}.aioseo-wp-table .wp-table tr.even{background-color:#f9f9fa}.aioseo-wp-table .wp-table tr.enabled td,.aioseo-wp-table .wp-table tr.enabled td strong a{color:#141b38}.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td,.aioseo-wp-table .wp-table tr:not(.enabled):not(.edit-row) td a.edit-link{color:#8c8f9a}.aioseo-wp-table .wp-table tr.edit-row th{padding:0 3px 0 0}.aioseo-wp-table .wp-table tr.edit-row td{padding:0 10px 0 30px}.aioseo-wp-table .wp-table tr td strong a{font-weight:400}.aioseo-wp-table .wp-table tr td .row-actions .edit a,.aioseo-wp-table .wp-table tr td strong a:hover{color:#005ae0}.aioseo-wp-table .wp-table tr td .row-actions .edit .trash a{color:#df2a4a}.aioseo-wp-table .wp-table tr td.edit-row-content .wrapper .border{margin-top:7px;padding:19px 0 20px;border-top:1px solid #e8e8eb}.custom-rules[data-v-191c51fe]{width:100%;margin-top:14px}.custom-rules .rule .rule-settings[data-v-191c51fe]{display:flex;flex-direction:row;align-items:center;flex:1}.custom-rules .rule .rule-settings>.aioseo-select[data-v-191c51fe]:first-child{width:100%;max-width:250px}.custom-rules .rule .rule-settings>[data-v-191c51fe]{margin:0 0 0 16px}.custom-rules .rule .rule-settings>[data-v-191c51fe]:last-child{margin-left:0}.custom-rules .rule .rule-settings>.aioseo-toggle[data-v-191c51fe]{margin:0 4px 0 10px}.custom-rules .rule .actions[data-v-191c51fe],.custom-rules .rule .logical[data-v-191c51fe]{flex:0}.custom-rules svg[data-v-191c51fe]{width:14px;height:14px;cursor:pointer}.custom-rules svg.aioseo-trash[data-v-191c51fe]{color:#dadada}.custom-rules svg.aioseo-trash[data-v-191c51fe]:hover{color:#df2a4a}.custom-rules .aioseo-tooltip[data-v-191c51fe]{margin:0;display:flex}.custom-rules .aioseo-button svg[data-v-191c51fe]{color:#fff;margin-left:6px}.aioseo-add-redirection.edit-url{margin-bottom:30px}.aioseo-add-redirection.edit-url .urls{align-items:flex-start}.aioseo-add-redirection.edit-url .urls .url-arrow{margin:-8px 30px 0}.aioseo-add-redirection.edit-url .advanced-settings-link{margin-top:21px}.aioseo-add-redirection .advanced-settings-link{text-decoration:underline!important}.aioseo-add-redirection.log-404 .urls .source{min-height:103px;align-items:flex-start}.aioseo-add-redirection .generic-error{margin-bottom:20px}.aioseo-add-redirection .aioseo-settings-row .settings-name .name{font-size:14px}.aioseo-add-redirection .urls{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .urls .break{flex-basis:100%;height:0}.aioseo-add-redirection .urls .url-arrow{width:36px;margin:-15px 30px 0;display:flex;align-items:center;justify-content:center}@media (min-width:1200px){.aioseo-add-redirection .urls .url-arrow{margin:-15px 50px 0}}.aioseo-add-redirection .urls .url-arrow svg{height:103px;color:#005ae0}.aioseo-add-redirection .urls .source,.aioseo-add-redirection .urls .target{flex:1;display:flex;align-items:center}.aioseo-add-redirection .urls .source>*,.aioseo-add-redirection .urls .target>*{flex:1}.aioseo-add-redirection .urls .source .aioseo-input,.aioseo-add-redirection .urls .target .aioseo-input{margin-bottom:12px}.aioseo-add-redirection .urls .target input{padding-left:30px}.aioseo-add-redirection .urls .target .append-icon{width:30px;justify-content:flex-end}.aioseo-add-redirection .urls .target .append-icon svg{max-width:16px;margin-left:5px}.aioseo-add-redirection .urls .target .append-icon svg:last-of-type{margin-left:0}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-add-redirection .urls .target .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-add-redirection .urls .target .aioseo-description{height:30px}.aioseo-add-redirection .urls .target .target-url-error,.aioseo-add-redirection .urls .target .target-url-warning{margin-bottom:10px}.aioseo-add-redirection .settings{display:flex;flex-direction:column;align-items:center;margin-top:24px}.aioseo-add-redirection .settings .all-settings{width:100%}.aioseo-add-redirection .settings .all-settings .all-settings-content{display:flex;align-items:center;flex-wrap:wrap}.aioseo-add-redirection .settings .all-settings .all-settings-content .advanced-settings-link{margin:16px 16px 0 0;color:#8c8f9a}@media (max-width:767px){.aioseo-add-redirection .settings .all-settings .all-settings-content{align-items:start}}.aioseo-add-redirection .settings>.actions{align-self:flex-end;margin-top:-50px}.aioseo-add-redirection .settings>.actions.advanced{margin-top:24px}.aioseo-add-redirection .settings .query-params,.aioseo-add-redirection .settings .redirect-type{margin-bottom:10px;flex:0 1 auto}.aioseo-add-redirection .settings .query-params .aioseo-select,.aioseo-add-redirection .settings .redirect-type .aioseo-select{margin-top:5px}.aioseo-add-redirection .settings .query-params{width:340px}.aioseo-add-redirection .settings .redirect-type{width:300px;margin-left:24px}.aioseo-add-redirection .settings .aioseo-button{align-self:flex-end}.aioseo-add-redirection .settings .cancel-edit-row{margin-right:10px}@media (min-width:1200px){.aioseo-add-redirection .settings .cancel-edit-row{margin-right:16px}}.aioseo-add-redirection-target-url,.aioseo-redirect-source-url{position:relative}.aioseo-redirect-source-url .aioseo-input input{padding-left:76px!important}.aioseo-redirect-source-url .aioseo-input .append-icon{width:60px;justify-content:flex-end}.aioseo-redirect-source-url .aioseo-input .append-icon svg{max-width:16px;margin-left:5px}.aioseo-redirect-source-url .aioseo-input .append-icon svg:last-of-type{margin-left:0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-gear:hover{color:#005ae0}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-check{color:#00aa63}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-circle-close{color:#df2a4a}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash{color:#8c8f9a;cursor:pointer}.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash.active,.aioseo-redirect-source-url .aioseo-input .append-icon svg.aioseo-trash:hover{color:#df2a4a}.aioseo-redirect-source-url .source-url-error,.aioseo-redirect-source-url .source-url-warning{margin-bottom:10px}.aioseo-redirect-source-url .source-url-options>div{padding-bottom:5px}.aioseo-redirect-source-url .source-url-options>div>div{margin-bottom:5px}.aioseo-add-redirection-url-results{display:flex;position:absolute;background:#fff;width:100%;max-height:300px;overflow:auto;border:1px solid #d0d1d7;border-radius:3px;z-index:50;right:1px;margin-top:-9px}.aioseo-add-redirection-url-results ul{display:inline-block;max-width:100%;list-style:none;padding:0;margin:0;min-width:100%;vertical-align:top}.aioseo-add-redirection-url-results ul li{margin:0;border-bottom:1px solid #e8e8eb;display:block}.aioseo-add-redirection-url-results ul li:last-of-type{border-bottom:none}.aioseo-add-redirection-url-results ul li>span{color:#141b38;font-weight:700;font-size:16px;white-space:normal;line-height:1.4;display:flex;padding:12px;min-height:40px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer}.aioseo-add-redirection-url-results ul li>span:hover{background-color:#f2f7fd}.aioseo-add-redirection-url-results ul li>span:hover .option-title{color:#005ae0}.aioseo-add-redirection-url-results .option{flex:1}.aioseo-add-redirection-url-results .option .option-title{font-weight:500;display:flex;font-size:16px;color:#141b38}.aioseo-add-redirection-url-results .option .option-title>div{margin-left:5px}.aioseo-add-redirection-url-results .option .option-title>div:first-of-type{display:inline-block}.aioseo-add-redirection-url-results .option .option-title .search-term{font-weight:700}.aioseo-add-redirection-url-results .option .option-details{display:flex;align-items:center;font-size:14px;color:#8c8f9a}.aioseo-add-redirection-url-results .option .option-details span{margin-left:15px}.aioseo-add-redirection-url-results .option-permalink{display:flex;align-items:center}.aioseo-add-redirection-url-results .option-permalink svg.aioseo-external{width:15px;height:15px;color:#434960}.aioseo-add-template-tag{border-radius:3px;padding:5px 10px;color:#141b38;font-size:14px;border:1px solid #e8e8eb;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-weight:600}.aioseo-add-template-tag:hover{background-color:#f3f4f5}.aioseo-add-template-tag svg.aioseo-plus{width:10px;height:10px;color:#005ae0}.aioseo-additional-pages .additional-pages-table{border:1px solid #d0d1d7;border-radius:3px;margin-bottom:20px}.aioseo-additional-pages .additional-pages-table .page-priority{max-width:110px}.aioseo-additional-pages .additional-pages-table .page-frequency{max-width:166px}.aioseo-additional-pages .additional-pages-table .page-last-modified{max-width:155px}.aioseo-additional-pages .additional-pages-table .page-actions{max-width:20px}.aioseo-additional-pages .additional-pages-table .page-actions .aioseo-tooltip{display:inline-block;margin:0}.aioseo-additional-pages .additional-pages-table .pages-header{height:50px;display:flex;font-size:14px;padding:0 30px;align-items:center;border-bottom:1px solid #d0d1d7}.aioseo-additional-pages .additional-pages-table .pages-header>div{flex:1 0 auto}.aioseo-additional-pages .additional-pages-table .pages-rows{font-size:14px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row{background-color:#fff;height:70px;display:flex;align-items:center;padding:0 30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row:last-of-type{border-radius:0 0 3px 3px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row.even{background-color:#f9f9fa}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div{flex:1 0 auto;padding-left:30px}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row>div:last-child{padding-left:0}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash{width:20px;height:20px;color:#8c8f9a;cursor:pointer;transition:color .1s ease}.aioseo-additional-pages .additional-pages-table .pages-rows .page-row .page-actions svg.aioseo-trash:hover{color:#df2a4a}.aioseo-additional-pages svg.aioseo-circle-plus{width:14px;height:14px;margin-left:10px}.aioseo-alert{position:relative;border-radius:3px;padding:24px;font-size:16px;color:#141b38;line-height:1.4}.aioseo-alert.small{padding:8px;font-size:13px}.aioseo-alert .aioseo-alert-close{cursor:pointer;position:absolute;top:-9px;left:-9px;width:18px;height:18px;border-radius:50%;padding:5px;display:inline-flex;justify-content:center;align-content:center}.aioseo-alert .aioseo-alert-close svg{width:100%;height:100%}.aioseo-alert.blue{border:1px solid #005ae0;background-color:#f2f7fd}.aioseo-alert.blue .aioseo-alert-close{background-color:#005ae0;color:#fff}.aioseo-alert.green{border:1px solid #00aa63;background-color:#f2fdf8}.aioseo-alert.green .aioseo-alert-close{background-color:#00aa63;color:#fff}.aioseo-alert.red{border:1px solid #df2a4a;background-color:#fbe9ec}.aioseo-alert.red .aioseo-alert-close{background-color:#df2a4a;color:#fff}.aioseo-alert.yellow{border:1px solid #f18200;background-color:#fcfae8}.aioseo-alert.yellow .aioseo-alert-close{background-color:#f18200;color:#fff}.aioseo-alert.no-border{border-width:0}.aioseo-alert.text-center{text-align:center}.aioseo-analyze-competitor-site-score{border:1px solid #00aa63;border-radius:3px;color:#00aa63;font-size:14px;padding:0 8px;height:24px;display:inline-flex;align-items:center;justify-content:center;margin-left:14px}.aioseo-analyze-competitor-site-score.red{color:#df2a4a;border-color:#df2a4a}.aioseo-analyze-competitor-site-score.orange{color:#f18200;border-color:#f18200}.aioseo-animated-dannie{display:flex;align-content:center;align-items:center;justify-content:center}.aioseo-animated-dannie svg{max-width:250px}.aioseo-api-bar{height:40px;background-color:#df2a4a;color:#fff;font-size:13px;padding:0 40px 0 14px}.aioseo-api-bar,.aioseo-api-bar .upgrade-text{display:flex;align-items:center;justify-content:center}.aioseo-api-bar .upgrade-text{flex:1}.aioseo-api-bar strong{font-weight:600}.aioseo-api-bar svg.aioseo-logo-gear{width:20px;height:20px;min-width:20px;margin-left:14px}.aioseo-api-bar svg.aioseo-close{cursor:pointer;width:12px;height:12px}.aioseo-api-bar a{color:#fff;text-decoration:underline}.aioseo-api-bar a:hover{text-decoration:none}@media screen and (max-width:782px){.aioseo-api-bar{padding:0 10px;height:60px}}.aioseo-attributes ul.aioseo-attributes-list[data-v-02af7dd2]{list-style:inside;list-style-type:disc;margin:20px 0 0}.aioseo-attributes ul.aioseo-attributes-list li[data-v-02af7dd2]{display:flex;margin-bottom:8px;align-items:flex-start}.aioseo-attributes ul.aioseo-attributes-list li div[data-v-02af7dd2]:first-of-type{flex:0 0 140px}.aioseo-blur{filter:blur(3px);pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.aioseo-card{color:#141b38;background-color:#fff;border:1px solid #e8e8eb;box-shadow:0 2px 5px rgba(0,0,0,.05);margin:30px 0}.aioseo-card.disabled .content{background:#f9f9fa;font-size:16px;line-height:24px}@media only screen and (max-width:782px){.aioseo-card{margin:20px 0}}.aioseo-card svg.aioseo-circle-question-mark{width:17px;height:17px;color:#8c8f99;transition:background-color .2s ease}.aioseo-card svg.aioseo-circle-question-mark:hover{color:#5a5c65}.aioseo-card .header{display:flex;align-items:center;height:70px;padding:0 30px;font-weight:600;font-size:18px;border-bottom:1px solid #e8e8eb}.aioseo-card .header .header-icon{display:flex}.aioseo-card .header .header-icon svg{width:24px;height:24px;margin-left:16px}.aioseo-card .header .text{flex:1 0 auto;display:flex;align-items:center}.aioseo-card .header .text svg.aioseo-circle-question-mark{cursor:pointer;width:17px;height:17px}.aioseo-card .header .text .aioseo-pro-badge{margin-right:10px}.aioseo-card .header .text .card-score{display:flex;flex:1;align-items:center;justify-content:flex-end;padding-left:18px;font-size:13px}.aioseo-card .header .text .card-score.green{color:#00aa63}.aioseo-card .header .text .card-score.orange{color:#f18200}.aioseo-card .header .text .card-score.red{color:#df2a4a}.aioseo-card .header .text .card-score svg{margin-left:7px}.aioseo-card .header svg.aioseo-caret{width:24px;height:24px;cursor:pointer;transform:rotate(180deg);transition:transform .3s}.aioseo-card .header svg.aioseo-caret.rotated{transform:rotate(90deg)}.aioseo-card .header svg.aioseo-close{width:14px;height:14px;cursor:pointer}.aioseo-card .content{padding:30px;position:relative}.aioseo-card div.aioseo-settings-row:last-child{margin-bottom:0;border-bottom:none;padding-bottom:0}.aioseo-copy-block{display:inline-flex}.aioseo-copy-block .message{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-radius:0 3px 3px 0;padding:10px 24px;font-weight:600}.aioseo-copy-block .copy-tooltip{display:flex}.aioseo-copy-block .copy{background-color:#fff;min-height:56px;display:flex;align-items:center;border:1px solid #dcdde1;border-right-width:0;border-radius:3px 0 0 3px;padding:10px 16px;font-weight:600;cursor:pointer}.aioseo-copy-block .copy:hover svg.aioseo-copy{color:#a7a7a7}.aioseo-copy-block .copy svg.aioseo-copy{width:20px;height:20px;color:#dadada}.aioseo-copy-block .copy svg.aioseo-circle-check-solid{width:20px;height:20px;color:#00aa63}.aioseo-display-info .aioseo-box-toggle svg{margin-top:-15px;color:#434960}.aioseo-display-info svg.aioseo-new-page,.aioseo-display-info svg.aioseo-shortcode,.aioseo-display-info svg.aioseo-widget{width:100%;height:auto;max-width:60px}.aioseo-display-info svg.aioseo-gutenberg-block{width:59px;height:54px}.aioseo-display-info svg.aioseo-gutenberg-block rect{width:100%;width:56px;height:51px}.aioseo-display-info svg.aioseo-php{width:110px}.aioseo-display-info .copy-box,.aioseo-display-info .extra-box{margin-top:10px;padding:30px;border-radius:3px;background-color:#f9f9fa}.aioseo-display-info .copy-box .aioseo-description,.aioseo-display-info .extra-box .aioseo-description{margin:0}.aioseo-display-info .copy-box .aioseo-copy-block,.aioseo-display-info .extra-box .aioseo-copy-block{margin:20px 0 0}.aioseo-display-info .copy-box .advanced-settings-link,.aioseo-display-info .extra-box .advanced-settings-link{display:inline-block;padding-top:5px;margin:16px 16px 0 0;color:#8c8f9a;text-decoration:underline;font-size:13px}.aioseo-display-info .copy-box .advanced-settings-link:hover,.aioseo-display-info .extra-box .advanced-settings-link:hover{text-decoration:none}.aioseo-display-info .copy-box .advanced-settings,.aioseo-display-info .extra-box .advanced-settings{padding-top:20px}.aioseo-display-info .advanced-settings.advanced-settings-hidden{display:none}.aioseo-display-info .aioseo-tooltip{margin-right:0}.aioseo-exclude-posts{display:flex}.aioseo-facebook-preview{background-color:#f0f2f5;padding:30px;display:flex;align-items:center;justify-content:center}.aioseo-facebook-preview .facebook-post{width:100%;max-width:525px;border-radius:10px;box-shadow:0 2px 5px rgba(0,0,0,.1);background-color:#fff}.aioseo-facebook-preview .facebook-post .facebook-header{height:65px;padding:0 18px;display:flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo{overflow:hidden;width:40px;height:40px;border:1px solid #e8e8eb;border-radius:50%}.aioseo-facebook-preview .facebook-post .facebook-header .profile-photo img{height:100%;width:100%}.aioseo-facebook-preview .facebook-post .facebook-header .poster{margin-right:10px;flex:1 0 auto}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-name{font-size:15px;color:#050505;font-weight:500}.aioseo-facebook-preview .facebook-post .facebook-header .poster .poster-date{color:#65676b;font-size:13px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis{display:inline-flex;align-items:center}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div{background-color:#5e666f;width:4px;height:4px;border-radius:50%;margin:0 2px}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:first-child{margin-right:0}.aioseo-facebook-preview .facebook-post .facebook-header .ellipsis div:last-child{margin-left:0}.aioseo-facebook-preview .facebook-post .facebook-content{display:flex;flex-direction:column}.aioseo-facebook-preview .facebook-post .facebook-content img{width:100%;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content.vertical{flex-direction:row}.aioseo-facebook-preview .facebook-post .facebook-content.vertical img{max-width:158px;max-height:158px;width:auto;height:auto}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description{flex:1;background-color:#f2f3f5;padding:9px 13px;color:#606770}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-domain{font-size:13px;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-title{color:#1d2129;font-size:17px;font-weight:600;margin:5px 0}.aioseo-facebook-preview .facebook-post .facebook-content .facebook-site-description .site-description{font-size:14px}.aioseo-facebook-preview .facebook-post .facebook-footer{height:24px}.aioseo-feature-card{height:100%;border:1px solid #e8e8eb;background:#fff;box-shadow:0 2px 5px rgba(0,0,0,.05);color:#141b38;display:flex;flex-direction:column}.aioseo-feature-card .feature-card-body{padding:30px 30px 20px;flex:1}.aioseo-feature-card .feature-card-body.static{padding:30px}.aioseo-feature-card .feature-card-body .feature-card-header{display:flex;align-items:center;font-size:18px;font-weight:600;margin-bottom:16px}.aioseo-feature-card .feature-card-body .feature-card-header img,.aioseo-feature-card .feature-card-body .feature-card-header svg{width:28px;height:28px;margin-left:10px}.aioseo-feature-card .feature-card-body .feature-card-description{color:#434960;font-size:15px}.aioseo-feature-card .feature-card-body .feature-card-description .learn-more{margin-top:10px}.aioseo-feature-card .feature-card-footer{padding:15px}.aioseo-feature-card .feature-card-footer:not(.upgrade-required){border:2px solid #fff;background-color:#f9f9fa;padding:12px;min-height:43px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate{display:flex;align-items:center;justify-content:flex-end;height:30px;position:relative}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-loading-spinner{position:absolute;right:0}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .status{font-weight:600;font-size:14px}.aioseo-feature-card .feature-card-footer .feature-card-install-activate .aioseo-toggle .toggle-content{margin-left:0;margin-right:10px}.aioseo-feature-card .feature-card-footer .feature-card-upgrade-cta{display:flex;align-items:center;justify-content:flex-end}.aioseo-feature-card .feature-card-footer.installed .feature-card-install-activate .status{color:#8c8f9a}.aioseo-setup-wizard-container{margin-top:30px;margin-bottom:50px;padding:30px;color:#fff;position:relative;background-color:#005ae0}@media only screen and (max-width:782px){.aioseo-setup-wizard-container{margin-top:20px}}.aioseo-setup-wizard-container p{color:#fff}.aioseo-setup-wizard-container .getting-started-wrapper{display:flex}.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 533px;margin:20px 20px 0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{padding-bottom:56.25%;margin-bottom:-60px;position:relative;height:0}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper iframe{width:100%;height:100%;position:absolute;top:0;right:0}@media only screen and (max-width:1350px){.aioseo-setup-wizard-container .getting-started-wrapper .video{flex:0 0 593px;margin:20px;align-self:center}.aioseo-setup-wizard-container .getting-started-wrapper .video .wrapper{margin-bottom:0}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}@media only screen and (max-width:1300px){.aioseo-setup-wizard-container .getting-started-wrapper{flex-direction:row;flex-wrap:wrap}.aioseo-setup-wizard-container .getting-started-wrapper .video{margin:20px 0 -60px}.aioseo-setup-wizard-container .getting-started-wrapper .text,.aioseo-setup-wizard-container .getting-started-wrapper .video{flex-basis:100%;width:100%}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions{justify-content:center}.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:inherit;max-width:inherit;justify-content:center}}@media only screen and (max-width:782px){.aioseo-setup-wizard-container .getting-started-wrapper .wizard-actions .aioseo-col{flex-basis:100%;max-width:100%;justify-content:center}}.aioseo-setup-wizard-container .aioseo-row{position:relative;z-index:1}.aioseo-setup-wizard-container .wizard-actions .aioseo-col{display:flex;align-items:center}.aioseo-setup-wizard-container .wizard-actions .aioseo-button svg{width:16px;height:16px;margin-left:10px}.aioseo-setup-wizard-container .setup-wizard-bg{width:100%;height:100%;overflow:hidden;z-index:0;position:absolute;top:0;right:0}.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg,.aioseo-setup-wizard-container .setup-wizard-bg svg.aioseo-setup-wizard-bg rect{width:auto;height:100%}.aioseo-setup-wizard-container .close-wizard{color:#fff;width:20px;height:20px;position:absolute;left:20px;top:20px;z-index:1;display:flex;align-items:center;justify-content:center}.aioseo-setup-wizard-container .close-wizard:hover{color:#ccc}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close{width:12px;height:12px;cursor:pointer;color:#fff}.aioseo-setup-wizard-container .close-wizard svg.aioseo-close:hover{color:#dadada}.aioseo-setup-wizard-container p.how-to-get-started{margin:0}.aioseo-setup-wizard-container p.welcome-text{line-height:1.6}.aioseo-setup-wizard-container h2{color:#fff;line-height:1.4}.aioseo-setup-wizard-container a{color:#fff}.aioseo-setup-wizard-container svg.aioseo-book{width:20px;height:20px;margin:0 0 0 10px}.aioseo-setup-wizard-container .getting-started-video{padding-left:20px;margin-bottom:-60px;position:relative;height:0;padding-bottom:56.25%}.aioseo-setup-wizard-container .getting-started-video iframe{width:100%;height:100%;position:absolute;top:0;right:0}.aioseo-google-search-preview{padding:32px 30px;border:1px solid #e8e8eb}.aioseo-google-search-preview .domain{font-size:14px;line-height:1.3;color:#3c4043;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aioseo-google-search-preview .site-title{font-size:20px;line-height:1.3;color:#1a0dab;margin:3px 0}.aioseo-google-search-preview .meta-description{max-width:600px;font-size:14px;line-height:1.4;color:#52565a}.edit-post-sidebar .domain,.editor-post-publish-panel .domain{font-size:13px}.edit-post-sidebar .site-title,.editor-post-publish-panel .site-title{font-size:16px}.edit-post-sidebar .meta-description,.editor-post-publish-panel .meta-description{font-size:12px}.aioseo-modal-content .domain,.aioseo-modal-content .meta-description{font-size:14px}.aioseo-modal-content .site-title{font-size:20px}html:not([data-scroll="0"]) .aioseo-header{box-shadow:0 2px 5px rgba(0,0,0,.05);transition:box-shadow .6s}.aioseo-header{position:fixed;z-index:1051;top:0;left:0;right:0;background-color:#fff;height:72px;color:#141b38}.aioseo-header .mascot{width:35px;height:auto;margin-left:10px}.aioseo-header .aioseo-header-content{padding:0;display:flex;height:72px;align-items:center}.aioseo-header .aioseo-header-content a:focus{box-shadow:none}.aioseo-header .aioseo-header-content svg.aioseo-logo{height:26px;margin-left:10px}.aioseo-header .aioseo-header-content .spacer{display:inline-flex;width:26.25px;height:0;border:1px solid #d0d1d7;transform:rotate(72.26deg)}.aioseo-header .aioseo-header-content .page-name{display:inline-flex;margin-right:10px;font-size:18px;font-weight:400;flex:1 0 auto}.aioseo-header .aioseo-header-content .header-actions{display:flex}.aioseo-header .aioseo-header-content .header-actions .round{position:relative;background-color:#f3f4f5;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:10px;cursor:pointer;transition:background-color .2s ease}.aioseo-header .aioseo-header-content .header-actions .round svg{width:20px;height:20px}.aioseo-header .aioseo-header-content .header-actions .round:hover{background-color:#e5e7e9}.aioseo-header .aioseo-header-content .header-actions .number{position:absolute;background-color:#df2a4a;width:16px;height:16px;font-weight:600;font-size:10px;color:#fff;top:-8px;right:50%;transform:translateX(50%);margin:0;-webkit-animation:bounce 2s 5;animation:bounce 2s 5}.aioseo-header .aioseo-header-content .header-actions .number:hover{background-color:#df2a4a}@-webkit-keyframes bounce{0%,25%,50%,75%,to{transform:translateX(50%) translateY(0)}40%{transform:translateX(50%) translateY(-8px)}60%{transform:translateX(50%) translateY(-4px)}}@keyframes bounce{0%,25%,50%,75%,to{transform:translateX(50%) translateY(0)}40%{transform:translateX(50%) translateY(-8px)}60%{transform:translateX(50%) translateY(-4px)}}body.modal-open{overflow:hidden}.aioseo-help{display:block;position:fixed;top:0;bottom:0;right:0;left:0;height:100%;width:100vw;background-color:#fff;color:#8c8f9a;opacity:0;max-height:100vh;overflow-y:auto;transition:opacity .3s ease-in 0s;z-index:-999}.aioseo-help.visible{opacity:1;z-index:100000}.aioseo-help .aioseo-help-header{background:#fff;width:100%;height:60px;z-index:1;padding:20px;display:flex}.aioseo-help .aioseo-help-header>.logo{flex:1}.aioseo-help .aioseo-help-docs{margin-bottom:25px;display:none}.aioseo-help .aioseo-help-docs li{padding:0 4px 14px 0;margin:0}.aioseo-help .aioseo-help-docs .aioseo-help-docs-viewall{margin:10px 0 0}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs{display:none}.aioseo-help .aioseo-help-docs .aioseo-help-additional-docs.opened{display:block}.aioseo-help .aioseo-help-docs .icon .aioseo-description{width:20px;margin-top:0;position:relative;top:5px;right:-5px;color:#8c8f9a}.aioseo-help .help-content{background-color:#fff;width:100%;max-width:740px;margin:0 auto 50px;padding:0 20px;box-sizing:border-box;z-index:1}.aioseo-help .help-content .aioseo-help-category{border-top:1px solid #e8e8eb;margin:0}.aioseo-help .help-content .aioseo-help-category:last-child{border-bottom:1px solid #e8e8eb}.aioseo-help .help-content .aioseo-help-category header{display:block;position:relative;cursor:pointer;width:100%;height:68px}.aioseo-help .help-content .aioseo-help-category header .title{display:block;font-size:16px;color:#8c8f9a;font-weight:600;padding:23px 30px 23px 11px}.aioseo-help .help-content .aioseo-help-category .folder-open{position:absolute;top:24px;width:20px;height:20px;color:#8c8f9a}.aioseo-help .help-content .aioseo-help-category .dashicons-arrow-right-alt2{position:absolute;top:20px;left:0;transition:transform .3s ease-out}.aioseo-help .help-content .aioseo-help-category.opened .aioseo-help-docs{display:block}.aioseo-help .help-content .aioseo-help-category.opened .dashicons-arrow-right-alt2{transform:rotate(-90deg)}.aioseo-help .help-content #aioseo-help-search{position:relative;background-color:#fff;text-align:center;top:0;padding:20px 0 50px}.aioseo-help .help-content #aioseo-help-result .aioseo-help-docs{display:block}.aioseo-help .help-content #aioseo-help-footer{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;margin:50px 0 0}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer{display:block}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{box-sizing:border-box;max-width:325px;border:1px solid #8c8f9a;border-radius:6px;text-align:center}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block{max-width:100%}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin-left:20px}@media screen and (max-width:750px){.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block:first-child{margin:0 0 20px}}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a{display:block;padding:25px;text-decoration:none;color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a h3{color:#8c8f9a}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a span{font-size:16px;color:#005ae0;text-decoration:underline}.aioseo-help .help-content #aioseo-help-footer .aioseo-help-footer-block a:hover span{text-decoration:none}.aioseo-help .help-content #aioseo-help-footer .aioseo-description,.aioseo-help .help-content #aioseo-help-footer .aioseo-support{width:48px;margin-top:0;color:#8c8f9a}#aioseo-help-logo{width:132px;height:26px;z-index:2}#aioseo-help-close{width:20px;height:20px;cursor:pointer;opacity:.7;transition:all .05s;z-index:2}@media screen and (max-width:750px){#aioseo-help-close{top:20px;left:20px}}.aioseo-html-tags-editor .no-access{margin-bottom:20px}.aioseo-html-tags-editor .aioseo-description.tags-description{margin:0 0 20px}.aioseo-html-tags-editor .add-tags{display:flex;align-items:center;margin-bottom:20px}.aioseo-html-tags-editor .add-tags div{margin-left:10px}.aioseo-html-tags-editor .add-tags a{font-size:14px}.aioseo-html-tags-editor .add-tags a.no-underline{padding-right:10px}.aioseo-loading-spinner{width:35px;height:35px;position:absolute}.aioseo-loading-spinner .double-bounce1,.aioseo-loading-spinner .double-bounce2{width:100%;height:100%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;right:0;-webkit-animation:sk-bounce 1.3s ease-in-out infinite;animation:sk-bounce 1.3s ease-in-out infinite}.aioseo-loading-spinner.dark .double-bounce1,.aioseo-loading-spinner.dark .double-bounce2{background-color:#8c8f9a}.aioseo-loading-spinner .double-bounce2{-webkit-animation-delay:-.65s;animation-delay:-.65s}@-webkit-keyframes sk-bounce{0%,to{-webkit-transform:scale(0)}50%{-webkit-transform:scale(1)}}@keyframes sk-bounce{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}body.vue-build{margin:0}body.vue-build .aioseo-app{min-height:calc(100vh - 88px)}body.vue-build .aioseo-app .aioseo-main{padding-bottom:30px}body.aioseo-setup-wizard{margin:0;padding:0}body.aioseo-setup-wizard .aioseo-app{min-height:100vh;width:100%}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay{right:160px}body[class*=page_aioseo].folded .aioseo-header,body[class*=page_aioseo].folded .aioseo-notifications .overlay{right:36px}body[class*=page_aioseo] #wpcontent{padding:0;background-color:#f3f4f5}body[class*=page_aioseo] .update-nag{display:none}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 185px)}body[class*=page_aioseo].admin-bar.aioseo-has-bar .aioseo-app{min-height:calc(100vh - 225px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:32px}body[class*=page_aioseo] .aioseo-app{min-height:calc(100vh - 153px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-app{min-height:calc(100vh - 193px)}body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:112px}@media screen and (max-width:782px){body[class*=page_aioseo].aioseo-has-bar .aioseo-header{height:132px}}@media screen and (max-width:960px){body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{right:36px}}@media screen and (max-width:782px){body[class*=page_aioseo] #wpbody-content{padding-bottom:20px}body[class*=page_aioseo].admin-bar .aioseo-app{min-height:calc(100vh - 199px)}body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .notification-menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{top:46px}body[class*=page_aioseo] .aioseo-header,body[class*=page_aioseo] .aioseo-notifications .overlay,body[class*=page_aioseo].auto-fold .aioseo-header,body[class*=page_aioseo].auto-fold .aioseo-notifications .overlay{right:0}}@media screen and (max-width:600px){body[class*=page_aioseo].admin-bar .aioseo-header,body[class*=page_aioseo].admin-bar .aioseo-notifications .menu,body[class*=page_aioseo].admin-bar .aioseo-notifications .overlay{position:absolute;top:46px}}body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:128px}@media screen and (max-width:782px){body.aioseo-has-bar .aioseo-app .aioseo-main>.aioseo-container{margin-top:148px}}.aioseo-app{box-sizing:border-box;background-color:#f3f4f5}.aioseo-app .route-fade-enter-active,.aioseo-app .route-fade-leave-active{transition:all .2s}.aioseo-app .route-fade-enter,.aioseo-app .route-fade-leave-active{opacity:0}.aioseo-app .route-fade-enter{transform:translateX(-30px)}.aioseo-app .route-fade-leave-active{transform:translateX(30px)}.aioseo-app *,.aioseo-app :after,.aioseo-app :before{box-sizing:inherit}.aioseo-app * :not(.aioseo-button):not(.aioseo-input),.aioseo-app :after :not(.aioseo-button):not(.aioseo-input),.aioseo-app :before :not(.aioseo-button):not(.aioseo-input){line-height:1.4}.aioseo-app p{font-size:16px}.aioseo-app a:not(.aioseo-button){color:#005ae0}.aioseo-app a:not(.aioseo-button).text-white{color:#fff}.aioseo-app a:not(.aioseo-button).no-underline,.aioseo-app a:not(.aioseo-button):hover{text-decoration:none}.aioseo-app h2{font-size:32px;margin:0}.aioseo-app .aioseo-main{height:100%}.aioseo-app .aioseo-main>.aioseo-container{margin-top:88px}.aioseo-app .aioseo-main .save-changes{display:flex;justify-content:flex-end}.aioseo-app .d-flex{display:flex}.aioseo-app .aioseo-section-description{font-size:16px;color:#141b38;line-height:1.8;padding-bottom:30px}.aioseo-app .aioseo-description-text{font-size:14px;line-height:1.8;color:#141b38}.aioseo-app .aioseo-description-text.aioseo-error{color:#df2a4a}.aioseo-app .aioseo-description{font-size:14px;line-height:1.8;margin:8px 0 0;color:#141b38}.aioseo-app .aioseo-description.no-margin{margin:0}.aioseo-app .aioseo-description.aioseo-error{color:#df2a4a}.aioseo-app .max-recommended-count{color:#434960;text-align:left;margin-top:10px;font-size:14px}.aioseo-app .max-recommended-count strong.error{color:#df2a4a}.aioseo-app .popper{text-align:right;font-size:12px;padding:20px;background-color:#fff;border:none;border-radius:3px;box-shadow:0 3px 4.8px 0 rgba(32,71,102,.27);z-index:9999;max-width:350px;line-height:1.4}.aioseo-app .popper.action{padding:8px 12px;background-color:#141b38;color:#fff}.aioseo-app .popper.action .popper__arrow{border-top-color:#141b38}.aioseo-app .popper[x-placement^=bottom]{box-shadow:0 -2px 4.8px 0 rgba(32,71,102,.27)}.aioseo-app .popper .aioseo-description{margin:0}.aioseo-app .aioseo-row-highlight{-webkit-animation-name:color;animation-name:color;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-iteration-count:2;animation-iteration-count:2}@-webkit-keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}@keyframes color{0%{background-color:#fff}50%{background-color:#00aa63}to{background-color:#fff}}.column-aioseo-details{position:relative}.aioseo-seo-site-score .aioseo-blur{display:flex;align-items:center}.aioseo-seo-site-score .aioseo-seo-site-score-cta{position:absolute;right:50%;top:50%;transform:translateX(50%) translateY(-50%);background-color:#fff;padding:24px 30px;border:1px solid #e8e8eb;box-shadow:0 2px 10px rgba(0,90,224,.2);color:#141b38;font-size:16px;font-weight:600;width:82%;max-width:500px;text-align:center}.aioseo-app .aioseo-upgrade-bar{height:40px;background-color:#00aa63;display:flex;align-items:center;justify-content:center;color:#fff;font-size:13px;padding:0 40px 0 14px}.aioseo-app .aioseo-upgrade-bar .upgrade-text{display:flex;align-items:center;flex:1;justify-content:center}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow{font-size:15px;text-decoration:none}.aioseo-app .aioseo-upgrade-bar .upgrade-arrow:hover{text-decoration:none}.aioseo-app .aioseo-upgrade-bar strong{font-weight:600}.aioseo-app .aioseo-upgrade-bar svg.aioseo-logo-gear{width:20px;height:20px;min-width:20px;margin-left:14px}.aioseo-app .aioseo-upgrade-bar svg.aioseo-close{cursor:pointer;width:12px;height:12px}.aioseo-app .aioseo-upgrade-bar a{color:#fff;text-decoration:underline}.aioseo-app .aioseo-upgrade-bar a:hover{text-decoration:none}@media screen and (max-width:782px){.aioseo-app .aioseo-upgrade-bar{padding:0 10px;height:60px}}.field-description[data-v-2bfc1de2]{display:inline-block;margin-top:10px;font-size:14px}.aioseo-address-wrapper[data-v-4bc9bbe6]{display:flex;max-width:500px}.field-description[data-v-4bc9bbe6]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4bc9bbe6]{margin-top:8px}.field-description[data-v-a0a894b8]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-a0a894b8]{margin-top:8px}.field-description[data-v-4fb4e044]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-4fb4e044]{margin-top:8px}.field-description[data-v-85733554]{display:inline-block;margin-top:10px;font-size:14px}.field-description[data-v-515336a2]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-515336a2]{margin-top:8px}.field-description[data-v-78337de7]{display:inline-block;margin-bottom:10px;font-size:14px}.mt-8[data-v-78337de7]{margin-top:8px}.aioseo-general-settings .more-tooltip-text strong{color:#00aa63}.aioseo-general-settings .license-cta-box{border-radius:3px;background-color:#f2f7fd;padding:20px;max-width:630px;margin:10px 0 30px}.aioseo-general-settings .license-cta-box a{color:#00aa63}.aioseo-general-settings .license-cta-box div{font-weight:600}.aioseo-general-settings .license-cta-box span{font-size:14px;font-style:italic}.aioseo-general-settings .license-key{margin-top:10px;display:flex;max-width:560px}.aioseo-general-settings .license-key .aioseo-input{margin-left:10px}.aioseo-app .aioseo-tabs.internal{margin-bottom:0}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation{margin-top:5px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button{height:60px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 25px}.aioseo-app .aioseo-tabs.internal .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-ripple-wave{display:none}.aioseo-app .aioseo-tabs.skinny .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 16px}.aioseo-app .md-tabs{display:flex;flex-direction:column}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation{margin-top:2px;background:transparent;display:flex;position:relative;justify-content:flex-start}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation.md-elevation-0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button{color:#141b38;max-width:264px;min-width:72px;height:60px;margin:0;border-radius:0;font-size:15px;font-weight:500;padding:0;display:inline-block;position:relative;overflow:hidden;outline:none;background:transparent;border:0;transition:.4s cubic-bezier(.4,0,.2,1);font-family:inherit;line-height:normal;text-decoration:none;vertical-align:top;white-space:nowrap}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:before{position:absolute;top:0;left:0;bottom:0;right:0;opacity:0;transition:.4s cubic-bezier(.4,0,.2,1);will-change:background-color,opacity;content:" "}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple{padding:0 18px;display:flex;justify-content:center;align-items:center;width:100%;height:100%;position:relative;overflow:hidden;-webkit-mask-image:radial-gradient(circle,#fff 100%,#000 0);mask-image:radial-gradient(circle,#fff 100%,#000 0)}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button .md-ripple .md-button-content{position:static;z-index:2}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]){cursor:pointer}.aioseo-app .md-tabs.md-theme-default .md-tabs-navigation .md-button:not([disabled]):active:b