Yoast SEO - Version 14.0.3

Version Description

Release Date: April 30th, 2020

Bugfixes:

  • Fixes a bug where running the migrations could cause fatal errors on sites where plugins are installed remotely. Some remote plugin installers don't remove files that are removed in an update. Since our migration runner goes through all migrations on the server, this could lead to fatal errors.
  • Fixes a bug where the pre_get_document_title filter could be skipped when other plugins were using this filter as well.
  • Fixes a bug where an error would be thrown when the name of an indexable table had been converted to a different case.
  • Fixes a bug where a taxonomy parent would not be present in the breadcrumbs even though it was set in the breadcrumbs settings.

Enhancements:

  • Adds a missing index to the new indexables table. Props to @pagelypete.

Other:

  • Adds the wpseo_frontend_presentation filter that can be used by third-party plugins to easily alter all our meta output with 1 single filter.
Download this release

Release Info

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

Code changes from version 14.0.2 to 14.0.3

Files changed (120) hide show
  1. config/dependency-injection/services.php +1 -0
  2. css/dist/{admin-global-1402-rtl.css → admin-global-1403-rtl.css} +0 -0
  3. css/dist/{admin-global-1402.css → admin-global-1403.css} +0 -0
  4. css/dist/{adminbar-1402-rtl.css → adminbar-1403-rtl.css} +0 -0
  5. css/dist/{adminbar-1402.css → adminbar-1403.css} +0 -0
  6. css/dist/{alerts-1402-rtl.css → alerts-1403-rtl.css} +0 -0
  7. css/dist/{alerts-1402.css → alerts-1403.css} +0 -0
  8. css/dist/{dashboard-1402-rtl.css → dashboard-1403-rtl.css} +0 -0
  9. css/dist/{dashboard-1402.css → dashboard-1403.css} +0 -0
  10. css/dist/{edit-page-1402-rtl.css → edit-page-1403-rtl.css} +0 -0
  11. css/dist/{edit-page-1402.css → edit-page-1403.css} +0 -0
  12. css/dist/{featured-image-1402-rtl.css → featured-image-1403-rtl.css} +0 -0
  13. css/dist/{featured-image-1402.css → featured-image-1403.css} +0 -0
  14. css/dist/{filter-explanation-1402-rtl.css → filter-explanation-1403-rtl.css} +0 -0
  15. css/dist/{filter-explanation-1402.css → filter-explanation-1403.css} +0 -0
  16. css/dist/{inside-editor-1402-rtl.css → inside-editor-1403-rtl.css} +0 -0
  17. css/dist/{inside-editor-1402.css → inside-editor-1403.css} +0 -0
  18. css/dist/{metabox-1402-rtl.css → metabox-1403-rtl.css} +0 -0
  19. css/dist/{metabox-1402.css → metabox-1403.css} +0 -0
  20. css/dist/{metabox-primary-category-1402-rtl.css → metabox-primary-category-1403-rtl.css} +0 -0
  21. css/dist/{metabox-primary-category-1402.css → metabox-primary-category-1403.css} +0 -0
  22. css/dist/{monorepo-1402-rtl.css → monorepo-1403-rtl.css} +0 -0
  23. css/dist/{monorepo-1402.css → monorepo-1403.css} +0 -0
  24. css/dist/{search-appearance-1402-rtl.css → search-appearance-1403-rtl.css} +0 -0
  25. css/dist/{search-appearance-1402.css → search-appearance-1403.css} +0 -0
  26. css/dist/{structured-data-blocks-1402-rtl.css → structured-data-blocks-1403-rtl.css} +0 -0
  27. css/dist/{structured-data-blocks-1402.css → structured-data-blocks-1403.css} +0 -0
  28. css/dist/{toggle-switch-1402-rtl.css → toggle-switch-1403-rtl.css} +0 -0
  29. css/dist/{toggle-switch-1402.css → toggle-switch-1403.css} +0 -0
  30. css/dist/{wpseo-dismissible-1402-rtl.css → wpseo-dismissible-1403-rtl.css} +0 -0
  31. css/dist/{wpseo-dismissible-1402.css → wpseo-dismissible-1403.css} +0 -0
  32. css/dist/{yoast-components-1402-rtl.css → yoast-components-1403-rtl.css} +0 -0
  33. css/dist/{yoast-components-1402.css → yoast-components-1403.css} +0 -0
  34. css/dist/{yoast-extensions-1402-rtl.css → yoast-extensions-1403-rtl.css} +0 -0
  35. css/dist/{yoast-extensions-1402.css → yoast-extensions-1403.css} +0 -0
  36. css/dist/{yst_plugin_tools-1402-rtl.css → yst_plugin_tools-1403-rtl.css} +0 -0
  37. css/dist/{yst_plugin_tools-1402.css → yst_plugin_tools-1403.css} +0 -0
  38. css/dist/{yst_seo_score-1402-rtl.css → yst_seo_score-1403-rtl.css} +0 -0
  39. css/dist/{yst_seo_score-1402.css → yst_seo_score-1403.css} +0 -0
  40. deprecated/frontend/breadcrumbs.php +4 -1
  41. deprecated/frontend/frontend.php +31 -20
  42. inc/class-upgrade.php +41 -33
  43. js/dist/{analysis-1402.js → analysis-1403.js} +0 -0
  44. js/dist/{babel-polyfill-1402.js → babel-polyfill-1403.js} +0 -0
  45. js/dist/{commons-1402.js → commons-1403.js} +0 -0
  46. js/dist/{components-1402.js → components-1403.js} +0 -0
  47. js/dist/{configuration-wizard-1402.js → configuration-wizard-1403.js} +0 -0
  48. js/dist/{help-scout-beacon-1402.js → help-scout-beacon-1403.js} +0 -0
  49. js/dist/{jed-1402.js → jed-1403.js} +0 -0
  50. js/dist/{redux-1402.js → redux-1403.js} +0 -0
  51. js/dist/{search-appearance-1402.js → search-appearance-1403.js} +0 -0
  52. js/dist/{styled-components-1402.js → styled-components-1403.js} +0 -0
  53. js/dist/{wp-seo-admin-1402.js → wp-seo-admin-1403.js} +0 -0
  54. js/dist/{wp-seo-admin-global-1402.js → wp-seo-admin-global-1403.js} +0 -0
  55. js/dist/{wp-seo-admin-gsc-1402.js → wp-seo-admin-gsc-1403.js} +0 -0
  56. js/dist/{wp-seo-admin-media-1402.js → wp-seo-admin-media-1403.js} +0 -0
  57. js/dist/{wp-seo-analysis-worker-1402.js → wp-seo-analysis-worker-1403.js} +0 -0
  58. js/dist/{wp-seo-api-1402.js → wp-seo-api-1403.js} +0 -0
  59. js/dist/{wp-seo-bulk-editor-1402.js → wp-seo-bulk-editor-1403.js} +0 -0
  60. js/dist/{wp-seo-dashboard-widget-1402.js → wp-seo-dashboard-widget-1403.js} +0 -0
  61. js/dist/{wp-seo-edit-page-1402.js → wp-seo-edit-page-1403.js} +0 -0
  62. js/dist/{wp-seo-featured-image-1402.js → wp-seo-featured-image-1403.js} +0 -0
  63. js/dist/{wp-seo-filter-explanation-1402.js → wp-seo-filter-explanation-1403.js} +0 -0
  64. js/dist/{wp-seo-indexation-1402.js → wp-seo-indexation-1403.js} +0 -0
  65. js/dist/{wp-seo-metabox-1402.js → wp-seo-metabox-1403.js} +0 -0
  66. js/dist/{wp-seo-metabox-category-1402.js → wp-seo-metabox-category-1403.js} +0 -0
  67. js/dist/{wp-seo-modal-1402.js → wp-seo-modal-1403.js} +0 -0
  68. js/dist/{wp-seo-network-admin-1402.js → wp-seo-network-admin-1403.js} +0 -0
  69. js/dist/{wp-seo-post-scraper-1402.js → wp-seo-post-scraper-1403.js} +0 -0
  70. js/dist/{wp-seo-quick-edit-handler-1402.js → wp-seo-quick-edit-handler-1403.js} +0 -0
  71. js/dist/{wp-seo-recalculate-1402.js → wp-seo-recalculate-1403.js} +0 -0
  72. js/dist/{wp-seo-reindex-links-1402.js → wp-seo-reindex-links-1403.js} +0 -0
  73. js/dist/{wp-seo-replacevar-plugin-1402.js → wp-seo-replacevar-plugin-1403.js} +0 -0
  74. js/dist/{wp-seo-shortcode-plugin-1402.js → wp-seo-shortcode-plugin-1403.js} +0 -0
  75. js/dist/{wp-seo-structured-data-blocks-1402.js → wp-seo-structured-data-blocks-1403.js} +0 -0
  76. js/dist/{wp-seo-term-scraper-1402.js → wp-seo-term-scraper-1403.js} +0 -0
  77. js/dist/{wp-seo-used-keywords-assessment-1402.js → wp-seo-used-keywords-assessment-1403.js} +0 -0
  78. languages/wordpress-seo-ro_RO.json +1 -1
  79. languages/wordpress-seojs-ro_RO.json +1 -1
  80. lib/orm.php +3 -4
  81. lib/ruckusing-adapter.php +186 -56
  82. readme.txt +19 -1
  83. {migrations → src/config/migrations}/20171228151840_WpYoastIndexable.php +0 -0
  84. {migrations → src/config/migrations}/20171228151841_WpYoastPrimaryTerm.php +0 -0
  85. {migrations → src/config/migrations}/20190529075038_WpYoastDropIndexableMetaTableIfExists.php +0 -0
  86. {migrations → src/config/migrations}/20191011111109_WpYoastIndexableHierarchy.php +0 -0
  87. {migrations → src/config/migrations}/20200408101900_AddCollationToTables.php +0 -0
  88. {migrations → src/config/migrations}/20200420073606_AddColumnsToIndexables.php +0 -0
  89. {migrations → src/config/migrations}/20200428123747_BreadcrumbTitleAndHierarchyReset.php +0 -0
  90. {migrations → src/config/migrations}/20200428194858_ExpandIndexableColumnLengths.php +0 -0
  91. {migrations → src/config/migrations}/20200429105310_TruncateIndexableTables.php +0 -0
  92. src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php +56 -0
  93. {migrations → src/config/migrations}/ruckusing/lib/Ruckusing/Adapter/why +0 -0
  94. {migrations → src/config/migrations}/ruckusing/lib/Task/why +0 -0
  95. src/config/ruckusing-framework.php +1 -1
  96. src/generated/container.php +1 -1
  97. src/generators/breadcrumbs-generator.php +37 -6
  98. src/initializers/migration-runner.php +1 -1
  99. src/integrations/breadcrumbs-integration.php +4 -1
  100. src/integrations/front-end-integration.php +11 -2
  101. src/integrations/third-party/woocommerce.php +38 -3
  102. src/presenters/title-presenter.php +13 -0
  103. src/repositories/indexable-hierarchy-repository.php +4 -5
  104. src/repositories/indexable-repository.php +3 -5
  105. src/repositories/primary-term-repository.php +4 -6
  106. src/repositories/seo-links-repository.php +3 -5
  107. src/repositories/seo-meta-repository.php +4 -6
  108. src/routes/route-interface.php +1 -1
  109. src/surfaces/values/meta.php +9 -4
  110. vendor/autoload.php +1 -1
  111. vendor/autoload_52.php +0 -7
  112. vendor/composer/ClassLoader.php +4 -4
  113. vendor/composer/ClassLoader52.php +0 -271
  114. vendor/composer/autoload_classmap.php +10 -5
  115. vendor/composer/autoload_real.php +4 -7
  116. vendor/composer/autoload_real_52.php +0 -58
  117. vendor/composer/autoload_static.php +14 -9
  118. vendor_prefixed/j4mie/idiorm/idiorm.php +0 -2415
  119. wp-seo-main.php +1 -1
  120. wp-seo.php +1 -1
config/dependency-injection/services.php CHANGED
@@ -44,6 +44,7 @@ $excluded_directories = [
44
  'backwards-compatibility',
45
  'surfaces/values',
46
  'presenters',
 
47
  ];
48
 
49
  $excluded = \implode( ',', \array_merge( $excluded_directories, $excluded_files ) );
44
  'backwards-compatibility',
45
  'surfaces/values',
46
  'presenters',
47
+ 'config/migrations',
48
  ];
49
 
50
  $excluded = \implode( ',', \array_merge( $excluded_directories, $excluded_files ) );
css/dist/{admin-global-1402-rtl.css → admin-global-1403-rtl.css} RENAMED
File without changes
css/dist/{admin-global-1402.css → admin-global-1403.css} RENAMED
File without changes
css/dist/{adminbar-1402-rtl.css → adminbar-1403-rtl.css} RENAMED
File without changes
css/dist/{adminbar-1402.css → adminbar-1403.css} RENAMED
File without changes
css/dist/{alerts-1402-rtl.css → alerts-1403-rtl.css} RENAMED
File without changes
css/dist/{alerts-1402.css → alerts-1403.css} RENAMED
File without changes
css/dist/{dashboard-1402-rtl.css → dashboard-1403-rtl.css} RENAMED
File without changes
css/dist/{dashboard-1402.css → dashboard-1403.css} RENAMED
File without changes
css/dist/{edit-page-1402-rtl.css → edit-page-1403-rtl.css} RENAMED
File without changes
css/dist/{edit-page-1402.css → edit-page-1403.css} RENAMED
File without changes
css/dist/{featured-image-1402-rtl.css → featured-image-1403-rtl.css} RENAMED
File without changes
css/dist/{featured-image-1402.css → featured-image-1403.css} RENAMED
File without changes
css/dist/{filter-explanation-1402-rtl.css → filter-explanation-1403-rtl.css} RENAMED
File without changes
css/dist/{filter-explanation-1402.css → filter-explanation-1403.css} RENAMED
File without changes
css/dist/{inside-editor-1402-rtl.css → inside-editor-1403-rtl.css} RENAMED
File without changes
css/dist/{inside-editor-1402.css → inside-editor-1403.css} RENAMED
File without changes
css/dist/{metabox-1402-rtl.css → metabox-1403-rtl.css} RENAMED
File without changes
css/dist/{metabox-1402.css → metabox-1403.css} RENAMED
File without changes
css/dist/{metabox-primary-category-1402-rtl.css → metabox-primary-category-1403-rtl.css} RENAMED
File without changes
css/dist/{metabox-primary-category-1402.css → metabox-primary-category-1403.css} RENAMED
File without changes
css/dist/{monorepo-1402-rtl.css → monorepo-1403-rtl.css} RENAMED
File without changes
css/dist/{monorepo-1402.css → monorepo-1403.css} RENAMED
File without changes
css/dist/{search-appearance-1402-rtl.css → search-appearance-1403-rtl.css} RENAMED
File without changes
css/dist/{search-appearance-1402.css → search-appearance-1403.css} RENAMED
File without changes
css/dist/{structured-data-blocks-1402-rtl.css → structured-data-blocks-1403-rtl.css} RENAMED
File without changes
css/dist/{structured-data-blocks-1402.css → structured-data-blocks-1403.css} RENAMED
File without changes
css/dist/{toggle-switch-1402-rtl.css → toggle-switch-1403-rtl.css} RENAMED
File without changes
css/dist/{toggle-switch-1402.css → toggle-switch-1403.css} RENAMED
File without changes
css/dist/{wpseo-dismissible-1402-rtl.css → wpseo-dismissible-1403-rtl.css} RENAMED
File without changes
css/dist/{wpseo-dismissible-1402.css → wpseo-dismissible-1403.css} RENAMED
File without changes
css/dist/{yoast-components-1402-rtl.css → yoast-components-1403-rtl.css} RENAMED
File without changes
css/dist/{yoast-components-1402.css → yoast-components-1403.css} RENAMED
File without changes
css/dist/{yoast-extensions-1402-rtl.css → yoast-extensions-1403-rtl.css} RENAMED
File without changes
css/dist/{yoast-extensions-1402.css → yoast-extensions-1403.css} RENAMED
File without changes
css/dist/{yst_plugin_tools-1402-rtl.css → yst_plugin_tools-1403-rtl.css} RENAMED
File without changes
css/dist/{yst_plugin_tools-1402.css → yst_plugin_tools-1403.css} RENAMED
File without changes
css/dist/{yst_seo_score-1402-rtl.css → yst_seo_score-1403-rtl.css} RENAMED
File without changes
css/dist/{yst_seo_score-1402.css → yst_seo_score-1403.css} RENAMED
File without changes
deprecated/frontend/breadcrumbs.php CHANGED
@@ -131,7 +131,10 @@ class WPSEO_Breadcrumbs {
131
  */
132
  private function render() {
133
  $presenter = new Breadcrumbs_Presenter();
134
- $presenter->presentation = $this->context_memoizer->for_current_page()->presentation;
 
 
 
135
  $presenter->replace_vars = $this->replace_vars;
136
  $presenter->helpers = $this->helpers;
137
 
131
  */
132
  private function render() {
133
  $presenter = new Breadcrumbs_Presenter();
134
+ $context = $this->context_memoizer->for_current_page();
135
+ /** This filter is documented in src/integrations/front-end-integration.php */
136
+ $presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context );
137
+ $presenter->presentation = $presentation;
138
  $presenter->replace_vars = $this->replace_vars;
139
  $presenter->helpers = $this->helpers;
140
 
deprecated/frontend/frontend.php CHANGED
@@ -108,13 +108,14 @@ class WPSEO_Frontend {
108
  public function canonical( $echo = true, $un_paged = false, $no_override = false ) {
109
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
110
 
111
- $context = $this->context_memoizer->for_current_page();
112
  if ( ! $echo ) {
113
- return $context->presentation->canonical;
114
  }
115
 
116
  $presenter = new Canonical_Presenter();
117
- $presenter->presentation = $context->presentation;
 
118
  $presenter->helpers = $this->helpers;
119
  $presenter->replace_vars = $this->replace_vars;
120
  echo $presenter->present();
@@ -128,9 +129,8 @@ class WPSEO_Frontend {
128
  public function get_robots() {
129
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
130
 
131
- $context = $this->context_memoizer->for_current_page();
132
-
133
- return $context->presentation->robots;
134
  }
135
 
136
  /**
@@ -139,9 +139,9 @@ class WPSEO_Frontend {
139
  public function robots() {
140
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
141
 
142
- $context = $this->context_memoizer->for_current_page();
143
- $presenter = new Robots_Presenter();
144
- $presenter->presentation = $context->presentation;
145
  $presenter->helpers = $this->helpers;
146
  $presenter->replace_vars = $this->replace_vars;
147
  echo $presenter->present();
@@ -158,9 +158,9 @@ class WPSEO_Frontend {
158
  public function robots_for_single_post( $robots, $post_id = 0 ) {
159
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
160
 
161
- $context = $this->context_memoizer->for_current_page();
162
 
163
- return $context->presentation->robots;
164
  }
165
 
166
  /**
@@ -173,10 +173,10 @@ class WPSEO_Frontend {
173
  private function get_title( $object = null ) {
174
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
175
 
176
- $context = $this->context_memoizer->for_current_page();
177
- $title = $context->presentation->title;
178
 
179
- return $this->replace_vars->replace( $title, $context->presentation->source );
180
  }
181
 
182
  /**
@@ -222,16 +222,16 @@ class WPSEO_Frontend {
222
  public function adjacent_rel_links() {
223
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
224
 
225
- $context = $this->context_memoizer->for_current_page();
226
 
227
  $rel_prev_presenter = new Rel_Prev_Presenter();
228
- $rel_prev_presenter->presentation = $context->presentation;
229
  $rel_prev_presenter->helpers = $this->helpers;
230
  $rel_prev_presenter->replace_vars = $this->replace_vars;
231
  echo $rel_prev_presenter->present();
232
 
233
  $rel_next_presenter = new Rel_Next_Presenter();
234
- $rel_next_presenter->presentation = $context->presentation;
235
  $rel_next_presenter->helpers = $this->helpers;
236
  $rel_next_presenter->replace_vars = $this->replace_vars;
237
  echo $rel_next_presenter->present();
@@ -247,16 +247,27 @@ class WPSEO_Frontend {
247
  public function metadesc( $echo = true ) {
248
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
249
 
250
- $context = $this->context_memoizer->for_current_page();
251
 
252
  if ( ! $echo ) {
253
- return $context->presentation->meta_description;
254
  }
255
 
256
  $presenter = new Meta_Description_Presenter();
257
- $presenter->presentation = $context->presentation;
258
  $presenter->helpers = $this->helpers;
259
  $presenter->replace_vars = $this->replace_vars;
260
  $presenter->present();
261
  }
 
 
 
 
 
 
 
 
 
 
 
262
  }
108
  public function canonical( $echo = true, $un_paged = false, $no_override = false ) {
109
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
110
 
111
+ $presentation = $this->get_current_page_presentation();
112
  if ( ! $echo ) {
113
+ return $presentation->canonical;
114
  }
115
 
116
  $presenter = new Canonical_Presenter();
117
+ /** This filter is documented in src/integrations/front-end-integration.php */
118
+ $presenter->presentation = $presentation;
119
  $presenter->helpers = $this->helpers;
120
  $presenter->replace_vars = $this->replace_vars;
121
  echo $presenter->present();
129
  public function get_robots() {
130
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
131
 
132
+ $presentation = $this->get_current_page_presentation();
133
+ return $presentation->robots;
 
134
  }
135
 
136
  /**
139
  public function robots() {
140
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
141
 
142
+ $presentation = $this->get_current_page_presentation();
143
+ $presenter = new Robots_Presenter();
144
+ $presenter->presentation = $presentation;
145
  $presenter->helpers = $this->helpers;
146
  $presenter->replace_vars = $this->replace_vars;
147
  echo $presenter->present();
158
  public function robots_for_single_post( $robots, $post_id = 0 ) {
159
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
160
 
161
+ $presentation = $this->get_current_page_presentation();
162
 
163
+ return $presentation->robots;
164
  }
165
 
166
  /**
173
  private function get_title( $object = null ) {
174
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
175
 
176
+ $presentation = $this->get_current_page_presentation();
177
+ $title = $presentation->title;
178
 
179
+ return $this->replace_vars->replace( $title, $presentation->source );
180
  }
181
 
182
  /**
222
  public function adjacent_rel_links() {
223
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
224
 
225
+ $presentation = $this->get_current_page_presentation();
226
 
227
  $rel_prev_presenter = new Rel_Prev_Presenter();
228
+ $rel_prev_presenter->presentation = $presentation;
229
  $rel_prev_presenter->helpers = $this->helpers;
230
  $rel_prev_presenter->replace_vars = $this->replace_vars;
231
  echo $rel_prev_presenter->present();
232
 
233
  $rel_next_presenter = new Rel_Next_Presenter();
234
+ $rel_next_presenter->presentation = $presentation;
235
  $rel_next_presenter->helpers = $this->helpers;
236
  $rel_next_presenter->replace_vars = $this->replace_vars;
237
  echo $rel_next_presenter->present();
247
  public function metadesc( $echo = true ) {
248
  _deprecated_function( __METHOD__, 'WPSEO 14.0' );
249
 
250
+ $presentation = $this->get_current_page_presentation();
251
 
252
  if ( ! $echo ) {
253
+ return $presentation->meta_description;
254
  }
255
 
256
  $presenter = new Meta_Description_Presenter();
257
+ $presenter->presentation = $presentation;
258
  $presenter->helpers = $this->helpers;
259
  $presenter->replace_vars = $this->replace_vars;
260
  $presenter->present();
261
  }
262
+
263
+ /**
264
+ * Returns the current page presentation.
265
+ *
266
+ * @return Indexable_Presentation The current page presentation.
267
+ */
268
+ private function get_current_page_presentation() {
269
+ $context = $this->context_memoizer->for_current_page();
270
+ /** This filter is documented in src/integrations/front-end-integration.php */
271
+ return \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context );
272
+ }
273
  }
inc/class-upgrade.php CHANGED
@@ -19,40 +19,41 @@ class WPSEO_Upgrade {
19
  WPSEO_Options::maybe_set_multisite_defaults( false );
20
 
21
  $routines = [
22
- '1.5.0' => 'upgrade_15',
23
- '2.0' => 'upgrade_20',
24
- '2.1' => 'upgrade_21',
25
- '2.2' => 'upgrade_22',
26
- '2.3' => 'upgrade_23',
27
- '3.0' => 'upgrade_30',
28
- '3.3' => 'upgrade_33',
29
- '3.6' => 'upgrade_36',
30
- '4.0' => 'upgrade_40',
31
- '4.4' => 'upgrade_44',
32
- '4.7' => 'upgrade_47',
33
- '4.9' => 'upgrade_49',
34
- '5.0' => 'upgrade_50',
35
- '5.1' => 'upgrade_50_51',
36
- '5.5' => 'upgrade_55',
37
- '5.6' => 'upgrade_56',
38
- '6.1' => 'upgrade_61',
39
- '6.3' => 'upgrade_63',
40
- '7.0-RC0' => 'upgrade_70',
41
- '7.1-RC0' => 'upgrade_71',
42
- '7.3-RC0' => 'upgrade_73',
43
- '7.4-RC0' => 'upgrade_74',
44
- '7.5.3' => 'upgrade_753',
45
- '7.7-RC0' => 'upgrade_77',
46
- '7.7.2-RC0' => 'upgrade_772',
47
- '9.0-RC0' => 'upgrade_90',
48
- '10.0-RC0' => 'upgrade_100',
49
- '11.1-RC0' => 'upgrade_111',
50
  /** Reset notifications because we removed the AMP Glue plugin notification */
51
- '12.1-RC0' => 'clean_all_notifications',
52
- '12.3-RC0' => 'upgrade_123',
53
- '12.4-RC0' => 'upgrade_124',
54
- '12.8-RC0' => 'upgrade_128',
55
- '13.2-RC0' => 'upgrade_132',
 
56
  ];
57
 
58
  array_walk( $routines, [ $this, 'run_upgrade_routine' ], $version );
@@ -728,6 +729,13 @@ class WPSEO_Upgrade {
728
  WPSEO_Capability_Manager_Factory::get()->add();
729
  }
730
 
 
 
 
 
 
 
 
731
  /**
732
  * Removes all notifications saved in the database under 'wp_yoast_notifications'.
733
  *
19
  WPSEO_Options::maybe_set_multisite_defaults( false );
20
 
21
  $routines = [
22
+ '1.5.0' => 'upgrade_15',
23
+ '2.0' => 'upgrade_20',
24
+ '2.1' => 'upgrade_21',
25
+ '2.2' => 'upgrade_22',
26
+ '2.3' => 'upgrade_23',
27
+ '3.0' => 'upgrade_30',
28
+ '3.3' => 'upgrade_33',
29
+ '3.6' => 'upgrade_36',
30
+ '4.0' => 'upgrade_40',
31
+ '4.4' => 'upgrade_44',
32
+ '4.7' => 'upgrade_47',
33
+ '4.9' => 'upgrade_49',
34
+ '5.0' => 'upgrade_50',
35
+ '5.1' => 'upgrade_50_51',
36
+ '5.5' => 'upgrade_55',
37
+ '5.6' => 'upgrade_56',
38
+ '6.1' => 'upgrade_61',
39
+ '6.3' => 'upgrade_63',
40
+ '7.0-RC0' => 'upgrade_70',
41
+ '7.1-RC0' => 'upgrade_71',
42
+ '7.3-RC0' => 'upgrade_73',
43
+ '7.4-RC0' => 'upgrade_74',
44
+ '7.5.3' => 'upgrade_753',
45
+ '7.7-RC0' => 'upgrade_77',
46
+ '7.7.2-RC0' => 'upgrade_772',
47
+ '9.0-RC0' => 'upgrade_90',
48
+ '10.0-RC0' => 'upgrade_100',
49
+ '11.1-RC0' => 'upgrade_111',
50
  /** Reset notifications because we removed the AMP Glue plugin notification */
51
+ '12.1-RC0' => 'clean_all_notifications',
52
+ '12.3-RC0' => 'upgrade_123',
53
+ '12.4-RC0' => 'upgrade_124',
54
+ '12.8-RC0' => 'upgrade_128',
55
+ '13.2-RC0' => 'upgrade_132',
56
+ '14.0.3-RC0' => 'upgrade_1403',
57
  ];
58
 
59
  array_walk( $routines, [ $this, 'run_upgrade_routine' ], $version );
729
  WPSEO_Capability_Manager_Factory::get()->add();
730
  }
731
 
732
+ /**
733
+ * Perform the 14.0.3 upgrade.
734
+ */
735
+ private function upgrade_1403() {
736
+ WPSEO_Options::set( 'ignore_indexation_warning', false );
737
+ }
738
+
739
  /**
740
  * Removes all notifications saved in the database under 'wp_yoast_notifications'.
741
  *
js/dist/{analysis-1402.js → analysis-1403.js} RENAMED
File without changes
js/dist/{babel-polyfill-1402.js → babel-polyfill-1403.js} RENAMED
File without changes
js/dist/{commons-1402.js → commons-1403.js} RENAMED
File without changes
js/dist/{components-1402.js → components-1403.js} RENAMED
File without changes
js/dist/{configuration-wizard-1402.js → configuration-wizard-1403.js} RENAMED
File without changes
js/dist/{help-scout-beacon-1402.js → help-scout-beacon-1403.js} RENAMED
File without changes
js/dist/{jed-1402.js → jed-1403.js} RENAMED
File without changes
js/dist/{redux-1402.js → redux-1403.js} RENAMED
File without changes
js/dist/{search-appearance-1402.js → search-appearance-1403.js} RENAMED
File without changes
js/dist/{styled-components-1402.js → styled-components-1403.js} RENAMED
File without changes
js/dist/{wp-seo-admin-1402.js → wp-seo-admin-1403.js} RENAMED
File without changes
js/dist/{wp-seo-admin-global-1402.js → wp-seo-admin-global-1403.js} RENAMED
File without changes
js/dist/{wp-seo-admin-gsc-1402.js → wp-seo-admin-gsc-1403.js} RENAMED
File without changes
js/dist/{wp-seo-admin-media-1402.js → wp-seo-admin-media-1403.js} RENAMED
File without changes
js/dist/{wp-seo-analysis-worker-1402.js → wp-seo-analysis-worker-1403.js} RENAMED
File without changes
js/dist/{wp-seo-api-1402.js → wp-seo-api-1403.js} RENAMED
File without changes
js/dist/{wp-seo-bulk-editor-1402.js → wp-seo-bulk-editor-1403.js} RENAMED
File without changes
js/dist/{wp-seo-dashboard-widget-1402.js → wp-seo-dashboard-widget-1403.js} RENAMED
File without changes
js/dist/{wp-seo-edit-page-1402.js → wp-seo-edit-page-1403.js} RENAMED
File without changes
js/dist/{wp-seo-featured-image-1402.js → wp-seo-featured-image-1403.js} RENAMED
File without changes
js/dist/{wp-seo-filter-explanation-1402.js → wp-seo-filter-explanation-1403.js} RENAMED
File without changes
js/dist/{wp-seo-indexation-1402.js → wp-seo-indexation-1403.js} RENAMED
File without changes
js/dist/{wp-seo-metabox-1402.js → wp-seo-metabox-1403.js} RENAMED
File without changes
js/dist/{wp-seo-metabox-category-1402.js → wp-seo-metabox-category-1403.js} RENAMED
File without changes
js/dist/{wp-seo-modal-1402.js → wp-seo-modal-1403.js} RENAMED
File without changes
js/dist/{wp-seo-network-admin-1402.js → wp-seo-network-admin-1403.js} RENAMED
File without changes
js/dist/{wp-seo-post-scraper-1402.js → wp-seo-post-scraper-1403.js} RENAMED
File without changes
js/dist/{wp-seo-quick-edit-handler-1402.js → wp-seo-quick-edit-handler-1403.js} RENAMED
File without changes
js/dist/{wp-seo-recalculate-1402.js → wp-seo-recalculate-1403.js} RENAMED
File without changes
js/dist/{wp-seo-reindex-links-1402.js → wp-seo-reindex-links-1403.js} RENAMED
File without changes
js/dist/{wp-seo-replacevar-plugin-1402.js → wp-seo-replacevar-plugin-1403.js} RENAMED
File without changes
js/dist/{wp-seo-shortcode-plugin-1402.js → wp-seo-shortcode-plugin-1403.js} RENAMED
File without changes
js/dist/{wp-seo-structured-data-blocks-1402.js → wp-seo-structured-data-blocks-1403.js} RENAMED
File without changes
js/dist/{wp-seo-term-scraper-1402.js → wp-seo-term-scraper-1403.js} RENAMED
File without changes
js/dist/{wp-seo-used-keywords-assessment-1402.js → wp-seo-used-keywords-assessment-1403.js} RENAMED
File without changes
languages/wordpress-seo-ro_RO.json CHANGED
@@ -1 +1 @@
1
- {"domain":"wordpress-seo","locale_data":{"wordpress-seo":{"":{"domain":"wordpress-seo","plural-forms":"nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);","lang":"ro"},"Google preview":["Previzualizare Google"],"Has feedback":["Are impresii"],"Content optimization:":["Optimizare conținut:"],"%1$sFlesch Reading Ease%2$s: The copy scores %3$s in the test, which is considered %4$s to read. %5$s":["%1$sCât de ușor este citit (Flesch Reading Ease)%2$s: textul a primit punctajul %3$s la efectuarea testului, este considerat %4$s de citit. %5$s"],"%3$sImage alt attributes%5$s: Out of %2$d images on this page, %1$d have alt attributes with words from your keyphrase or synonyms. That's a bit much. %4$sOnly include the keyphrase or its synonyms when it really fits the image%5$s.":["%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, %1$d au atribute alt care cu cuvinte din fraza cheie sau sinonimele ei. E un pic cam mult. %4$sInclude numai fraza cheie sau sinonimele ei când chiar se potrivesc cu imaginea%5$s."],"%1$sImage alt attributes%2$s: Good job!":["%1$sAtribute alt imagini%2$s: Foarte bine!"],"%3$sImage alt attributes%5$s: Out of %2$d images on this page, only %1$d has an alt attribute that reflects the topic of your text. %4$sAdd your keyphrase or synonyms to the alt tags of more relevant images%5$s!":["%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, numai una are un atribut alt care reflectă subiectul textului. %4$sAdaugă fraza cheie sau sinonimele ei la tagurile alt pentru mai multe imagini relevante%5$s!","%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, numai %1$d au atribute alt care reflectă subiectul textului. %4$sAdaugă fraza cheie sau sinonimele ei la tagurile alt pentru mai multe imagini relevante%5$s!","%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, numai %1$d au atribute alt care reflectă subiectul textului. %4$sAdaugă fraza cheie sau sinonimele ei la tagurile alt pentru mai multe imagini relevante%5$s!"],"%1$sImage alt attributes%3$s: Images on this page do not have alt attributes that reflect the topic of your text. %2$sAdd your keyphrase or synonyms to the alt tags of relevant images%3$s!":["%1$sAtribute alt imagini%3$s: imaginile din această pagină nu au atribute alt care să reflecte subiectul textului. %2$sAdaugă fraza cheie sau sinonimele ei la tagurile alt ale imaginilor relevante%3$s!"],"%1$sImage alt attributes%3$s: Images on this page have alt attributes, but you have not set your keyphrase. %2$sFix that%3$s!":["%1$sAtribute alt imagini%3$s: imaginile din această pagină au atribute alt, dar nu ai setat o frază cheie. %2$sCorectează asta%3$s!"],"%1$sKeyphrase in subheading%2$s: %3$s of your higher-level subheadings reflects the topic of your copy. Good job!":["%1$sFrază cheie în subtitluri%2$s: unul dintre subtitlurile tale reflectă subiectul textului. Foarte bine!","%1$sFrază cheie în subtitluri%2$s: %3$s dintre subtitlurile tale reflectă subiectul textului. Foarte bine!","%1$sFrază cheie în subtitluri%2$s: %3$s dintre subtitlurile tale reflectă subiectul textului. Foarte bine!"],"%1$sKeyphrase in subheading%2$s: Your higher-level subheading reflects the topic of your copy. Good job!":["%1$sFrază cheie în subtitluri%2$s: subtitlul tău reflectă subiectul textului. Foarte bine!"],"%1$sKeyphrase in subheading%3$s: %2$sUse more keyphrases or synonyms in your higher-level subheadings%3$s!":["%1$sFrază cheie în subtitluri%3$s: %2$sfolosește mai multe fraze cheie sau sinonimele ei în subtitluri%3$s!"],"%1$sSingle title%3$s: H1s should only be used as your main title. Find all H1s in your text that aren't your main title and %2$schange them to a lower heading level%3$s!":["%1$sNumai un titlu%3$s: H1 ar trebui să fie folosit numai pentru titlul principal. Găsește toate subtitlurile H1 din text care nu sunt folosite ca titlu principal și %2$smodifică-le în subtitluri inferioare (H2, H3...)%3$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found 0 times. That's less than the recommended minimum of %3$d times for a text of this length. %4$sFocus on your keyphrase%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie nu a fost găsită. Este sub minimul recomandat de %3$d ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %5$d time. That's less than the recommended minimum of %3$d times for a text of this length. %4$sFocus on your keyphrase%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Este sub minimul recomandat de %3$d ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d ori. Este sub minimul recomandat de %3$d ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d de ori. Este sub minimul recomandat de %3$d de ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %3$d time. This is great!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Foarte bine!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %3$d ori. Foarte bine!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %3$d de ori. Foarte bine!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %5$d time. That's more than the recommended maximum of %3$d times for a text of this length. %4$sDon't overoptimize%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Este peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d ori. Este peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d de ori. Este peste maximul recomandat de %3$d de ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %5$d time. That's way more than the recommended maximum of %3$d times for a text of this length. %4$sDon't overoptimize%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Este cu mult peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d ori. Este cu mult peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d de ori. Este cu mult peste maximul recomandat de %3$d de ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!"],"%1$sFunction words in keyphrase%3$s: Your keyphrase \"%4$s\" contains function words only. %2$sLearn more about what makes a good keyphrase.%3$s":["%1$sDeterminanți în fraza cheie%3$s: fraza ta cheie „%4$s” conține numai determinanți. %2$sAflă mai multe despre cum se alcătuiește o frază cheie bună.%3$s"],"%1$sKeyphrase length%3$s: %2$sSet a keyphrase in order to calculate your SEO score%3$s.":["%1$sLungime frază cheie%3$s: %2$sintrodu o frază cheie pentru a calcula punctajul SEO%3$s."],"%1$sKeyphrase in slug%2$s: More than half of your keyphrase appears in the slug. That's great!":["%1$sFrază cheie în descriptor%2$s: mai mult de jumătate din fraza ta cheie apare în descriptor. Foarte bine!"],"%1$sKeyphrase in slug%3$s: (Part of) your keyphrase does not appear in the slug. %2$sChange that%3$s!":["%1$sFrază cheie în descriptor%3$s: fraza ta cheie (sau o parte din ea) nu apare în descriptor. %2$sCorectează asta%3$s!"],"%1$sKeyphrase in slug%2$s: Great work!":["%1$sFrază cheie în descriptor%2$s: foarte bine!"],"%1$sKeyphrase in title%3$s: Not all the words from your keyphrase \"%4$s\" appear in the SEO title. %2$sTry to use the exact match of your keyphrase in the SEO title%3$s.":["%1$sFrază cheie în titlu%3$s: în titlul SEO nu apar toate cuvintele din fraza ta cheie „%4$s”. %2$sÎncearcă să folosești în titlul SEO chiar fraza cheie%3$s."],"%1$sKeyphrase in title%3$s: Does not contain the exact match. %2$sTry to write the exact match of your keyphrase in the SEO title%3$s.":["%1$sFrază cheie în titlu%3$s: titlul nu conține fraza cheie. %2$sÎncearcă să scrii în titlul SEO chiar fraza cheie%3$s."],"%1$sKeyphrase in title%3$s: The exact match of the keyphrase appears in the SEO title, but not at the beginning. %2$sTry to move it to the beginning%3$s.":["%1$sFrază cheie în titlu%3$s: fraza cheie apare în titlul SEO, dar nu este la începutul lui. %2$sÎncearcă să o muți la începutul titlului%3$s."],"%1$sKeyphrase in title%2$s: The exact match of the keyphrase appears at the beginning of the SEO title. Good job!":["%1$sFrază cheie în titlu%2$s: fraza cheie apare la începutul titlului SEO. Foarte bine!"],"%1$sKeyphrase distribution%2$s: Good job!":["%1$sDistribuție frază cheie%2$s: foarte bine!"],"%1$sKeyphrase distribution%3$s: Uneven. Some parts of your text do not contain the keyphrase or its synonyms. %2$sDistribute them more evenly%3$s.":["%1$sDistribuție frază cheie%3$s: inegală. Unele părți ale textului nu conțin fraza cheie sau sinonimele ei. %2$sDistribuie fraza cheie uniform%3$s."],"%1$sKeyphrase distribution%3$s: Very uneven. Large parts of your text do not contain the keyphrase or its synonyms. %2$sDistribute them more evenly%3$s.":["%1$sDistribuție frază cheie%3$s: inegală. Părți mari de text nu conțin fraza cheie sau sinonimele ei. %2$sDistribuie fraza cheie uniform%3$s."],"%1$sKeyphrase distribution%3$s: %2$sInclude your keyphrase or its synonyms in the text so that we can check keyphrase distribution%3$s.":["%1$sDistribuție frază cheie%3$s: %2$sinclude fraza cheie sau sinonimele ei în text ca să putem verifica distribuția ei (lor)%3$s."],"%4$sPreviously used keyphrase%6$s: You've used this keyphrase %1$s%2$d times before%3$s. %5$sDo not use your keyphrase more than once%6$s.":["%4$sFrază cheie folosită anterior%6$s: ai folosit această frază cheie de %1$s%2$d ori mai înainte%3$s. %5$sFolosește o frază cheie numai o singură dată%6$s."],"%3$sPreviously used keyphrase%5$s: You've used this keyphrase %1$sonce before%2$s. %4$sDo not use your keyphrase more than once%5$s.":["%3$sFrază cheie folosită anterior%5$s: ai folosit această frază cheie %1$saltădată, mai înainte%2$s. %4$sFolosește o frază cheie numai o singură dată%5$s."],"%1$sPreviously used keyphrase%2$s: You've not used this keyphrase before, very good.":["%1$sFrază cheie folosită anterior%2$s: nu ai mai folosit această frază cheie, foarte bine."],"%1$sSlug stopwords%3$s: The slug for this page contains a stop word. %2$sRemove it%3$s!":["%1$sCuvinte stop în descriptor%3$s: descriptorul acestei pagini conține un cuvânt stop. %2$sÎnlătură-l%3$s!","%1$sCuvinte stop în descriptor%3$s: descriptorul acestei pagini conține cuvinte stop. %2$sÎnlătură-le%3$s!","%1$sCuvinte stop în descriptor%3$s: descriptorul acestei pagini conține cuvinte stop. %2$sÎnlătură-le%3$s!"],"%1$sSlug too long%3$s: the slug for this page is a bit long. %2$sShorten it%3$s!":["%1$sDescriptor prea lung%3$s: descriptorul acestei pagini este un pic prea lung. %2$sScurtează-l%3$s!"],"%1$sImage alt attributes%3$s: No images appear on this page. %2$sAdd some%3$s!":["%1$sAtribute alt imagini%3$s: nu apare nicio imagine în această pagină. %2$sAdaugă cel puțin una%3$s!"],"%1$sLink keyphrase%3$s: You're linking to another page with the words you want this page to rank for. %2$sDon't do that%3$s!":["%1$sLegătură frază cheie%3$s: ești legat la o altă pagină cu cuvintele frazei cheie pe care vrei să o folosești pentru această pagină. %2$sNu face asta%3$s!"],"This is far below the recommended minimum of %5$d word. %3$sAdd more content%4$s.":["Este cu mult sub minimul recomandat de %5$d cuvânt. %3$sAdaugă mai mult conținut%4$s.","Este cu mult sub minimul recomandat de %5$d cuvinte. %3$sAdaugă mai mult conținut%4$s.","Este cu mult sub minimul recomandat de %5$d de cuvinte. %3$sAdaugă mai mult conținut%4$s."],"This is below the recommended minimum of %5$d word. %3$sAdd more content%4$s.":["Este sub minimul recomandat de %5$d cuvânt. %3$sAdaugă mai mult conținut%4$s.","Este sub minimul recomandat de %5$d cuvinte. %3$sAdaugă mai mult conținut%4$s.","Este sub minimul recomandat de %5$d de cuvinte. %3$sAdaugă mai mult conținut%4$s."],"%2$sText length%4$s: The text contains %1$d word.":["%2$sLungime text%4$s: textul conține un cuvânt.","%2$sLungime text%4$s: textul conține %1$d cuvinte.","%2$sLungime text%4$s: textul conține %1$d de cuvinte."],"%2$sText length%3$s: The text contains %1$d word. Good job!":["%2$sLungime text%3$s: textul conține un cuvânt. Foarte bine!","%2$sLungime text%3$s: textul conține %1$d cuvinte. Foarte bine!","%2$sLungime text%3$s: textul conține %1$d de cuvinte. Foarte bine!"],"%1$sKeyphrase in subheading%3$s: More than 75%% of your higher-level subheadings reflect the topic of your copy. That's too much. %2$sDon't over-optimize%3$s!":["%1$sFrază cheie în subtitluri%3$s: mai mult de 75%% dintre subtitlurile tale reflectă subiectul textului. E prea mult. %2$sNu optimiza în exces%3$s!"],"%1$sSEO title width%3$s: %2$sPlease create an SEO title%3$s.":["%1$sLungime titlu SEO%3$s: %2$ste rog crează un titlu SEO%3$s."],"%1$sSEO title width%3$s: The SEO title is wider than the viewable limit. %2$sTry to make it shorter%3$s.":["%1$sLungime titlu SEO%3$s: titlul SEO mai mare decât limita vizibilă. %2$sÎncearcă să-l scurtezi%3$s."],"%1$sSEO title width%2$s: Good job!":["%1$sLungime titlu SEO%2$s: foarte bine!"],"%1$sSEO title width%3$s: The SEO title is too short. %2$sUse the space to add keyphrase variations or create compelling call-to-action copy%3$s.":["%1$sLungime titlu SEO%3$s: titlul SEO este prea scurt. %2$sFolosește întreg spațiul pentru a adăuga variante de cuvinte cheie sau pentru a crea un apel la acțiune convingător%3$s."],"%1$sOutbound links%2$s: There are both nofollowed and normal outbound links on this page. Good job!":["%1$sLegături externe%2$s: în această pagină sunt legături externe nofollow și normale. Foarte bine!"],"%1$sOutbound links%2$s: Good job!":["%1$sLegături externe%2$s: foarte bine!"],"%1$sOutbound links%3$s: All outbound links on this page are nofollowed. %2$sAdd some normal links%3$s.":["%1$sLegături externe%3$s: în această pagină toate legăturile externe sunt nofollow. %2$sAdaugă și legături normale%3$s."],"%1$sOutbound links%3$s: No outbound links appear in this page. %2$sAdd some%3$s!":["%1$sLegături externe%3$s: în această pagină nu apare nicio legătură externă. %2$sAdaugă câteva%3$s!"],"%1$sMeta description length%2$s: Well done!":["%1$sLungime descriere meta%2$s: foarte bună!"],"%1$sMeta description length%3$s: The meta description is over %4$d characters. To ensure the entire description will be visible, %2$syou should reduce the length%3$s!":["%1$sLungime descriere meta%3$s: descrierea meta are mai mult de %4$d de caractere. Pentru a te asigura că va fi vizibilă în întregime, %2$sar trebui să-i reduci lungimea%3$s!"],"%1$sMeta description length%3$s: The meta description is too short (under %4$d characters). Up to %5$d characters are available. %2$sUse the space%3$s!":["%1$sLungime descriere meta%3$s: descrierea meta este prea scurtă (are mai puțin de %4$d de caractere). Sunt disponibile până la %5$d de caractere. %2$sFolosește acest spațiu%3$s!"],"%1$sMeta description length%3$s: No meta description has been specified. Search engines will display copy from the page instead. %2$sMake sure to write one%3$s!":["%1$sLungime descriere meta%3$s: nu a fost specificată nicio descriere meta. În locul ei, motoarele de căutare vor afișa un text din pagină. %2$sAsigură-te că scrii una%3$s!"],"%1$sKeyphrase in meta description%2$s: The meta description has been specified, but it does not contain the keyphrase. %3$sFix that%4$s!":["%1$sFrază cheie în descrierea meta%2$s: descrierea meta a fost specificată, dar nu conține fraza cheie. %3$sCorectează asta%4$s!"],"%1$sKeyphrase in meta description%2$s: The meta description contains the keyphrase %3$s times, which is over the advised maximum of 2 times. %4$sLimit that%5$s!":["%1$sFrază cheie în descrierea meta%2$s: descrierea meta conține de %3$s ori fraza cheie, este peste maximul recomandat, de 2 ori. %4$sÎncadrează-te%5$s!"],"%1$sKeyphrase in meta description%2$s: Keyphrase or synonym appear in the meta description. Well done!":["%1$sFrază cheie în descrierea meta%2$s: descrierea meta conține fraza cheie sau sinonimele ei. Foarte bine!"],"%3$sKeyphrase length%5$s: The keyphrase is %1$d words long. That's way more than the recommended maximum of %2$d words. %4$sMake it shorter%5$s!":["%3$sLungime frază cheie%5$s: fraza cheie are %1$d cuvinte. Este cu mult mai mare decât maximul recomandat de %2$d cuvinte. %4$sScurtează fraza%5$s!"],"%3$sKeyphrase length%5$s: The keyphrase is %1$d words long. That's more than the recommended maximum of %2$d words. %4$sMake it shorter%5$s!":["%3$sLungime frază cheie%5$s: fraza cheie are %1$d cuvinte. Este mai mare decât maximul recomandat de %2$d cuvinte. %4$sScurtează fraza%5$s!"],"%1$sKeyphrase length%2$s: Good job!":["%1$sLungime frază cheie%2$s: foarte bine!"],"%1$sKeyphrase length%3$s: No focus keyphrase was set for this page. %2$sSet a keyphrase in order to calculate your SEO score%3$s.":["%1$sLungime frază cheie%3$s: nu ai stabilit nicio frază cheie pentru această pagină. %2$sIntrodu o frază cheie pentru a calcula punctajul SEO%3$s."],"%1$sKeyphrase in introduction%3$s: Your keyphrase or its synonyms do not appear in the first paragraph. %2$sMake sure the topic is clear immediately%3$s.":["%1$sFrază cheie în introducere%3$s: fraza cheie sau sinonimele ei nu apar în primul paragraf. %2$sAsigură-te că apar în introducere%3$s."],"%1$sKeyphrase in introduction%3$s:Your keyphrase or its synonyms appear in the first paragraph of the copy, but not within one sentence. %2$sFix that%3$s!":["%1$sFrază cheie în introducere%3$s: fraza cheie sau sinonimele ei apar în primul paragraf al textului, dar cuvintele nu sunt în aceeași propoziție. %2$sCorectează asta%3$s!"],"%1$sKeyphrase in introduction%2$s: Well done!":["%1$sFrază cheie în introducere%2$s: foarte bine!"],"%1$sInternal links%2$s: There are both nofollowed and normal internal links on this page. Good job!":["%1$sLegături interne%2$s: în această pagină sunt legături interne nofollow și normale. Foarte bine!"],"%1$sInternal links%2$s: You have enough internal links. Good job!":["%1$sLegături interne%2$s: ai suficiente legături interne. Foarte bine!"],"%1$sInternal links%3$s: The internal links in this page are all nofollowed. %2$sAdd some good internal links%3$s.":["%1$sLegături interne%3$s: în această pagină legăturile interne sunt nofollow. %2$sAdaugă și legături interne normale%3$s."],"%1$sInternal links%3$s: No internal links appear in this page, %2$smake sure to add some%3$s!":["%1$sLegături interne%3$s: în această pagină nu apare nicio legătură internă, %2$sasigură-te că adaugi câteva%3$s!"],"%1$sTransition words%2$s: Well done!":["%1$sCuvinte de legătură%2$s: foarte bine!"],"%1$sTransition words%2$s: Only %3$s of the sentences contain transition words, which is not enough. %4$sUse more of them%2$s.":["%1$sCuvinte de legătură%2$s: numai %3$s dintre propoziții conțin cuvinte de legătură, nu este suficient. %4$sFolosește mai multe%2$s."],"%1$sTransition words%2$s: None of the sentences contain transition words. %3$sUse some%2$s.":["%1$sCuvinte de legătură%2$s: niciuna dintre propoziții nu conține cuvinte de legătură. %3$sFolosește câteva%2$s."],"%1$sNot enough content%2$s: %3$sPlease add some content to enable a good analysis%2$s.":["%1$sConținut insuficient%2$s: %3$ste rog adaugă mai mult conținut pentru a permite o analiză completă%2$s."],"%1$sSubheading distribution%2$s: You are not using any subheadings, but your text is short enough and probably doesn't need them.":["%1$sDistribuție subtitluri%2$s: nu folosești niciun subtitlu, dar textul este destul de scurt și probabil subtitlurile nu sunt necesare."],"%1$sSubheading distribution%2$s: You are not using any subheadings, although your text is rather long. %3$sTry and add some subheadings%2$s.":["%1$sDistribuție subtitluri%2$s: nu folosești niciun subtitlu, cu toate că textul este destul de lung. %3$sÎncearcă să adaugi câteva subtitluri%2$s."],"%1$sSubheading distribution%2$s: %3$d section of your text is longer than %4$d words and is not separated by any subheadings. %5$sAdd subheadings to improve readability%2$s.":["%1$sDistribuție subtitluri%2$s: o secțiune a textului are mai mult de %4$d de cuvinte și nu este separată de niciun subtitlu. %5$sAdaugă subtitluri pentru a îmbunătăți lizibilitatea%2$s.","%1$sDistribuție subtitluri%2$s: %3$d secțiuni ale textului au mai mult de %4$d de cuvinte și nu sunt separate de niciun subtitlu. %5$sAdaugă subtitluri pentru a îmbunătăți lizibilitatea%2$s.","%1$sDistribuție subtitluri%2$s: %3$d de secțiuni ale textului au mai mult de %4$d de cuvinte și nu sunt separate de niciun subtitlu. %5$sAdaugă subtitluri pentru a îmbunătăți lizibilitatea%2$s."],"%1$sSubheading distribution%2$s: Great job!":["%1$sDistribuție subtitluri%2$s: foarte bine!"],"%1$sSentence length%2$s: %3$s of the sentences contain more than %4$s words, which is more than the recommended maximum of %5$s. %6$sTry to shorten the sentences%2$s.":["%1$sLungime propoziție%2$s: %3$s dintre propoziții conțin mai mult de %4$s cuvinte, este mai mult decât maximul recomandat de %5$s. %6$sÎncearcă să le scurtezi%2$s."],"%1$sSentence length%2$s: Great!":["%1$sLungime propoziție%2$s: bună!"],"%1$sConsecutive sentences%2$s: There is enough variety in your sentences. That's great!":["%1$sPropoziții consecutive%2$s: propozițiile sunt destul de diversificate. Foarte bine!"],"%1$sConsecutive sentences%2$s: The text contains %3$d consecutive sentences starting with the same word. %5$sTry to mix things up%2$s!":["%1$sPropoziții consecutive%2$s: textul conține %3$d propoziții consecutive care încep cu același cuvânt. %5$sÎncearcă să combini cuvintele%2$s!","%1$sPropoziții consecutive%2$s: textul conține %4$d situații în care %3$d sau mai multe propoziții consecutive încep cu același cuvânt. %5$sÎncearcă să combini cuvintele%2$s!","%1$sPropoziții consecutive%2$s: textul conține %4$d de situații în care %3$d sau mai multe propoziții consecutive încep cu același cuvânt. %5$sÎncearcă să combini cuvintele%2$s!"],"%1$sPassive voice%2$s: %3$s of the sentences contain passive voice, which is more than the recommended maximum of %4$s. %5$sTry to use their active counterparts%2$s.":["%1$sDiateză pasivă%2$s: %3$s dintre propoziții folosesc diateza pasivă, este mai mare decât maximul recomandat de %4$s. %5$sÎncearcă să folosești în schimb diateza activă%2$s."],"%1$sPassive voice%2$s: You're using enough active voice. That's great!":["%1$sDiateză pasivă%2$s: folosești suficient diateza activă. Foarte bine!"],"%1$sParagraph length%2$s: %3$d of the paragraphs contains more than the recommended maximum of %4$d words. %5$sShorten your paragraphs%2$s!":["%1$sLungime paragraf%2$s: un paragraf este mai mare decât maximul recomandat de %4$d de cuvinte. %5$sScurtează paragraful%2$s!","%1$sLungime paragraf%2$s: %3$d paragrafe sunt mai mari decât maximul recomandat de %4$d de cuvinte. %5$sScurtează paragrafele%2$s!","%1$sLungime paragraf%2$s: %3$d de paragrafe sunt mai mari decât maximul recomandat de %4$d de cuvinte. %5$sScurtează paragrafele%2$s!"],"%1$sParagraph length%2$s: None of the paragraphs are too long. Great job!":["%1$sLungime paragraf%2$s: niciun paragraf nu este prea lung. Foarte bine!"],"Good job!":["Foarte bine!"],"%1$sFlesch Reading Ease%2$s: The copy scores %3$s in the test, which is considered %4$s to read. %5$s%6$s%7$s":["%1$sCât de ușor este citit (Flesch Reading Ease)%2$s: textul a primit punctajul %3$s la efectuarea testului, este considerat %4$s de citit. %5$s%6$s%7$s"],"Scroll to see the preview content.":["Derulează pentru a vedea conținutul previzualizării."],"An error occurred in the '%1$s' assessment":["A apărut o eroare în evaluarea '%1$s'"],"%1$s of the words contain %2$sover %3$s syllables%4$s, which is more than the recommended maximum of %5$s.":["%1$s din cuvinte conțin %2$speste %3$s silabe%4$s, care este mai mult decât recomandarea maximă de %5$s."],"%1$s of the words contain %2$sover %3$s syllables%4$s, which is less than or equal to the recommended maximum of %5$s.":["%1$s din cuvinte conțin %2$speste %3$s silabe%4$s, care este mai puțin sau egal decât recomandarea maximă de %5$s."],"This is slightly below the recommended minimum of %5$d word. %3$sAdd a bit more copy%4$s.":["Este cu puțin sub minimul recomandat de %5$d cuvânt. %3$sMai adaugă puțin text%4$s.","Este cu puțin sub minimul recomandat de %5$d cuvinte. %3$sMai adaugă puțin text%4$s.","Este cu puțin sub minimul recomandat de %5$d de cuvinte. %3$sMai adaugă puțin text%4$s."],"The meta description contains %1$d sentence %2$sover %3$s words%4$s. Try to shorten this sentence.":["Descrierea meta conține %1$d propoziție %2$scu peste %3$s de cuvinte%4$s. Încearcă să scurtezi această propoziție.","Descrierea meta conține %1$d propoziții %2$scu peste %3$s de cuvinte%4$s. Încearcă să scurtezi aceste propoziții.","Descrierea meta conține %1$d de propoziții %2$scu peste %3$s de cuvinte%4$s. Încearcă să scurtezi aceste propoziții."],"The meta description contains no sentences %1$sover %2$s words%3$s.":["Descrierea meta conține nicio propoziție %1$s cu peste %2$s de cuvinte%3$s."],"Mobile preview":["Previzualizare pe mobil"],"Desktop preview":["Previzualizare desktop"],"Please provide an SEO title by editing the snippet below.":["Te rog furnizează un titlu SEO prin editarea fragmentului de mai jos."],"Meta description preview:":["Previzualizare descriere meta:"],"Slug preview:":["Previzualizare descriptor:"],"SEO title preview:":["Previzualizare titlu SEO:"],"Close snippet editor":["Închide editor fragment"],"Slug":["Descriptor"],"Remove marks in the text":["Înlătură marcaje în text"],"Mark this result in the text":["Marchează acest rezultat în text"],"Marks are disabled in current view":["Marcajele sunt dezactivate în vizualizarea curentă"],"Good SEO score":["Punctaj SEO bun"],"OK SEO score":["Punctaj SEO OK"],"Feedback":["Impresii"],"ok":["OK"],"Please provide a meta description by editing the snippet below.":["Te rog furnizează o descriere meta prin editarea fragmentului de mai jos."],"Edit snippet":["Editează fragmentul"],"You can click on each element in the preview to jump to the Snippet Editor.":["Poți da clic pe fiecare element din previzualizare pentru a sări la editor fragment."],"SEO title":["Titlu SEO"],"Needs improvement":["Necesită îmbunătățire"],"Good":["bun"],"very difficult":["foarte dificil"],"Try to make shorter sentences, using less difficult words to improve readability":["Pentru a îmbunătăți lizibilitatea, încearcă să faci propoziții mai scurte, folosind cuvinte mai puțin dificile."],"difficult":["dificil"],"Try to make shorter sentences to improve readability":["Pentru a îmbunătăți lizibilitatea, încearcă să faci propoziții mai scurte."],"fairly difficult":["destul de dificil"],"OK":["OK"],"fairly easy":["destul de ușor"],"easy":["ușor"],"very easy":["foarte ușor"],"Meta description":["Descriere meta"]}}}
1
+ {"domain":"wordpress-seo","locale_data":{"wordpress-seo":{"":{"domain":"wordpress-seo","plural-forms":"nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);","lang":"ro"},"Google preview":["Previzualizare Google"],"Has feedback":["Are impresii"],"Content optimization:":["Optimizare conținut:"],"%1$sFlesch Reading Ease%2$s: The copy scores %3$s in the test, which is considered %4$s to read. %5$s":["%1$sCât de ușor este citit (Flesch Reading Ease)%2$s: textul a primit punctajul %3$s la efectuarea testului, este considerat %4$s de citit. %5$s"],"%3$sImage alt attributes%5$s: Out of %2$d images on this page, %1$d have alt attributes with words from your keyphrase or synonyms. That's a bit much. %4$sOnly include the keyphrase or its synonyms when it really fits the image%5$s.":["%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, %1$d au atribute alt care cu cuvinte din fraza cheie sau sinonimele ei. E un pic cam mult. %4$sInclude numai fraza cheie sau sinonimele ei când chiar se potrivesc cu imaginea%5$s."],"%1$sImage alt attributes%2$s: Good job!":["%1$sAtribute alt imagini%2$s: Foarte bine!"],"%3$sImage alt attributes%5$s: Out of %2$d images on this page, only %1$d has an alt attribute that reflects the topic of your text. %4$sAdd your keyphrase or synonyms to the alt tags of more relevant images%5$s!":["%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, numai una are un atribut alt care reflectă subiectul textului. %4$sAdaugă fraza cheie sau sinonimele ei la tagurile alt pentru mai multe imagini relevante%5$s!","%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, numai %1$d au atribute alt care reflectă subiectul textului. %4$sAdaugă fraza cheie sau sinonimele ei la tagurile alt pentru mai multe imagini relevante%5$s!","%3$sAtribute alt imagini%5$s: din %2$d imagini existente în această pagină, numai %1$d au atribute alt care reflectă subiectul textului. %4$sAdaugă fraza cheie sau sinonimele ei la tagurile alt pentru mai multe imagini relevante%5$s!"],"%1$sImage alt attributes%3$s: Images on this page do not have alt attributes that reflect the topic of your text. %2$sAdd your keyphrase or synonyms to the alt tags of relevant images%3$s!":["%1$sAtribute alt imagini%3$s: imaginile din această pagină nu au atribute alt care să reflecte subiectul textului. %2$sAdaugă fraza cheie sau sinonimele ei la tagurile alt ale imaginilor relevante%3$s!"],"%1$sImage alt attributes%3$s: Images on this page have alt attributes, but you have not set your keyphrase. %2$sFix that%3$s!":["%1$sAtribute alt imagini%3$s: imaginile din această pagină au atribute alt, dar nu ai setat o frază cheie. %2$sCorectează asta%3$s!"],"%1$sKeyphrase in subheading%2$s: %3$s of your higher-level subheadings reflects the topic of your copy. Good job!":["%1$sFrază cheie în subtitluri%2$s: unul dintre subtitlurile tale reflectă subiectul textului. Foarte bine!","%1$sFrază cheie în subtitluri%2$s: %3$s dintre subtitlurile tale reflectă subiectul textului. Foarte bine!","%1$sFrază cheie în subtitluri%2$s: %3$s dintre subtitlurile tale reflectă subiectul textului. Foarte bine!"],"%1$sKeyphrase in subheading%2$s: Your higher-level subheading reflects the topic of your copy. Good job!":["%1$sFrază cheie în subtitluri%2$s: subtitlul tău reflectă subiectul textului. Foarte bine!"],"%1$sKeyphrase in subheading%3$s: %2$sUse more keyphrases or synonyms in your higher-level subheadings%3$s!":["%1$sFrază cheie în subtitluri%3$s: %2$sfolosește mai multe fraze cheie sau sinonimele ei în subtitluri%3$s!"],"%1$sSingle title%3$s: H1s should only be used as your main title. Find all H1s in your text that aren't your main title and %2$schange them to a lower heading level%3$s!":["%1$sNumai un titlu%3$s: H1 ar trebui să fie folosit numai pentru titlul principal. Găsește toate subtitlurile H1 din text care nu sunt folosite ca titlu principal și %2$smodifică-le în subtitluri inferioare (H2, H3...)%3$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found 0 times. That's less than the recommended minimum of %3$d times for a text of this length. %4$sFocus on your keyphrase%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie nu a fost găsită. Este sub minimul recomandat de %3$d ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %5$d time. That's less than the recommended minimum of %3$d times for a text of this length. %4$sFocus on your keyphrase%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Este sub minimul recomandat de %3$d ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d ori. Este sub minimul recomandat de %3$d ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d de ori. Este sub minimul recomandat de %3$d de ori pentru un text de această lungime. %4$sFolosește-o mai des%2$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %3$d time. This is great!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Foarte bine!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %3$d ori. Foarte bine!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %3$d de ori. Foarte bine!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %5$d time. That's more than the recommended maximum of %3$d times for a text of this length. %4$sDon't overoptimize%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Este peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d ori. Este peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d de ori. Este peste maximul recomandat de %3$d de ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!"],"%1$sKeyphrase density%2$s: The focus keyphrase was found %5$d time. That's way more than the recommended maximum of %3$d times for a text of this length. %4$sDon't overoptimize%2$s!":["%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită o singură dată. Este cu mult peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d ori. Este cu mult peste maximul recomandat de %3$d ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!","%1$sDensitate frază cheie%2$s: fraza cheie a fost găsită de %5$d de ori. Este cu mult peste maximul recomandat de %3$d de ori pentru un text de această lungime. %4$sO folosești de prea multe ori%2$s!"],"%1$sFunction words in keyphrase%3$s: Your keyphrase \"%4$s\" contains function words only. %2$sLearn more about what makes a good keyphrase.%3$s":["%1$sDeterminanți în fraza cheie%3$s: fraza ta cheie „%4$s” conține numai determinanți. %2$sAflă mai multe despre cum se alcătuiește o frază cheie bună.%3$s"],"%1$sKeyphrase length%3$s: %2$sSet a keyphrase in order to calculate your SEO score%3$s.":["%1$sLungime frază cheie%3$s: %2$sintrodu o frază cheie pentru a calcula punctajul SEO%3$s."],"%1$sKeyphrase in slug%2$s: More than half of your keyphrase appears in the slug. That's great!":["%1$sFrază cheie în descriptor%2$s: mai mult de jumătate din fraza ta cheie apare în descriptor. Foarte bine!"],"%1$sKeyphrase in slug%3$s: (Part of) your keyphrase does not appear in the slug. %2$sChange that%3$s!":["%1$sFrază cheie în descriptor%3$s: fraza ta cheie (sau o parte din ea) nu apare în descriptor. %2$sCorectează asta%3$s!"],"%1$sKeyphrase in slug%2$s: Great work!":["%1$sFrază cheie în descriptor%2$s: foarte bine!"],"%1$sKeyphrase in title%3$s: Not all the words from your keyphrase \"%4$s\" appear in the SEO title. %2$sTry to use the exact match of your keyphrase in the SEO title%3$s.":["%1$sFrază cheie în titlu%3$s: în titlul SEO nu apar toate cuvintele din fraza ta cheie „%4$s”. %2$sÎncearcă să folosești în titlul SEO chiar fraza cheie%3$s."],"%1$sKeyphrase in title%3$s: Does not contain the exact match. %2$sTry to write the exact match of your keyphrase in the SEO title%3$s.":["%1$sFrază cheie în titlu%3$s: titlul nu conține fraza cheie. %2$sÎncearcă să scrii în titlul SEO chiar fraza cheie%3$s."],"%1$sKeyphrase in title%3$s: The exact match of the keyphrase appears in the SEO title, but not at the beginning. %2$sTry to move it to the beginning%3$s.":["%1$sFrază cheie în titlu%3$s: fraza cheie apare în titlul SEO, dar nu este la începutul lui. %2$sÎncearcă să o muți la începutul titlului%3$s."],"%1$sKeyphrase in title%2$s: The exact match of the keyphrase appears at the beginning of the SEO title. Good job!":["%1$sFrază cheie în titlu%2$s: fraza cheie apare la începutul titlului SEO. Foarte bine!"],"%1$sKeyphrase distribution%2$s: Good job!":["%1$sDistribuție frază cheie%2$s: foarte bine!"],"%1$sKeyphrase distribution%3$s: Uneven. Some parts of your text do not contain the keyphrase or its synonyms. %2$sDistribute them more evenly%3$s.":["%1$sDistribuție frază cheie%3$s: inegală. Unele părți ale textului nu conțin fraza cheie sau sinonimele ei. %2$sDistribuie fraza cheie uniform%3$s."],"%1$sKeyphrase distribution%3$s: Very uneven. Large parts of your text do not contain the keyphrase or its synonyms. %2$sDistribute them more evenly%3$s.":["%1$sDistribuție frază cheie%3$s: inegală. Părți mari de text nu conțin fraza cheie sau sinonimele ei. %2$sDistribuie fraza cheie uniform%3$s."],"%1$sKeyphrase distribution%3$s: %2$sInclude your keyphrase or its synonyms in the text so that we can check keyphrase distribution%3$s.":["%1$sDistribuție frază cheie%3$s: %2$sinclude fraza cheie sau sinonimele ei în text ca să putem verifica distribuția ei (lor)%3$s."],"%4$sPreviously used keyphrase%6$s: You've used this keyphrase %1$s%2$d times before%3$s. %5$sDo not use your keyphrase more than once%6$s.":["%4$sFrază cheie folosită anterior%6$s: ai folosit această frază cheie de %1$s%2$d ori mai înainte%3$s. %5$sFolosește o frază cheie numai o singură dată%6$s."],"%3$sPreviously used keyphrase%5$s: You've used this keyphrase %1$sonce before%2$s. %4$sDo not use your keyphrase more than once%5$s.":["%3$sFrază cheie folosită anterior%5$s: ai folosit această frază cheie %1$saltădată, mai înainte%2$s. %4$sFolosește o frază cheie numai o singură dată%5$s."],"%1$sPreviously used keyphrase%2$s: You've not used this keyphrase before, very good.":["%1$sFrază cheie folosită anterior%2$s: nu ai mai folosit această frază cheie, foarte bine."],"%1$sSlug stopwords%3$s: The slug for this page contains a stop word. %2$sRemove it%3$s!":["%1$sCuvinte stop în descriptor%3$s: descriptorul acestei pagini conține un cuvânt stop. %2$sÎnlătură-l%3$s!","%1$sCuvinte stop în descriptor%3$s: descriptorul acestei pagini conține cuvinte stop. %2$sÎnlătură-le%3$s!","%1$sCuvinte stop în descriptor%3$s: descriptorul acestei pagini conține cuvinte stop. %2$sÎnlătură-le%3$s!"],"%1$sSlug too long%3$s: the slug for this page is a bit long. %2$sShorten it%3$s!":["%1$sDescriptor prea lung%3$s: descriptorul acestei pagini este un pic prea lung. %2$sScurtează-l%3$s!"],"%1$sImage alt attributes%3$s: No images appear on this page. %2$sAdd some%3$s!":["%1$sAtribute alt imagini%3$s: nu apare nicio imagine în această pagină. %2$sAdaugă cel puțin una%3$s!"],"%1$sLink keyphrase%3$s: You're linking to another page with the words you want this page to rank for. %2$sDon't do that%3$s!":["%1$sLegătură frază cheie%3$s: ești legat la o altă pagină cu cuvintele frazei cheie pe care vrei să o folosești pentru această pagină. %2$sNu face asta%3$s!"],"This is far below the recommended minimum of %5$d word. %3$sAdd more content%4$s.":["Este cu mult sub minimul recomandat de %5$d cuvânt. %3$sAdaugă mai mult conținut%4$s.","Este cu mult sub minimul recomandat de %5$d cuvinte. %3$sAdaugă mai mult conținut%4$s.","Este cu mult sub minimul recomandat de %5$d de cuvinte. %3$sAdaugă mai mult conținut%4$s."],"This is below the recommended minimum of %5$d word. %3$sAdd more content%4$s.":["Este sub minimul recomandat de %5$d cuvânt. %3$sAdaugă mai mult conținut%4$s.","Este sub minimul recomandat de %5$d cuvinte. %3$sAdaugă mai mult conținut%4$s.","Este sub minimul recomandat de %5$d de cuvinte. %3$sAdaugă mai mult conținut%4$s."],"%2$sText length%4$s: The text contains %1$d word.":["%2$sLungime text%4$s: textul conține un cuvânt.","%2$sLungime text%4$s: textul conține %1$d cuvinte.","%2$sLungime text%4$s: textul conține %1$d de cuvinte."],"%2$sText length%3$s: The text contains %1$d word. Good job!":["%2$sLungime text%3$s: textul conține un cuvânt. Foarte bine!","%2$sLungime text%3$s: textul conține %1$d cuvinte. Foarte bine!","%2$sLungime text%3$s: textul conține %1$d de cuvinte. Foarte bine!"],"%1$sKeyphrase in subheading%3$s: More than 75%% of your higher-level subheadings reflect the topic of your copy. That's too much. %2$sDon't over-optimize%3$s!":["%1$sFrază cheie în subtitluri%3$s: mai mult de 75%% dintre subtitlurile tale reflectă subiectul textului. E prea mult. %2$sNu optimiza în exces%3$s!"],"%1$sSEO title width%3$s: %2$sPlease create an SEO title%3$s.":["%1$sLungime titlu SEO%3$s: %2$ste rog crează un titlu SEO%3$s."],"%1$sSEO title width%3$s: The SEO title is wider than the viewable limit. %2$sTry to make it shorter%3$s.":["%1$sLungime titlu SEO%3$s: titlul SEO mai mare decât limita vizibilă. %2$sÎncearcă să-l scurtezi%3$s."],"%1$sSEO title width%2$s: Good job!":["%1$sLungime titlu SEO%2$s: foarte bine!"],"%1$sSEO title width%3$s: The SEO title is too short. %2$sUse the space to add keyphrase variations or create compelling call-to-action copy%3$s.":["%1$sLungime titlu SEO%3$s: titlul SEO este prea scurt. %2$sFolosește întreg spațiul pentru a adăuga variante de cuvinte cheie sau pentru a crea un apel la acțiune convingător%3$s."],"%1$sOutbound links%2$s: There are both nofollowed and normal outbound links on this page. Good job!":["%1$sLegături externe%2$s: în această pagină sunt legături externe fără urmărire și normale. Foarte bine!"],"%1$sOutbound links%2$s: Good job!":["%1$sLegături externe%2$s: foarte bine!"],"%1$sOutbound links%3$s: All outbound links on this page are nofollowed. %2$sAdd some normal links%3$s.":["%1$sLegături externe%3$s: în această pagină toate legăturile externe sunt fără urmărire. %2$sAdaugă și legături normale%3$s."],"%1$sOutbound links%3$s: No outbound links appear in this page. %2$sAdd some%3$s!":["%1$sLegături externe%3$s: în această pagină nu apare nicio legătură externă. %2$sAdaugă câteva%3$s!"],"%1$sMeta description length%2$s: Well done!":["%1$sLungime descriere meta%2$s: foarte bună!"],"%1$sMeta description length%3$s: The meta description is over %4$d characters. To ensure the entire description will be visible, %2$syou should reduce the length%3$s!":["%1$sLungime descriere meta%3$s: descrierea meta are mai mult de %4$d de caractere. Pentru a te asigura că va fi vizibilă în întregime, %2$sar trebui să-i reduci lungimea%3$s!"],"%1$sMeta description length%3$s: The meta description is too short (under %4$d characters). Up to %5$d characters are available. %2$sUse the space%3$s!":["%1$sLungime descriere meta%3$s: descrierea meta este prea scurtă (are mai puțin de %4$d de caractere). Sunt disponibile până la %5$d de caractere. %2$sFolosește acest spațiu%3$s!"],"%1$sMeta description length%3$s: No meta description has been specified. Search engines will display copy from the page instead. %2$sMake sure to write one%3$s!":["%1$sLungime descriere meta%3$s: nu a fost specificată nicio descriere meta. În locul ei, motoarele de căutare vor afișa un text din pagină. %2$sAsigură-te că scrii una%3$s!"],"%1$sKeyphrase in meta description%2$s: The meta description has been specified, but it does not contain the keyphrase. %3$sFix that%4$s!":["%1$sFrază cheie în descrierea meta%2$s: descrierea meta a fost specificată, dar nu conține fraza cheie. %3$sCorectează asta%4$s!"],"%1$sKeyphrase in meta description%2$s: The meta description contains the keyphrase %3$s times, which is over the advised maximum of 2 times. %4$sLimit that%5$s!":["%1$sFrază cheie în descrierea meta%2$s: descrierea meta conține de %3$s ori fraza cheie, este peste maximul recomandat, de 2 ori. %4$sÎncadrează-te%5$s!"],"%1$sKeyphrase in meta description%2$s: Keyphrase or synonym appear in the meta description. Well done!":["%1$sFrază cheie în descrierea meta%2$s: descrierea meta conține fraza cheie sau sinonimele ei. Foarte bine!"],"%3$sKeyphrase length%5$s: The keyphrase is %1$d words long. That's way more than the recommended maximum of %2$d words. %4$sMake it shorter%5$s!":["%3$sLungime frază cheie%5$s: fraza cheie are %1$d cuvinte. Este cu mult mai mare decât maximul recomandat de %2$d cuvinte. %4$sScurtează fraza%5$s!"],"%3$sKeyphrase length%5$s: The keyphrase is %1$d words long. That's more than the recommended maximum of %2$d words. %4$sMake it shorter%5$s!":["%3$sLungime frază cheie%5$s: fraza cheie are %1$d cuvinte. Este mai mare decât maximul recomandat de %2$d cuvinte. %4$sScurtează fraza%5$s!"],"%1$sKeyphrase length%2$s: Good job!":["%1$sLungime frază cheie%2$s: foarte bine!"],"%1$sKeyphrase length%3$s: No focus keyphrase was set for this page. %2$sSet a keyphrase in order to calculate your SEO score%3$s.":["%1$sLungime frază cheie%3$s: nu ai stabilit nicio frază cheie pentru această pagină. %2$sIntrodu o frază cheie pentru a calcula punctajul SEO%3$s."],"%1$sKeyphrase in introduction%3$s: Your keyphrase or its synonyms do not appear in the first paragraph. %2$sMake sure the topic is clear immediately%3$s.":["%1$sFrază cheie în introducere%3$s: fraza cheie sau sinonimele ei nu apar în primul paragraf. %2$sAsigură-te că apar în introducere%3$s."],"%1$sKeyphrase in introduction%3$s:Your keyphrase or its synonyms appear in the first paragraph of the copy, but not within one sentence. %2$sFix that%3$s!":["%1$sFrază cheie în introducere%3$s: fraza cheie sau sinonimele ei apar în primul paragraf al textului, dar cuvintele nu sunt în aceeași propoziție. %2$sCorectează asta%3$s!"],"%1$sKeyphrase in introduction%2$s: Well done!":["%1$sFrază cheie în introducere%2$s: foarte bine!"],"%1$sInternal links%2$s: There are both nofollowed and normal internal links on this page. Good job!":["%1$sLegături interne%2$s: în această pagină sunt legături interne fără urmărire și normale. Foarte bine!"],"%1$sInternal links%2$s: You have enough internal links. Good job!":["%1$sLegături interne%2$s: ai suficiente legături interne. Foarte bine!"],"%1$sInternal links%3$s: The internal links in this page are all nofollowed. %2$sAdd some good internal links%3$s.":["%1$sLegături interne%3$s: în această pagină toate legăturile interne sunt fără urmărire. %2$sAdaugă și legături interne normale%3$s."],"%1$sInternal links%3$s: No internal links appear in this page, %2$smake sure to add some%3$s!":["%1$sLegături interne%3$s: în această pagină nu apare nicio legătură internă, %2$sasigură-te că adaugi câteva%3$s!"],"%1$sTransition words%2$s: Well done!":["%1$sCuvinte de legătură%2$s: foarte bine!"],"%1$sTransition words%2$s: Only %3$s of the sentences contain transition words, which is not enough. %4$sUse more of them%2$s.":["%1$sCuvinte de legătură%2$s: numai %3$s dintre propoziții conțin cuvinte de legătură, nu este suficient. %4$sFolosește mai multe%2$s."],"%1$sTransition words%2$s: None of the sentences contain transition words. %3$sUse some%2$s.":["%1$sCuvinte de legătură%2$s: niciuna dintre propoziții nu conține cuvinte de legătură. %3$sFolosește câteva%2$s."],"%1$sNot enough content%2$s: %3$sPlease add some content to enable a good analysis%2$s.":["%1$sConținut insuficient%2$s: %3$ste rog adaugă mai mult conținut pentru a permite o analiză completă%2$s."],"%1$sSubheading distribution%2$s: You are not using any subheadings, but your text is short enough and probably doesn't need them.":["%1$sDistribuție subtitluri%2$s: nu folosești niciun subtitlu, dar textul este destul de scurt și probabil subtitlurile nu sunt necesare."],"%1$sSubheading distribution%2$s: You are not using any subheadings, although your text is rather long. %3$sTry and add some subheadings%2$s.":["%1$sDistribuție subtitluri%2$s: nu folosești niciun subtitlu, cu toate că textul este destul de lung. %3$sÎncearcă să adaugi câteva subtitluri%2$s."],"%1$sSubheading distribution%2$s: %3$d section of your text is longer than %4$d words and is not separated by any subheadings. %5$sAdd subheadings to improve readability%2$s.":["%1$sDistribuție subtitluri%2$s: o secțiune a textului are mai mult de %4$d de cuvinte și nu este separată de niciun subtitlu. %5$sAdaugă subtitluri pentru a îmbunătăți lizibilitatea%2$s.","%1$sDistribuție subtitluri%2$s: %3$d secțiuni ale textului au mai mult de %4$d de cuvinte și nu sunt separate de niciun subtitlu. %5$sAdaugă subtitluri pentru a îmbunătăți lizibilitatea%2$s.","%1$sDistribuție subtitluri%2$s: %3$d de secțiuni ale textului au mai mult de %4$d de cuvinte și nu sunt separate de niciun subtitlu. %5$sAdaugă subtitluri pentru a îmbunătăți lizibilitatea%2$s."],"%1$sSubheading distribution%2$s: Great job!":["%1$sDistribuție subtitluri%2$s: foarte bine!"],"%1$sSentence length%2$s: %3$s of the sentences contain more than %4$s words, which is more than the recommended maximum of %5$s. %6$sTry to shorten the sentences%2$s.":["%1$sLungime propoziție%2$s: %3$s dintre propoziții conțin mai mult de %4$s cuvinte, este mai mult decât maximul recomandat de %5$s. %6$sÎncearcă să le scurtezi%2$s."],"%1$sSentence length%2$s: Great!":["%1$sLungime propoziție%2$s: bună!"],"%1$sConsecutive sentences%2$s: There is enough variety in your sentences. That's great!":["%1$sPropoziții consecutive%2$s: propozițiile sunt destul de diversificate. Foarte bine!"],"%1$sConsecutive sentences%2$s: The text contains %3$d consecutive sentences starting with the same word. %5$sTry to mix things up%2$s!":["%1$sPropoziții consecutive%2$s: textul conține %3$d propoziții consecutive care încep cu același cuvânt. %5$sÎncearcă să combini cuvintele%2$s!","%1$sPropoziții consecutive%2$s: textul conține %4$d situații în care %3$d sau mai multe propoziții consecutive încep cu același cuvânt. %5$sÎncearcă să combini cuvintele%2$s!","%1$sPropoziții consecutive%2$s: textul conține %4$d de situații în care %3$d sau mai multe propoziții consecutive încep cu același cuvânt. %5$sÎncearcă să combini cuvintele%2$s!"],"%1$sPassive voice%2$s: %3$s of the sentences contain passive voice, which is more than the recommended maximum of %4$s. %5$sTry to use their active counterparts%2$s.":["%1$sDiateză pasivă%2$s: %3$s dintre propoziții folosesc diateza pasivă, este mai mare decât maximul recomandat de %4$s. %5$sÎncearcă să folosești în schimb diateza activă%2$s."],"%1$sPassive voice%2$s: You're using enough active voice. That's great!":["%1$sDiateză pasivă%2$s: folosești suficient diateza activă. Foarte bine!"],"%1$sParagraph length%2$s: %3$d of the paragraphs contains more than the recommended maximum of %4$d words. %5$sShorten your paragraphs%2$s!":["%1$sLungime paragraf%2$s: un paragraf este mai mare decât maximul recomandat de %4$d de cuvinte. %5$sScurtează paragraful%2$s!","%1$sLungime paragraf%2$s: %3$d paragrafe sunt mai mari decât maximul recomandat de %4$d de cuvinte. %5$sScurtează paragrafele%2$s!","%1$sLungime paragraf%2$s: %3$d de paragrafe sunt mai mari decât maximul recomandat de %4$d de cuvinte. %5$sScurtează paragrafele%2$s!"],"%1$sParagraph length%2$s: None of the paragraphs are too long. Great job!":["%1$sLungime paragraf%2$s: niciun paragraf nu este prea lung. Foarte bine!"],"Good job!":["Foarte bine!"],"%1$sFlesch Reading Ease%2$s: The copy scores %3$s in the test, which is considered %4$s to read. %5$s%6$s%7$s":["%1$sCât de ușor este citit (Flesch Reading Ease)%2$s: textul a primit punctajul %3$s la efectuarea testului, este considerat %4$s de citit. %5$s%6$s%7$s"],"Scroll to see the preview content.":["Derulează pentru a vedea conținutul previzualizării."],"An error occurred in the '%1$s' assessment":["A apărut o eroare în evaluarea '%1$s'"],"%1$s of the words contain %2$sover %3$s syllables%4$s, which is more than the recommended maximum of %5$s.":["%1$s din cuvinte conțin %2$speste %3$s silabe%4$s, care este mai mult decât recomandarea maximă de %5$s."],"%1$s of the words contain %2$sover %3$s syllables%4$s, which is less than or equal to the recommended maximum of %5$s.":["%1$s din cuvinte conțin %2$speste %3$s silabe%4$s, care este mai puțin sau egal decât recomandarea maximă de %5$s."],"This is slightly below the recommended minimum of %5$d word. %3$sAdd a bit more copy%4$s.":["Este cu puțin sub minimul recomandat de %5$d cuvânt. %3$sMai adaugă puțin text%4$s.","Este cu puțin sub minimul recomandat de %5$d cuvinte. %3$sMai adaugă puțin text%4$s.","Este cu puțin sub minimul recomandat de %5$d de cuvinte. %3$sMai adaugă puțin text%4$s."],"The meta description contains %1$d sentence %2$sover %3$s words%4$s. Try to shorten this sentence.":["Descrierea meta conține %1$d propoziție %2$scu peste %3$s de cuvinte%4$s. Încearcă să scurtezi această propoziție.","Descrierea meta conține %1$d propoziții %2$scu peste %3$s de cuvinte%4$s. Încearcă să scurtezi aceste propoziții.","Descrierea meta conține %1$d de propoziții %2$scu peste %3$s de cuvinte%4$s. Încearcă să scurtezi aceste propoziții."],"The meta description contains no sentences %1$sover %2$s words%3$s.":["Descrierea meta conține nicio propoziție %1$s cu peste %2$s de cuvinte%3$s."],"Mobile preview":["Previzualizare pe mobil"],"Desktop preview":["Previzualizare desktop"],"Please provide an SEO title by editing the snippet below.":["Te rog furnizează un titlu SEO prin editarea fragmentului de mai jos."],"Meta description preview:":["Previzualizare descriere meta:"],"Slug preview:":["Previzualizare descriptor:"],"SEO title preview:":["Previzualizare titlu SEO:"],"Close snippet editor":["Închide editor fragment"],"Slug":["Descriptor"],"Remove marks in the text":["Înlătură marcaje în text"],"Mark this result in the text":["Marchează acest rezultat în text"],"Marks are disabled in current view":["Marcajele sunt dezactivate în vizualizarea curentă"],"Good SEO score":["Punctaj SEO bun"],"OK SEO score":["Punctaj SEO OK"],"Feedback":["Impresii"],"ok":["OK"],"Please provide a meta description by editing the snippet below.":["Te rog furnizează o descriere meta prin editarea fragmentului de mai jos."],"Edit snippet":["Editează fragmentul"],"You can click on each element in the preview to jump to the Snippet Editor.":["Poți da clic pe fiecare element din previzualizare pentru a sări la editor fragment."],"SEO title":["Titlu SEO"],"Needs improvement":["Necesită îmbunătățire"],"Good":["bun"],"very difficult":["foarte dificil"],"Try to make shorter sentences, using less difficult words to improve readability":["Pentru a îmbunătăți lizibilitatea, încearcă să faci propoziții mai scurte, folosind cuvinte mai puțin dificile."],"difficult":["dificil"],"Try to make shorter sentences to improve readability":["Pentru a îmbunătăți lizibilitatea, încearcă să faci propoziții mai scurte."],"fairly difficult":["destul de dificil"],"OK":["OK"],"fairly easy":["destul de ușor"],"easy":["ușor"],"very easy":["foarte ușor"],"Meta description":["Descriere meta"]}}}
languages/wordpress-seojs-ro_RO.json CHANGED
@@ -1 +1 @@
1
- {"domain":"wordpress-seo","locale_data":{"wordpress-seo":{"":{"domain":"wordpress-seo","plural-forms":"nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);","lang":"ro"},"Google preview":["Previzualizare Google"],"When you click OK we will open our HelpScout beacon where you can find answers to your questions. This beacon will load our support data and also potentially set cookies.":["Când dai clic pe OK, vom deschide îndrumarul nostru HelpScout unde poți găsi răspunsuri la întrebările tale. Acest îndrumar va încărca datele noastre pentru suport și poate seta și cookie-uri."],"Schema":["Schema"],"Truly optimize your site for a local audience with our %s plugin! Optimized address details, opening hours, store locator and pickup option!":["Îți optimizezi cu adevărat situl pentru un public local cu modulul nostru %s! Detalii despre adresă și programul de funcționare optimizate și opțiuni pentru localizarea magazinului și preluarea comenzilor!"],"Serving local customers?":["Ai clienți locali?"],"Get the %s plugin now":["Ia modul %s acum"],"You can edit the details shown in meta data, like the social profiles, the name and the description of this user on their %1$s profile page.":["Poți edita detaliile afișate în metadate, cum ar fi profilurile sociale, numele și descrierea unui utilizator, pe pagina de profil %1$s."],"Select a user...":["Selectează un utilizator..."],"Name:":["Nume:"],"You have selected the user %1$s as the person this site represents. Their user profile information will now be used in search results. %2$sUpdate their profile to make sure the information is correct.%3$s":["Ai selectat utilizatorul %1$s drept persoana pe care acest sit o reprezintă. Informațiile despre profilul utilizatorului vor fi folosite acum în rezultatele de căutare. %2$sActualizează profilul utilizatorului pentru a te asigura că informațiile sunt corecte.%3$s"],"Error: Please select a user below to make your site's meta data complete.":["Eroare: te rog selectează un utilizator de mai jos pentru a completa metadatele sitului."],"New step added":["A fost adăugat un pas nou"],"New question added":["A fost adăugată o întrebare nouă"],"Did you know %s also analyzes the different word forms of your keyphrase, like plurals and past tenses?":["Știai că %s analizează și alte forme ale cuvintelor frazei cheie, cum ar fi pluralul și participiul trecut?"],"Help on choosing the perfect focus keyphrase":["Ajutor pentru alegerea frazei cheie perfecte"],"Would you like to add a related keyphrase?":["Vrei să adaugi o frază cheie similară?"],"Go %s!":["Fă %s!"],"Rank better with synonyms & related keyphrases":["Te clasezi mai sus cu fraze cheie sinonime și similare"],"Add related keyphrase":["Adaugă fraze cheie similare"],"Get %s":["Ia %s"],"Focus keyphrase":["Frază cheie"],"Learn more about the readability analysis":["Află mai multe despre analiza lizibilității"],"Describe the duration of the instruction:":["Descrie durata instruirii:"],"Optional. Customize how you want to describe the duration of the instruction":["Opțional. Personalizează cum vrei să descrii durata instruirii"],"%s, %s and %s":["%s, %s și %s"],"%s and %s":["%s și %s"],"%d minute":["1 minut","%d minute","%d de minute"],"%d hour":["O oră","%d ore","%d de ore"],"%d day":["O zi","%d zile","%d de zile"],"Enter a step title":["Introdu un titlu pentru pas"],"Optional. This can give you better control over the styling of the steps.":["Opțional. Acest lucru îți poate oferi un control mai bun asupra stilului pașilor."],"CSS class(es) to apply to the steps":["Clasă (clase) CSS de aplicat la pași"],"minutes":["minute"],"hours":["ore"],"days":["zile"],"Create a How-to guide in an SEO-friendly way. You can only use one How-to block per post.":["Creează un ghid de sfaturi practice într-o manieră prietenoasă pentru SEO. Poți folosi numai un singur bloc Sfaturi practice pentru fiecare articol."],"List your Frequently Asked Questions in an SEO-friendly way. You can only use one FAQ block per post.":["Afișează-ți întrebările frecvente într-o manieră prietenoasă pentru SEO. Poți folosi numai un singur bloc Întrebările frecvente pentru fiecare articol."],"Copy error":["Eroare text"],"An error occurred loading the %s primary taxonomy picker.":["A apărut o eroare la încărcarea selectorului taxonomiei principale %s."],"Time needed:":["Timp necesar:"],"Move question down":["Mută întrebarea în jos"],"Move question up":["Mută întrebarea în sus"],"Insert question":["Inserează întrebarea"],"Delete question":["Șterge întrebarea"],"Enter the answer to the question":["Introdu răspunsul la întrebare"],"Enter a question":["Introdu o întrebare"],"Add question":["Adaugă o întrebare"],"Frequently Asked Questions":["Întrebări frecvente"],"Great news: you can, with %s!":["Vești bune: poți, cu %s!"],"Select the primary %s":["Selectează %s principal"],"Mark as cornerstone content":["Fă-l conținut fundamental"],"Move step down":["Mută pasul în jos"],"Move step up":["Mută pasul în sus"],"Insert step":["Inserează pas"],"Delete step":["Șterge pasul"],"Add image":["Adaugă imagine"],"Enter a step description":["Introdu o descriere pentru pas"],"Enter a description":["Introdu o descriere"],"Unordered list":["Listă neordonată"],"Showing step items as an ordered list.":["Afișez elementele pasului ca listă ordonată."],"Showing step items as an unordered list":["Afișez elementele pasului ca listă neordonată."],"Add step":["Adaugă pas"],"Delete total time":["Șterge timpul total"],"Add total time":["Adaugă timp total"],"How to":["Sfaturi practice"],"How-to":["Sfaturi practice"],"Analysis results":["Rezultate analiză"],"Enter a focus keyphrase to calculate the SEO score":["Introdu o frază cheie pentru a calcula punctajul SEO"],"Learn more about Cornerstone Content.":["Află mai multe despre conținutul fundamental."],"Cornerstone content should be the most important and extensive articles on your site.":["Conținutul fundamental ar trebui să fie cele mai importante și mai ample articole de pe situl tău."],"Add synonyms":["Adaugă sinonime"],"Would you like to add keyphrase synonyms?":["Vrei să adaugi sinonime ale frazei cheie?"],"Current year":["Anul curent"],"Page":["Pagină"],"Tagline":["Slogan"],"Modify your meta description by editing it right here":["Modifică-ți descrierea meta editând-o chiar aici"],"ID":["ID"],"Separator":["Separator"],"Search phrase":["Frază de căutare"],"Term description":["Descriere termen"],"Tag description":["Descriere etichetă"],"Category description":["Descriere categorie"],"Primary category":["Categorie principală"],"Category":["Categorie"],"Excerpt only":["Numai rezumat"],"Excerpt":["Rezumat"],"Site title":["Titlu sit"],"Parent title":["Titlu părinte"],"Date":["Dată"],"24/7 email support":["Suport prin email non-stop (24/7)"],"SEO analysis":["Analiză SEO"],"Other benefits of %s for you:":["Alte avantaje ale %s pentru tine:"],"Cornerstone content":["Conținut fundamental"],"Superfast internal linking suggestions":["Sugestii de legare internă ultrarapidă"],"Great news: you can, with %1$s!":["Vești bune: poți, cu %1$s!"],"1 year free support and updates included!":["Sunt incluse suport și actualizări gratuite pentru un an!"],"%1$sSocial media preview%2$s: Facebook & Twitter":["%1$sPrevizualizare media socială%2$s: Facebook și Twitter"],"%1$sNo more dead links%2$s: easy redirect manager":["%1$sNicio legătură moartă%2$s: manager de redirecționări fără niciun efort"],"No ads!":["Fără anunțuri!"],"Please provide a meta description by editing the snippet below.":["Te rog furnizează o descriere meta prin editarea fragmentului de mai jos."],"The name of the person":["Numele persoanei"],"Readability analysis":["Analiză lizibilitate"],"Open":["Deschide"],"Title":["Titlu"],"Close":["Închide"],"FAQ":["Întrebări frecvente"],"Settings":["Setări"]}}}
1
+ {"domain":"wordpress-seo","locale_data":{"wordpress-seo":{"":{"domain":"wordpress-seo","plural-forms":"nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);","lang":"ro"},"Google preview":["Previzualizare Google"],"When you click OK we will open our HelpScout beacon where you can find answers to your questions. This beacon will load our support data and also potentially set cookies.":["Când dai clic pe OK, vom deschide îndrumarul nostru HelpScout unde poți găsi răspunsuri la întrebările tale. Acest îndrumar va încărca datele noastre pentru suport și poate seta și cookie-uri."],"Schema":["Schema"],"Truly optimize your site for a local audience with our %s plugin! Optimized address details, opening hours, store locator and pickup option!":["Îți optimizezi cu adevărat situl pentru un public local cu modulul nostru %s! Detalii despre adresă și programul de funcționare optimizate și opțiuni pentru localizarea magazinului și preluarea comenzilor!"],"Serving local customers?":["Ai clienți locali?"],"Get the %s plugin now":["Ia modul %s acum"],"You can edit the details shown in meta data, like the social profiles, the name and the description of this user on their %1$s profile page.":["Poți edita detaliile afișate în metadate, cum ar fi profilurile sociale, numele și descrierea unui utilizator, pe pagina de profil %1$s."],"Select a user...":["Selectează un utilizator..."],"Name:":["Nume:"],"You have selected the user %1$s as the person this site represents. Their user profile information will now be used in search results. %2$sUpdate their profile to make sure the information is correct.%3$s":["Ai selectat utilizatorul %1$s drept persoana pe care acest sit o reprezintă. Acum vor fi folosite în rezultatele de căutare informațiile din profilul utilizatorului. %2$sActualizează profilul utilizatorului pentru a te asigura că informațiile sunt corecte.%3$s"],"Error: Please select a user below to make your site's meta data complete.":["Eroare: te rog selectează un utilizator de mai jos pentru a completa metadatele sitului."],"New step added":["A fost adăugat un pas nou"],"New question added":["A fost adăugată o întrebare nouă"],"Did you know %s also analyzes the different word forms of your keyphrase, like plurals and past tenses?":["Știai că %s analizează și alte forme ale cuvintelor frazei cheie, cum ar fi pluralul și participiul trecut?"],"Help on choosing the perfect focus keyphrase":["Ajutor pentru alegerea frazei cheie perfecte"],"Would you like to add a related keyphrase?":["Vrei să adaugi o frază cheie similară?"],"Go %s!":["Fă %s!"],"Rank better with synonyms & related keyphrases":["Te clasezi mai sus cu fraze cheie sinonime și similare"],"Add related keyphrase":["Adaugă fraze cheie similare"],"Get %s":["Ia %s"],"Focus keyphrase":["Frază cheie"],"Learn more about the readability analysis":["Află mai multe despre analiza lizibilității"],"Describe the duration of the instruction:":["Descrie durata instruirii:"],"Optional. Customize how you want to describe the duration of the instruction":["Opțional. Personalizează cum vrei să descrii durata instruirii"],"%s, %s and %s":["%s, %s și %s"],"%s and %s":["%s și %s"],"%d minute":["1 minut","%d minute","%d de minute"],"%d hour":["O oră","%d ore","%d de ore"],"%d day":["O zi","%d zile","%d de zile"],"Enter a step title":["Introdu un titlu pentru pas"],"Optional. This can give you better control over the styling of the steps.":["Opțional. Acest lucru îți poate oferi un control mai bun asupra stilului pașilor."],"CSS class(es) to apply to the steps":["Clasă (clase) CSS de aplicat la pași"],"minutes":["minute"],"hours":["ore"],"days":["zile"],"Create a How-to guide in an SEO-friendly way. You can only use one How-to block per post.":["Creează un ghid de sfaturi practice într-o manieră prietenoasă pentru SEO. Poți folosi numai un singur bloc Sfaturi practice pentru fiecare articol."],"List your Frequently Asked Questions in an SEO-friendly way. You can only use one FAQ block per post.":["Afișează-ți întrebările frecvente într-o manieră prietenoasă pentru SEO. Poți folosi numai un singur bloc Întrebările frecvente pentru fiecare articol."],"Copy error":["Eroare text"],"An error occurred loading the %s primary taxonomy picker.":["A apărut o eroare la încărcarea selectorului taxonomiei principale %s."],"Time needed:":["Timp necesar:"],"Move question down":["Mută întrebarea în jos"],"Move question up":["Mută întrebarea în sus"],"Insert question":["Inserează întrebarea"],"Delete question":["Șterge întrebarea"],"Enter the answer to the question":["Introdu răspunsul la întrebare"],"Enter a question":["Introdu o întrebare"],"Add question":["Adaugă o întrebare"],"Frequently Asked Questions":["Întrebări frecvente"],"Great news: you can, with %s!":["Vești bune: poți, cu %s!"],"Select the primary %s":["Selectează %s principal"],"Mark as cornerstone content":["Fă-l conținut fundamental"],"Move step down":["Mută pasul în jos"],"Move step up":["Mută pasul în sus"],"Insert step":["Inserează pas"],"Delete step":["Șterge pasul"],"Add image":["Adaugă imagine"],"Enter a step description":["Introdu o descriere pentru pas"],"Enter a description":["Introdu o descriere"],"Unordered list":["Listă neordonată"],"Showing step items as an ordered list.":["Afișez elementele pasului ca listă ordonată."],"Showing step items as an unordered list":["Afișez elementele pasului ca listă neordonată."],"Add step":["Adaugă pas"],"Delete total time":["Șterge timpul total"],"Add total time":["Adaugă timp total"],"How to":["Sfaturi practice"],"How-to":["Sfaturi practice"],"Analysis results":["Rezultate analiză"],"Enter a focus keyphrase to calculate the SEO score":["Introdu o frază cheie pentru a calcula punctajul SEO"],"Learn more about Cornerstone Content.":["Află mai multe despre conținutul fundamental."],"Cornerstone content should be the most important and extensive articles on your site.":["Conținutul fundamental ar trebui să fie cele mai importante și mai ample articole de pe situl tău."],"Add synonyms":["Adaugă sinonime"],"Would you like to add keyphrase synonyms?":["Vrei să adaugi sinonime ale frazei cheie?"],"Current year":["Anul curent"],"Page":["Pagină"],"Tagline":["Slogan"],"Modify your meta description by editing it right here":["Modifică-ți descrierea meta editând-o chiar aici"],"ID":["ID"],"Separator":["Separator"],"Search phrase":["Frază de căutare"],"Term description":["Descriere termen"],"Tag description":["Descriere etichetă"],"Category description":["Descriere categorie"],"Primary category":["Categorie principală"],"Category":["Categorie"],"Excerpt only":["Numai rezumat"],"Excerpt":["Rezumat"],"Site title":["Titlu sit"],"Parent title":["Titlu părinte"],"Date":["Dată"],"24/7 email support":["Suport prin email non-stop (24/7)"],"SEO analysis":["Analiză SEO"],"Other benefits of %s for you:":["Alte avantaje ale %s pentru tine:"],"Cornerstone content":["Conținut fundamental"],"Superfast internal linking suggestions":["Sugestii de legare internă ultrarapidă"],"Great news: you can, with %1$s!":["Vești bune: poți, cu %1$s!"],"1 year free support and updates included!":["Sunt incluse suport și actualizări gratuite pentru un an!"],"%1$sSocial media preview%2$s: Facebook & Twitter":["%1$sPrevizualizare media socială%2$s: Facebook și Twitter"],"%1$sNo more dead links%2$s: easy redirect manager":["%1$sNicio legătură moartă%2$s: manager de redirecționări fără niciun efort"],"No ads!":["Fără anunțuri!"],"Please provide a meta description by editing the snippet below.":["Te rog furnizează o descriere meta prin editarea fragmentului de mai jos."],"The name of the person":["Numele persoanei"],"Readability analysis":["Analiză lizibilitate"],"Open":["Deschide"],"Title":["Titlu"],"Close":["Închide"],"FAQ":["Întrebări frecvente"],"Settings":["Setări"]}}}
lib/orm.php CHANGED
@@ -223,12 +223,11 @@ class ORM implements \ArrayAccess {
223
  * Factory method, return an instance of this class bound to the supplied
224
  * table name.
225
  *
226
- * A repeat of content in parent::for_table, so that created class is
227
- * ORMWrapper, not ORM.
228
  *
229
- * @param string $table_name Table name. The table to create instance for.
230
  *
231
- * @return ORM Instance of the ORM wrapper.
232
  */
233
  public static function for_table( $table_name ) {
234
  return new static( $table_name, [] );
223
  * Factory method, return an instance of this class bound to the supplied
224
  * table name.
225
  *
226
+ * A repeat of content in parent::for_table, so that created class is ORM.
 
227
  *
228
+ * @param string $table_name The table to create instance for.
229
  *
230
+ * @return ORM Instance of the ORM.
231
  */
232
  public static function for_table( $table_name ) {
233
  return new static( $table_name, [] );
lib/ruckusing-adapter.php CHANGED
@@ -62,6 +62,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
62
  * @var boolean
63
  */
64
  private $_in_trx = false;
 
65
  /**
66
  * Creates an instance of Ruckusing_Adapter.
67
  *
@@ -72,6 +73,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
72
  public function __construct( $config ) {
73
  $this->set_dsn( $config );
74
  }
 
75
  /**
76
  * Get the current db name
77
  *
@@ -79,8 +81,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
79
  */
80
  public function get_database_name() {
81
  global $wpdb;
 
82
  return $wpdb->dbname;
83
  }
 
84
  /**
85
  * Check support for migrations
86
  *
@@ -89,15 +93,43 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
89
  public function supports_migrations() {
90
  return true;
91
  }
 
92
  /**
93
  * Get the column native types
94
  *
95
  * @return array
96
  */
97
  public function native_database_types() {
98
- $types = [ 'primary_key' => [ 'name' => 'integer', 'limit' => 11, 'null' => false ], 'string' => [ 'name' => 'varchar', 'limit' => 255 ], 'text' => [ 'name' => 'text' ], 'tinytext' => [ 'name' => 'tinytext' ], 'mediumtext' => [ 'name' => 'mediumtext' ], 'integer' => [ 'name' => 'int', 'limit' => 11 ], 'tinyinteger' => [ 'name' => 'tinyint' ], 'smallinteger' => [ 'name' => 'smallint' ], 'mediuminteger' => [ 'name' => 'mediumint' ], 'biginteger' => [ 'name' => 'bigint' ], 'float' => [ 'name' => 'float' ], 'decimal' => [ 'name' => 'decimal', 'scale' => 0, 'precision' => 10 ], 'datetime' => [ 'name' => 'datetime' ], 'timestamp' => [ 'name' => 'timestamp' ], 'time' => [ 'name' => 'time' ], 'date' => [ 'name' => 'date' ], 'binary' => [ 'name' => 'blob' ], 'tinybinary' => [ 'name' => 'tinyblob' ], 'mediumbinary' => [ 'name' => 'mediumblob' ], 'longbinary' => [ 'name' => 'longblob' ], 'boolean' => [ 'name' => 'tinyint', 'limit' => 1 ], 'enum' => [ 'name' => 'enum', 'values' => [] ], 'uuid' => [ 'name' => 'char', 'limit' => 36 ], 'char' => [ 'name' => 'char' ] ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  return $types;
100
  }
 
101
  /**
102
  * Create the schema table, if necessary
103
  */
@@ -109,6 +141,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
109
  $this->add_index( $this->get_schema_version_table_name(), 'version', [ 'unique' => true ] );
110
  }
111
  }
 
112
  /**
113
  * Start Transaction
114
  */
@@ -117,6 +150,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
117
  $this->beginTransaction();
118
  }
119
  }
 
120
  /**
121
  * Commit Transaction
122
  */
@@ -125,6 +159,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
125
  $this->commit();
126
  }
127
  }
 
128
  /**
129
  * Rollback Transaction
130
  */
@@ -133,15 +168,18 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
133
  $this->rollback();
134
  }
135
  }
 
136
  /**
137
  * Quote a table name string
138
  *
139
  * @param string $str table name.
 
140
  * @return string
141
  */
142
  public function quote_table( $str ) {
143
  return '`' . $str . '`';
144
  }
 
145
  /**
146
  * Column definition
147
  *
@@ -153,9 +191,11 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
153
  */
154
  public function column_definition( $column_name, $type, $options = null ) {
155
  $col = new Ruckusing_Adapter_ColumnDefinition( $this, $column_name, $type, $options );
 
156
  return $col->__toString();
157
  }
158
  // -------- DATABASE LEVEL OPERATIONS
 
159
  /**
160
  * Check if a db exists
161
  *
@@ -164,7 +204,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
164
  * @return boolean
165
  */
166
  public function database_exists( $db ) {
167
- $ddl = 'SHOW DATABASES';
168
  $result = $this->select_all( $ddl );
169
  if ( \count( $result ) == 0 ) {
170
  return false;
@@ -174,8 +214,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
174
  return true;
175
  }
176
  }
 
177
  return false;
178
  }
 
179
  /**
180
  * Create a database
181
  *
@@ -187,10 +229,12 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
187
  if ( $this->database_exists( $db ) ) {
188
  return false;
189
  }
190
- $ddl = \sprintf( 'CREATE DATABASE %s', $this->identifier( $db ) );
191
  $result = $this->query( $ddl );
 
192
  return $result === true;
193
  }
 
194
  /**
195
  * Drop a database
196
  *
@@ -202,10 +246,12 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
202
  if ( ! $this->database_exists( $db ) ) {
203
  return false;
204
  }
205
- $ddl = \sprintf( 'DROP DATABASE IF EXISTS %s', $this->identifier( $db ) );
206
  $result = $this->query( $ddl );
 
207
  return $result === true;
208
  }
 
209
  /**
210
  * Dump the complete schema of the DB. This is really just all of the
211
  * CREATE TABLE statements for all of the tables in the DB.
@@ -224,7 +270,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
224
  if ( $tbl == 'schema_info' ) {
225
  continue;
226
  }
227
- $stmt = \sprintf( 'SHOW CREATE TABLE %s', $this->identifier( $tbl ) );
228
  $result = $this->query( $stmt );
229
  if ( \is_array( $result ) && \count( $result ) == 1 ) {
230
  $row = $result[0];
@@ -238,8 +284,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
238
  }
239
  }
240
  $data = $final . $views;
 
241
  return \file_put_contents( $output_file, $data, \LOCK_EX );
242
  }
 
243
  /**
244
  * Check if a table exists
245
  *
@@ -249,9 +297,23 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
249
  * @return boolean
250
  */
251
  public function table_exists( $tbl, $reload_tables = false ) {
252
- $this->load_tables( $reload_tables );
253
- return \array_key_exists( $tbl, $this->_tables );
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  }
 
255
  /**
256
  * Wrapper to execute a query
257
  *
@@ -262,24 +324,26 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
262
  public function execute( $query ) {
263
  return $this->query( $query );
264
  }
 
265
  /**
266
  * Execute a query
267
  *
268
  * @param string $query query to run
269
  *
270
- * @throws Ruckusing_Exception
271
  * @return boolean
 
272
  */
273
  public function query( $query ) {
274
  global $wpdb;
275
 
276
  $query_type = $this->determine_query_type( $query );
277
- $data = [];
278
  if ( $query_type == SQL_SELECT || $query_type == SQL_SHOW ) {
279
  $data = $wpdb->get_results( $query, ARRAY_A );
280
  if ( $this->isError( $data ) ) {
281
  throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
282
  }
 
283
  return $data;
284
  } else {
285
  // INSERT, DELETE, etc...
@@ -290,30 +354,34 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
290
  if ( $query_type == SQL_INSERT ) {
291
  return $wpdb->insert_id;
292
  }
 
293
  return true;
294
  }
295
  }
 
296
  /**
297
  * Execute several queries
298
  *
299
  * @param string $queries queries to run
300
  *
301
- * @throws Ruckusing_Exception
302
  * @return boolean
 
303
  */
304
  public function multi_query( $queries ) {
305
  if ( \defined( 'YOAST_ENVIRONMENT' ) && YOAST_ENVIRONMENT !== 'production' ) {
306
  throw new Ruckusing_Exception( 'WPDB does not support multi_query.', Ruckusing_Exception::QUERY_ERROR );
307
  }
 
308
  return false;
309
  }
 
310
  /**
311
  * Select one
312
  *
313
  * @param string $query query to run
314
  *
315
- * @throws Ruckusing_Exception
316
  * @return array
 
317
  */
318
  public function select_one( $query ) {
319
  global $wpdb;
@@ -324,11 +392,13 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
324
  if ( $this->isError( $res ) ) {
325
  throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
326
  }
 
327
  return $wpdb->last_result;
328
  } else {
329
  throw new Ruckusing_Exception( "Query for select_one() is not one of SELECT or SHOW: {$query}", Ruckusing_Exception::QUERY_ERROR );
330
  }
331
  }
 
332
  /**
333
  * Select all
334
  *
@@ -339,6 +409,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
339
  public function select_all( $query ) {
340
  return $this->query( $query );
341
  }
 
342
  /**
343
  * Use this method for non-SELECT queries
344
  * Or anything where you dont necessarily expect a result string, e.g. DROPs, CREATEs, etc.
@@ -349,8 +420,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
349
  */
350
  public function execute_ddl( $ddl ) {
351
  $result = $this->query( $ddl );
 
352
  return true;
353
  }
 
354
  /**
355
  * Drop table
356
  *
@@ -359,20 +432,24 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
359
  * @return boolean
360
  */
361
  public function drop_table( $tbl ) {
362
- $ddl = \sprintf( 'DROP TABLE IF EXISTS %s', $this->identifier( $tbl ) );
363
  $result = $this->query( $ddl );
 
364
  return true;
365
  }
 
366
  /**
367
  * Create table
368
  *
369
  * @param string $table_name the table name
370
- * @param array $options the options
 
371
  * @return bool|Ruckusing_Adapter_MySQL_TableDefinition
372
  */
373
  public function create_table( $table_name, $options = [] ) {
374
  return new Ruckusing_Adapter_MySQL_TableDefinition( $this, $table_name, $options );
375
  }
 
376
  /**
377
  * Escape a string for mysql
378
  *
@@ -382,8 +459,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
382
  */
383
  public function quote_string( $str ) {
384
  global $wpdb;
 
385
  return $wpdb->_escape( $str );
386
  }
 
387
  /**
388
  * Quote a string
389
  *
@@ -394,6 +473,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
394
  public function identifier( $str ) {
395
  return '`' . $str . '`';
396
  }
 
397
  /**
398
  * Quote a string
399
  *
@@ -405,14 +485,15 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
405
  public function quote( $value, $column = null ) {
406
  return $this->quote_string( $value );
407
  }
 
408
  /**
409
  * Rename a table
410
  *
411
- * @param string $name the current table name
412
  * @param string $new_name the new table name
413
  *
414
- * @throws Ruckusing_Exception
415
  * @return boolean
 
416
  */
417
  public function rename_table( $name, $new_name ) {
418
  if ( empty( $name ) ) {
@@ -422,19 +503,21 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
422
  throw new Ruckusing_Exception( 'Missing new column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
423
  }
424
  $sql = \sprintf( 'RENAME TABLE %s TO %s', $this->identifier( $name ), $this->identifier( $new_name ) );
 
425
  return $this->execute_ddl( $sql );
426
  }
427
  // create_table
 
428
  /**
429
  * Add a column
430
  *
431
- * @param string $table_name the table name
432
  * @param string $column_name the column name
433
- * @param string $type the column type
434
- * @param array $options column options
435
  *
436
- * @throws Ruckusing_Exception
437
  * @return boolean
 
438
  */
439
  public function add_column( $table_name, $column_name, $type, $options = [] ) {
440
  if ( empty( $table_name ) ) {
@@ -458,9 +541,11 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
458
  }
459
  $sql = \sprintf( 'ALTER TABLE %s ADD `%s` %s', $this->identifier( $table_name ), $column_name, $this->type_to_sql( $type, $options ) );
460
  $sql .= $this->add_column_options( $type, $options );
 
461
  return $this->execute_ddl( $sql );
462
  }
463
  // add_column
 
464
  /**
465
  * Drop a column
466
  *
@@ -471,18 +556,20 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
471
  */
472
  public function remove_column( $table_name, $column_name ) {
473
  $sql = \sprintf( 'ALTER TABLE %s DROP COLUMN %s', $this->identifier( $table_name ), $this->identifier( $column_name ) );
 
474
  return $this->execute_ddl( $sql );
475
  }
476
  // remove_column
 
477
  /**
478
  * Rename a column
479
  *
480
- * @param string $table_name the table name
481
- * @param string $column_name the column name
482
  * @param string $new_column_name the new column name
483
  *
484
- * @throws Ruckusing_Exception
485
  * @return boolean
 
486
  */
487
  public function rename_column( $table_name, $column_name, $new_column_name ) {
488
  if ( empty( $table_name ) ) {
@@ -494,23 +581,25 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
494
  if ( empty( $new_column_name ) ) {
495
  throw new Ruckusing_Exception( 'Missing new column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
496
  }
497
- $column_info = $this->column_info( $table_name, $column_name );
498
  $current_type = $column_info['type'];
499
- $sql = \sprintf( 'ALTER TABLE %s CHANGE %s %s %s', $this->identifier( $table_name ), $this->identifier( $column_name ), $this->identifier( $new_column_name ), $current_type );
500
- $sql .= $this->add_column_options( $current_type, $column_info );
 
501
  return $this->execute_ddl( $sql );
502
  }
503
  // rename_column
 
504
  /**
505
  * Change a column
506
  *
507
- * @param string $table_name the table name
508
  * @param string $column_name the column name
509
- * @param string $type the column type
510
- * @param array $options column options
511
  *
512
- * @throws Ruckusing_Exception
513
  * @return boolean
 
514
  */
515
  public function change_column( $table_name, $column_name, $type, $options = [] ) {
516
  if ( empty( $table_name ) ) {
@@ -535,17 +624,19 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
535
  }
536
  $sql = \sprintf( 'ALTER TABLE `%s` CHANGE `%s` `%s` %s', $table_name, $column_name, $column_name, $this->type_to_sql( $type, $options ) );
537
  $sql .= $this->add_column_options( $type, $options );
 
538
  return $this->execute_ddl( $sql );
539
  }
540
  // change_column
 
541
  /**
542
  * Get a column info
543
  *
544
- * @param string $table the table name
545
  * @param string $column the column name
546
  *
547
- * @throws Ruckusing_Exception
548
  * @return array
 
549
  */
550
  public function column_info( $table, $column ) {
551
  if ( empty( $table ) ) {
@@ -555,26 +646,28 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
555
  throw new Ruckusing_Exception( 'Missing original column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
556
  }
557
  try {
558
- $sql = \sprintf( "SHOW FULL COLUMNS FROM %s LIKE '%s'", $this->identifier( $table ), $column );
559
  $result = $this->select_one( $sql );
560
  if ( \is_array( $result ) ) {
561
  // lowercase key names
562
  $result = \array_change_key_case( $result, \CASE_LOWER );
563
  }
 
564
  return $result;
565
- } catch (\Exception $e) {
566
  return null;
567
  }
568
  }
 
569
  /**
570
  * Add an index
571
  *
572
- * @param string $table_name the table name
573
  * @param string $column_name the column name
574
- * @param array $options index options
575
  *
576
- * @throws Ruckusing_Exception
577
  * @return boolean
 
578
  */
579
  public function add_index( $table_name, $column_name, $options = [] ) {
580
  if ( empty( $table_name ) ) {
@@ -612,17 +705,19 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
612
  $cols[] = $this->identifier( $name );
613
  }
614
  $sql = \sprintf( 'CREATE %sINDEX %s ON %s(%s)', $unique ? 'UNIQUE ' : '', $this->identifier( $index_name ), $this->identifier( $table_name ), \join( ', ', $cols ) );
 
615
  return $this->execute_ddl( $sql );
616
  }
 
617
  /**
618
  * Drop an index
619
  *
620
- * @param string $table_name the table name
621
  * @param string $column_name the column name
622
- * @param array $options index options
623
  *
624
- * @throws Ruckusing_Exception
625
  * @return boolean
 
626
  */
627
  public function remove_index( $table_name, $column_name, $options = [] ) {
628
  if ( empty( $table_name ) ) {
@@ -638,8 +733,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
638
  $index_name = Ruckusing_Util_Naming::index_name( $table_name, $column_name );
639
  }
640
  $sql = \sprintf( 'DROP INDEX %s ON %s', $this->identifier( $index_name ), $this->identifier( $table_name ) );
 
641
  return $this->execute_ddl( $sql );
642
  }
 
643
  /**
644
  * Add timestamps
645
  *
@@ -660,9 +757,15 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
660
  throw new Ruckusing_Exception( 'Missing updated at column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
661
  }
662
  $created_at = $this->add_column( $table_name, $created_column_name, 'datetime' );
663
- $updated_at = $this->add_column( $table_name, $updated_column_name, 'timestamp', [ 'null' => false, 'default' => 'CURRENT_TIMESTAMP', 'extra' => 'ON UPDATE CURRENT_TIMESTAMP' ] );
 
 
 
 
 
664
  return $created_at && $updated_at;
665
  }
 
666
  /**
667
  * Remove timestamps
668
  *
@@ -684,17 +787,19 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
684
  }
685
  $updated_at = $this->remove_column( $table_name, $created_column_name );
686
  $created_at = $this->remove_column( $table_name, $updated_column_name );
 
687
  return $created_at && $updated_at;
688
  }
 
689
  /**
690
  * Check an index
691
  *
692
- * @param string $table_name the table name
693
  * @param string $column_name the column name
694
- * @param array $options index options
695
  *
696
- * @throws Ruckusing_Exception
697
  * @return boolean
 
698
  */
699
  public function has_index( $table_name, $column_name, $options = [] ) {
700
  if ( empty( $table_name ) ) {
@@ -715,8 +820,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
715
  return true;
716
  }
717
  }
 
718
  return false;
719
  }
 
720
  /**
721
  * Return all indexes of a table
722
  *
@@ -725,8 +832,8 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
725
  * @return array
726
  */
727
  public function indexes( $table_name ) {
728
- $sql = \sprintf( 'SHOW KEYS FROM %s', $this->identifier( $table_name ) );
729
- $result = $this->select_all( $sql );
730
  $indexes = [];
731
  $cur_idx = null;
732
  foreach ( $result as $row ) {
@@ -734,11 +841,13 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
734
  if ( $row['Key_name'] == 'PRIMARY' ) {
735
  continue;
736
  }
737
- $cur_idx = $row['Key_name'];
738
  $indexes[] = [ 'name' => $row['Key_name'], 'unique' => (int) $row['Non_unique'] == 0 ? true : false ];
739
  }
 
740
  return $indexes;
741
  }
 
742
  /**
743
  * Convert type to sql
744
  * $limit = null, $precision = null, $scale = null
@@ -746,8 +855,8 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
746
  * @param string $type the native type
747
  * @param array $options
748
  *
749
- * @throws Ruckusing_Exception
750
  * @return string
 
751
  */
752
  public function type_to_sql( $type, $options = [] ) {
753
  $natives = $this->native_database_types();
@@ -764,9 +873,9 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
764
  }
765
  throw new Ruckusing_Exception( $error, Ruckusing_Exception::INVALID_ARGUMENT );
766
  }
767
- $scale = null;
768
  $precision = null;
769
- $limit = null;
770
  if ( isset( $options['precision'] ) ) {
771
  $precision = $options['precision'];
772
  }
@@ -831,7 +940,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
831
  if ( empty( $values ) ) {
832
  throw new Ruckusing_Exception( 'Error adding enum column: there must be at least one value defined', Ruckusing_Exception::INVALID_ARGUMENT );
833
  } else {
834
- $column_type_sql .= \sprintf( "('%s')", \implode( "','", \array_map( [ $this, 'quote_string' ], $values ) ) );
 
 
 
835
  }
836
  }
837
  // not a decimal column
@@ -841,16 +953,18 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
841
  if ( $limit ) {
842
  $column_type_sql .= \sprintf( '(%d)', $limit );
843
  }
 
844
  return $column_type_sql;
845
  }
 
846
  /**
847
  * Add column options
848
  *
849
  * @param string $type the native type
850
  * @param array $options
851
  *
852
- * @throws Ruckusing_Exception
853
  * @return string
 
854
  */
855
  public function add_column_options( $type, $options ) {
856
  $sql = '';
@@ -884,7 +998,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
884
  $default_format = "'%s'";
885
  }
886
  $default_value = \sprintf( $default_format, $options['default'] );
887
- $sql .= \sprintf( ' DEFAULT %s', $default_value );
888
  }
889
  if ( \array_key_exists( 'null', $options ) ) {
890
  if ( $options['null'] === false || $options['null'] === 'NO' ) {
@@ -902,8 +1016,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
902
  if ( \array_key_exists( 'after', $options ) ) {
903
  $sql .= \sprintf( ' AFTER %s', $this->identifier( $options['after'] ) );
904
  }
 
905
  return $sql;
906
  }
 
907
  /**
908
  * Set current version
909
  *
@@ -913,8 +1029,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
913
  */
914
  public function set_current_version( $version ) {
915
  $sql = \sprintf( "INSERT INTO %s (version) VALUES ('%s')", $this->get_schema_version_table_name(), $version );
 
916
  return $this->execute_ddl( $sql );
917
  }
 
918
  /**
919
  * remove a version
920
  *
@@ -924,8 +1042,10 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
924
  */
925
  public function remove_version( $version ) {
926
  $sql = \sprintf( "DELETE FROM %s WHERE version = '%s'", $this->get_schema_version_table_name(), $version );
 
927
  return $this->execute_ddl( $sql );
928
  }
 
929
  /**
930
  * Return a message displaying the current version
931
  *
@@ -947,6 +1067,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
947
  private function isError( $o ) {
948
  return $o === false;
949
  }
 
950
  /**
951
  * Initialize an array of table names
952
  *
@@ -959,17 +1080,18 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
959
  $this->_tables = [];
960
  // clear existing structure
961
  $query = 'SHOW TABLES';
962
- $res = $wpdb->get_results( $query, \ARRAY_N );
963
  // check for errors
964
  if ( $this->isError( $res ) ) {
965
  throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
966
  }
967
  foreach ( $res as $row ) {
968
- $table = $row[0];
969
  $this->_tables[ $table ] = true;
970
  }
971
  }
972
  }
 
973
  /**
974
  * Check query type
975
  *
@@ -1007,20 +1129,24 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
1007
  return SQL_UNKNOWN_QUERY_TYPE;
1008
  }
1009
  }
 
1010
  /**
1011
  * Check query type
1012
  *
1013
  * @param $query_type
1014
- * @internal param string $query query to run
1015
  *
1016
  * @return boolean
 
 
1017
  */
1018
  private function is_select( $query_type ) {
1019
  if ( $query_type == SQL_SELECT ) {
1020
  return true;
1021
  }
 
1022
  return false;
1023
  }
 
1024
  /**
1025
  * Detect whether or not the string represents a function call and if so
1026
  * do not wrap it in single-quotes, otherwise do wrap in single quotes.
@@ -1031,12 +1157,13 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
1031
  */
1032
  private function is_sql_method_call( $str ) {
1033
  $str = \trim( $str );
1034
- if ( \substr( $str, -2, 2 ) == '()' ) {
1035
  return true;
1036
  } else {
1037
  return false;
1038
  }
1039
  }
 
1040
  /**
1041
  * Check if in transaction
1042
  *
@@ -1045,6 +1172,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
1045
  private function inTransaction() {
1046
  return $this->_in_trx;
1047
  }
 
1048
  /**
1049
  * Start transaction
1050
  */
@@ -1057,6 +1185,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
1057
  $wpdb->query( 'START TRANSACTION' );
1058
  $this->_in_trx = true;
1059
  }
 
1060
  /**
1061
  * Commit a transaction
1062
  */
@@ -1069,6 +1198,7 @@ class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusin
1069
  $wpdb->query( 'COMMIT' );
1070
  $this->_in_trx = false;
1071
  }
 
1072
  /**
1073
  * Rollback a transaction
1074
  */
62
  * @var boolean
63
  */
64
  private $_in_trx = false;
65
+
66
  /**
67
  * Creates an instance of Ruckusing_Adapter.
68
  *
73
  public function __construct( $config ) {
74
  $this->set_dsn( $config );
75
  }
76
+
77
  /**
78
  * Get the current db name
79
  *
81
  */
82
  public function get_database_name() {
83
  global $wpdb;
84
+
85
  return $wpdb->dbname;
86
  }
87
+
88
  /**
89
  * Check support for migrations
90
  *
93
  public function supports_migrations() {
94
  return true;
95
  }
96
+
97
  /**
98
  * Get the column native types
99
  *
100
  * @return array
101
  */
102
  public function native_database_types() {
103
+ $types = [
104
+ 'primary_key' => [ 'name' => 'integer', 'limit' => 11, 'null' => false ],
105
+ 'string' => [ 'name' => 'varchar', 'limit' => 255 ],
106
+ 'text' => [ 'name' => 'text' ],
107
+ 'tinytext' => [ 'name' => 'tinytext' ],
108
+ 'mediumtext' => [ 'name' => 'mediumtext' ],
109
+ 'integer' => [ 'name' => 'int', 'limit' => 11 ],
110
+ 'tinyinteger' => [ 'name' => 'tinyint' ],
111
+ 'smallinteger' => [ 'name' => 'smallint' ],
112
+ 'mediuminteger' => [ 'name' => 'mediumint' ],
113
+ 'biginteger' => [ 'name' => 'bigint' ],
114
+ 'float' => [ 'name' => 'float' ],
115
+ 'decimal' => [ 'name' => 'decimal', 'scale' => 0, 'precision' => 10 ],
116
+ 'datetime' => [ 'name' => 'datetime' ],
117
+ 'timestamp' => [ 'name' => 'timestamp' ],
118
+ 'time' => [ 'name' => 'time' ],
119
+ 'date' => [ 'name' => 'date' ],
120
+ 'binary' => [ 'name' => 'blob' ],
121
+ 'tinybinary' => [ 'name' => 'tinyblob' ],
122
+ 'mediumbinary' => [ 'name' => 'mediumblob' ],
123
+ 'longbinary' => [ 'name' => 'longblob' ],
124
+ 'boolean' => [ 'name' => 'tinyint', 'limit' => 1 ],
125
+ 'enum' => [ 'name' => 'enum', 'values' => [] ],
126
+ 'uuid' => [ 'name' => 'char', 'limit' => 36 ],
127
+ 'char' => [ 'name' => 'char' ]
128
+ ];
129
+
130
  return $types;
131
  }
132
+
133
  /**
134
  * Create the schema table, if necessary
135
  */
141
  $this->add_index( $this->get_schema_version_table_name(), 'version', [ 'unique' => true ] );
142
  }
143
  }
144
+
145
  /**
146
  * Start Transaction
147
  */
150
  $this->beginTransaction();
151
  }
152
  }
153
+
154
  /**
155
  * Commit Transaction
156
  */
159
  $this->commit();
160
  }
161
  }
162
+
163
  /**
164
  * Rollback Transaction
165
  */
168
  $this->rollback();
169
  }
170
  }
171
+
172
  /**
173
  * Quote a table name string
174
  *
175
  * @param string $str table name.
176
+ *
177
  * @return string
178
  */
179
  public function quote_table( $str ) {
180
  return '`' . $str . '`';
181
  }
182
+
183
  /**
184
  * Column definition
185
  *
191
  */
192
  public function column_definition( $column_name, $type, $options = null ) {
193
  $col = new Ruckusing_Adapter_ColumnDefinition( $this, $column_name, $type, $options );
194
+
195
  return $col->__toString();
196
  }
197
  // -------- DATABASE LEVEL OPERATIONS
198
+
199
  /**
200
  * Check if a db exists
201
  *
204
  * @return boolean
205
  */
206
  public function database_exists( $db ) {
207
+ $ddl = 'SHOW DATABASES';
208
  $result = $this->select_all( $ddl );
209
  if ( \count( $result ) == 0 ) {
210
  return false;
214
  return true;
215
  }
216
  }
217
+
218
  return false;
219
  }
220
+
221
  /**
222
  * Create a database
223
  *
229
  if ( $this->database_exists( $db ) ) {
230
  return false;
231
  }
232
+ $ddl = \sprintf( 'CREATE DATABASE %s', $this->identifier( $db ) );
233
  $result = $this->query( $ddl );
234
+
235
  return $result === true;
236
  }
237
+
238
  /**
239
  * Drop a database
240
  *
246
  if ( ! $this->database_exists( $db ) ) {
247
  return false;
248
  }
249
+ $ddl = \sprintf( 'DROP DATABASE IF EXISTS %s', $this->identifier( $db ) );
250
  $result = $this->query( $ddl );
251
+
252
  return $result === true;
253
  }
254
+
255
  /**
256
  * Dump the complete schema of the DB. This is really just all of the
257
  * CREATE TABLE statements for all of the tables in the DB.
270
  if ( $tbl == 'schema_info' ) {
271
  continue;
272
  }
273
+ $stmt = \sprintf( 'SHOW CREATE TABLE %s', $this->identifier( $tbl ) );
274
  $result = $this->query( $stmt );
275
  if ( \is_array( $result ) && \count( $result ) == 1 ) {
276
  $row = $result[0];
284
  }
285
  }
286
  $data = $final . $views;
287
+
288
  return \file_put_contents( $output_file, $data, \LOCK_EX );
289
  }
290
+
291
  /**
292
  * Check if a table exists
293
  *
297
  * @return boolean
298
  */
299
  public function table_exists( $tbl, $reload_tables = false ) {
300
+ global $wpdb;
301
+
302
+ // We need last error to be clear so we can check against it easily.
303
+ $previous_last_error = $wpdb->last_error;
304
+ $previous_suppress_errors = $wpdb->suppress_errors;
305
+ $wpdb->last_error = '';
306
+ $wpdb->suppress_errors = true;
307
+
308
+ $result = $wpdb->query( "SELECT * FROM $tbl LIMIT 1" );
309
+
310
+ // Restore the last error, as this is not truly an error and we don't want to alarm people.
311
+ $wpdb->last_error = $previous_last_error;
312
+ $wpdb->suppress_errors = $previous_suppress_errors;
313
+
314
+ return $result !== false;
315
  }
316
+
317
  /**
318
  * Wrapper to execute a query
319
  *
324
  public function execute( $query ) {
325
  return $this->query( $query );
326
  }
327
+
328
  /**
329
  * Execute a query
330
  *
331
  * @param string $query query to run
332
  *
 
333
  * @return boolean
334
+ * @throws Ruckusing_Exception
335
  */
336
  public function query( $query ) {
337
  global $wpdb;
338
 
339
  $query_type = $this->determine_query_type( $query );
340
+ $data = [];
341
  if ( $query_type == SQL_SELECT || $query_type == SQL_SHOW ) {
342
  $data = $wpdb->get_results( $query, ARRAY_A );
343
  if ( $this->isError( $data ) ) {
344
  throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
345
  }
346
+
347
  return $data;
348
  } else {
349
  // INSERT, DELETE, etc...
354
  if ( $query_type == SQL_INSERT ) {
355
  return $wpdb->insert_id;
356
  }
357
+
358
  return true;
359
  }
360
  }
361
+
362
  /**
363
  * Execute several queries
364
  *
365
  * @param string $queries queries to run
366
  *
 
367
  * @return boolean
368
+ * @throws Ruckusing_Exception
369
  */
370
  public function multi_query( $queries ) {
371
  if ( \defined( 'YOAST_ENVIRONMENT' ) && YOAST_ENVIRONMENT !== 'production' ) {
372
  throw new Ruckusing_Exception( 'WPDB does not support multi_query.', Ruckusing_Exception::QUERY_ERROR );
373
  }
374
+
375
  return false;
376
  }
377
+
378
  /**
379
  * Select one
380
  *
381
  * @param string $query query to run
382
  *
 
383
  * @return array
384
+ * @throws Ruckusing_Exception
385
  */
386
  public function select_one( $query ) {
387
  global $wpdb;
392
  if ( $this->isError( $res ) ) {
393
  throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
394
  }
395
+
396
  return $wpdb->last_result;
397
  } else {
398
  throw new Ruckusing_Exception( "Query for select_one() is not one of SELECT or SHOW: {$query}", Ruckusing_Exception::QUERY_ERROR );
399
  }
400
  }
401
+
402
  /**
403
  * Select all
404
  *
409
  public function select_all( $query ) {
410
  return $this->query( $query );
411
  }
412
+
413
  /**
414
  * Use this method for non-SELECT queries
415
  * Or anything where you dont necessarily expect a result string, e.g. DROPs, CREATEs, etc.
420
  */
421
  public function execute_ddl( $ddl ) {
422
  $result = $this->query( $ddl );
423
+
424
  return true;
425
  }
426
+
427
  /**
428
  * Drop table
429
  *
432
  * @return boolean
433
  */
434
  public function drop_table( $tbl ) {
435
+ $ddl = \sprintf( 'DROP TABLE IF EXISTS %s', $this->identifier( $tbl ) );
436
  $result = $this->query( $ddl );
437
+
438
  return true;
439
  }
440
+
441
  /**
442
  * Create table
443
  *
444
  * @param string $table_name the table name
445
+ * @param array $options the options
446
+ *
447
  * @return bool|Ruckusing_Adapter_MySQL_TableDefinition
448
  */
449
  public function create_table( $table_name, $options = [] ) {
450
  return new Ruckusing_Adapter_MySQL_TableDefinition( $this, $table_name, $options );
451
  }
452
+
453
  /**
454
  * Escape a string for mysql
455
  *
459
  */
460
  public function quote_string( $str ) {
461
  global $wpdb;
462
+
463
  return $wpdb->_escape( $str );
464
  }
465
+
466
  /**
467
  * Quote a string
468
  *
473
  public function identifier( $str ) {
474
  return '`' . $str . '`';
475
  }
476
+
477
  /**
478
  * Quote a string
479
  *
485
  public function quote( $value, $column = null ) {
486
  return $this->quote_string( $value );
487
  }
488
+
489
  /**
490
  * Rename a table
491
  *
492
+ * @param string $name the current table name
493
  * @param string $new_name the new table name
494
  *
 
495
  * @return boolean
496
+ * @throws Ruckusing_Exception
497
  */
498
  public function rename_table( $name, $new_name ) {
499
  if ( empty( $name ) ) {
503
  throw new Ruckusing_Exception( 'Missing new column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
504
  }
505
  $sql = \sprintf( 'RENAME TABLE %s TO %s', $this->identifier( $name ), $this->identifier( $new_name ) );
506
+
507
  return $this->execute_ddl( $sql );
508
  }
509
  // create_table
510
+
511
  /**
512
  * Add a column
513
  *
514
+ * @param string $table_name the table name
515
  * @param string $column_name the column name
516
+ * @param string $type the column type
517
+ * @param array $options column options
518
  *
 
519
  * @return boolean
520
+ * @throws Ruckusing_Exception
521
  */
522
  public function add_column( $table_name, $column_name, $type, $options = [] ) {
523
  if ( empty( $table_name ) ) {
541
  }
542
  $sql = \sprintf( 'ALTER TABLE %s ADD `%s` %s', $this->identifier( $table_name ), $column_name, $this->type_to_sql( $type, $options ) );
543
  $sql .= $this->add_column_options( $type, $options );
544
+
545
  return $this->execute_ddl( $sql );
546
  }
547
  // add_column
548
+
549
  /**
550
  * Drop a column
551
  *
556
  */
557
  public function remove_column( $table_name, $column_name ) {
558
  $sql = \sprintf( 'ALTER TABLE %s DROP COLUMN %s', $this->identifier( $table_name ), $this->identifier( $column_name ) );
559
+
560
  return $this->execute_ddl( $sql );
561
  }
562
  // remove_column
563
+
564
  /**
565
  * Rename a column
566
  *
567
+ * @param string $table_name the table name
568
+ * @param string $column_name the column name
569
  * @param string $new_column_name the new column name
570
  *
 
571
  * @return boolean
572
+ * @throws Ruckusing_Exception
573
  */
574
  public function rename_column( $table_name, $column_name, $new_column_name ) {
575
  if ( empty( $table_name ) ) {
581
  if ( empty( $new_column_name ) ) {
582
  throw new Ruckusing_Exception( 'Missing new column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
583
  }
584
+ $column_info = $this->column_info( $table_name, $column_name );
585
  $current_type = $column_info['type'];
586
+ $sql = \sprintf( 'ALTER TABLE %s CHANGE %s %s %s', $this->identifier( $table_name ), $this->identifier( $column_name ), $this->identifier( $new_column_name ), $current_type );
587
+ $sql .= $this->add_column_options( $current_type, $column_info );
588
+
589
  return $this->execute_ddl( $sql );
590
  }
591
  // rename_column
592
+
593
  /**
594
  * Change a column
595
  *
596
+ * @param string $table_name the table name
597
  * @param string $column_name the column name
598
+ * @param string $type the column type
599
+ * @param array $options column options
600
  *
 
601
  * @return boolean
602
+ * @throws Ruckusing_Exception
603
  */
604
  public function change_column( $table_name, $column_name, $type, $options = [] ) {
605
  if ( empty( $table_name ) ) {
624
  }
625
  $sql = \sprintf( 'ALTER TABLE `%s` CHANGE `%s` `%s` %s', $table_name, $column_name, $column_name, $this->type_to_sql( $type, $options ) );
626
  $sql .= $this->add_column_options( $type, $options );
627
+
628
  return $this->execute_ddl( $sql );
629
  }
630
  // change_column
631
+
632
  /**
633
  * Get a column info
634
  *
635
+ * @param string $table the table name
636
  * @param string $column the column name
637
  *
 
638
  * @return array
639
+ * @throws Ruckusing_Exception
640
  */
641
  public function column_info( $table, $column ) {
642
  if ( empty( $table ) ) {
646
  throw new Ruckusing_Exception( 'Missing original column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
647
  }
648
  try {
649
+ $sql = \sprintf( "SHOW FULL COLUMNS FROM %s LIKE '%s'", $this->identifier( $table ), $column );
650
  $result = $this->select_one( $sql );
651
  if ( \is_array( $result ) ) {
652
  // lowercase key names
653
  $result = \array_change_key_case( $result, \CASE_LOWER );
654
  }
655
+
656
  return $result;
657
+ } catch ( \Exception $e ) {
658
  return null;
659
  }
660
  }
661
+
662
  /**
663
  * Add an index
664
  *
665
+ * @param string $table_name the table name
666
  * @param string $column_name the column name
667
+ * @param array $options index options
668
  *
 
669
  * @return boolean
670
+ * @throws Ruckusing_Exception
671
  */
672
  public function add_index( $table_name, $column_name, $options = [] ) {
673
  if ( empty( $table_name ) ) {
705
  $cols[] = $this->identifier( $name );
706
  }
707
  $sql = \sprintf( 'CREATE %sINDEX %s ON %s(%s)', $unique ? 'UNIQUE ' : '', $this->identifier( $index_name ), $this->identifier( $table_name ), \join( ', ', $cols ) );
708
+
709
  return $this->execute_ddl( $sql );
710
  }
711
+
712
  /**
713
  * Drop an index
714
  *
715
+ * @param string $table_name the table name
716
  * @param string $column_name the column name
717
+ * @param array $options index options
718
  *
 
719
  * @return boolean
720
+ * @throws Ruckusing_Exception
721
  */
722
  public function remove_index( $table_name, $column_name, $options = [] ) {
723
  if ( empty( $table_name ) ) {
733
  $index_name = Ruckusing_Util_Naming::index_name( $table_name, $column_name );
734
  }
735
  $sql = \sprintf( 'DROP INDEX %s ON %s', $this->identifier( $index_name ), $this->identifier( $table_name ) );
736
+
737
  return $this->execute_ddl( $sql );
738
  }
739
+
740
  /**
741
  * Add timestamps
742
  *
757
  throw new Ruckusing_Exception( 'Missing updated at column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
758
  }
759
  $created_at = $this->add_column( $table_name, $created_column_name, 'datetime' );
760
+ $updated_at = $this->add_column( $table_name, $updated_column_name, 'timestamp', [
761
+ 'null' => false,
762
+ 'default' => 'CURRENT_TIMESTAMP',
763
+ 'extra' => 'ON UPDATE CURRENT_TIMESTAMP'
764
+ ] );
765
+
766
  return $created_at && $updated_at;
767
  }
768
+
769
  /**
770
  * Remove timestamps
771
  *
787
  }
788
  $updated_at = $this->remove_column( $table_name, $created_column_name );
789
  $created_at = $this->remove_column( $table_name, $updated_column_name );
790
+
791
  return $created_at && $updated_at;
792
  }
793
+
794
  /**
795
  * Check an index
796
  *
797
+ * @param string $table_name the table name
798
  * @param string $column_name the column name
799
+ * @param array $options index options
800
  *
 
801
  * @return boolean
802
+ * @throws Ruckusing_Exception
803
  */
804
  public function has_index( $table_name, $column_name, $options = [] ) {
805
  if ( empty( $table_name ) ) {
820
  return true;
821
  }
822
  }
823
+
824
  return false;
825
  }
826
+
827
  /**
828
  * Return all indexes of a table
829
  *
832
  * @return array
833
  */
834
  public function indexes( $table_name ) {
835
+ $sql = \sprintf( 'SHOW KEYS FROM %s', $this->identifier( $table_name ) );
836
+ $result = $this->select_all( $sql );
837
  $indexes = [];
838
  $cur_idx = null;
839
  foreach ( $result as $row ) {
841
  if ( $row['Key_name'] == 'PRIMARY' ) {
842
  continue;
843
  }
844
+ $cur_idx = $row['Key_name'];
845
  $indexes[] = [ 'name' => $row['Key_name'], 'unique' => (int) $row['Non_unique'] == 0 ? true : false ];
846
  }
847
+
848
  return $indexes;
849
  }
850
+
851
  /**
852
  * Convert type to sql
853
  * $limit = null, $precision = null, $scale = null
855
  * @param string $type the native type
856
  * @param array $options
857
  *
 
858
  * @return string
859
+ * @throws Ruckusing_Exception
860
  */
861
  public function type_to_sql( $type, $options = [] ) {
862
  $natives = $this->native_database_types();
873
  }
874
  throw new Ruckusing_Exception( $error, Ruckusing_Exception::INVALID_ARGUMENT );
875
  }
876
+ $scale = null;
877
  $precision = null;
878
+ $limit = null;
879
  if ( isset( $options['precision'] ) ) {
880
  $precision = $options['precision'];
881
  }
940
  if ( empty( $values ) ) {
941
  throw new Ruckusing_Exception( 'Error adding enum column: there must be at least one value defined', Ruckusing_Exception::INVALID_ARGUMENT );
942
  } else {
943
+ $column_type_sql .= \sprintf( "('%s')", \implode( "','", \array_map( [
944
+ $this,
945
+ 'quote_string'
946
+ ], $values ) ) );
947
  }
948
  }
949
  // not a decimal column
953
  if ( $limit ) {
954
  $column_type_sql .= \sprintf( '(%d)', $limit );
955
  }
956
+
957
  return $column_type_sql;
958
  }
959
+
960
  /**
961
  * Add column options
962
  *
963
  * @param string $type the native type
964
  * @param array $options
965
  *
 
966
  * @return string
967
+ * @throws Ruckusing_Exception
968
  */
969
  public function add_column_options( $type, $options ) {
970
  $sql = '';
998
  $default_format = "'%s'";
999
  }
1000
  $default_value = \sprintf( $default_format, $options['default'] );
1001
+ $sql .= \sprintf( ' DEFAULT %s', $default_value );
1002
  }
1003
  if ( \array_key_exists( 'null', $options ) ) {
1004
  if ( $options['null'] === false || $options['null'] === 'NO' ) {
1016
  if ( \array_key_exists( 'after', $options ) ) {
1017
  $sql .= \sprintf( ' AFTER %s', $this->identifier( $options['after'] ) );
1018
  }
1019
+
1020
  return $sql;
1021
  }
1022
+
1023
  /**
1024
  * Set current version
1025
  *
1029
  */
1030
  public function set_current_version( $version ) {
1031
  $sql = \sprintf( "INSERT INTO %s (version) VALUES ('%s')", $this->get_schema_version_table_name(), $version );
1032
+
1033
  return $this->execute_ddl( $sql );
1034
  }
1035
+
1036
  /**
1037
  * remove a version
1038
  *
1042
  */
1043
  public function remove_version( $version ) {
1044
  $sql = \sprintf( "DELETE FROM %s WHERE version = '%s'", $this->get_schema_version_table_name(), $version );
1045
+
1046
  return $this->execute_ddl( $sql );
1047
  }
1048
+
1049
  /**
1050
  * Return a message displaying the current version
1051
  *
1067
  private function isError( $o ) {
1068
  return $o === false;
1069
  }
1070
+
1071
  /**
1072
  * Initialize an array of table names
1073
  *
1080
  $this->_tables = [];
1081
  // clear existing structure
1082
  $query = 'SHOW TABLES';
1083
+ $res = $wpdb->get_results( $query, \ARRAY_N );
1084
  // check for errors
1085
  if ( $this->isError( $res ) ) {
1086
  throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
1087
  }
1088
  foreach ( $res as $row ) {
1089
+ $table = $row[0];
1090
  $this->_tables[ $table ] = true;
1091
  }
1092
  }
1093
  }
1094
+
1095
  /**
1096
  * Check query type
1097
  *
1129
  return SQL_UNKNOWN_QUERY_TYPE;
1130
  }
1131
  }
1132
+
1133
  /**
1134
  * Check query type
1135
  *
1136
  * @param $query_type
 
1137
  *
1138
  * @return boolean
1139
+ * @internal param string $query query to run
1140
+ *
1141
  */
1142
  private function is_select( $query_type ) {
1143
  if ( $query_type == SQL_SELECT ) {
1144
  return true;
1145
  }
1146
+
1147
  return false;
1148
  }
1149
+
1150
  /**
1151
  * Detect whether or not the string represents a function call and if so
1152
  * do not wrap it in single-quotes, otherwise do wrap in single quotes.
1157
  */
1158
  private function is_sql_method_call( $str ) {
1159
  $str = \trim( $str );
1160
+ if ( \substr( $str, - 2, 2 ) == '()' ) {
1161
  return true;
1162
  } else {
1163
  return false;
1164
  }
1165
  }
1166
+
1167
  /**
1168
  * Check if in transaction
1169
  *
1172
  private function inTransaction() {
1173
  return $this->_in_trx;
1174
  }
1175
+
1176
  /**
1177
  * Start transaction
1178
  */
1185
  $wpdb->query( 'START TRANSACTION' );
1186
  $this->_in_trx = true;
1187
  }
1188
+
1189
  /**
1190
  * Commit a transaction
1191
  */
1198
  $wpdb->query( 'COMMIT' );
1199
  $this->_in_trx = false;
1200
  }
1201
+
1202
  /**
1203
  * Rollback a transaction
1204
  */
readme.txt CHANGED
@@ -6,7 +6,7 @@ License URI: http://www.gnu.org/licenses/gpl.html
6
  Tags: SEO, XML sitemap, Content analysis, Readability
7
  Requires at least: 5.3
8
  Tested up to: 5.4
9
- Stable tag: 14.0.2
10
  Requires PHP: 5.6.20
11
 
12
  Improve your WordPress SEO: Write better content and have a fully optimized WordPress site using the Yoast SEO plugin.
@@ -209,6 +209,24 @@ Your question has most likely been answered on our knowledge base: [kb.yoast.com
209
 
210
  == Changelog ==
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  = 14.0.2 =
213
  Release Date: April 29th, 2020
214
 
6
  Tags: SEO, XML sitemap, Content analysis, Readability
7
  Requires at least: 5.3
8
  Tested up to: 5.4
9
+ Stable tag: 14.0.3
10
  Requires PHP: 5.6.20
11
 
12
  Improve your WordPress SEO: Write better content and have a fully optimized WordPress site using the Yoast SEO plugin.
209
 
210
  == Changelog ==
211
 
212
+ = 14.0.3 =
213
+ Release Date: April 30th, 2020
214
+
215
+ Bugfixes:
216
+
217
+ * Fixes a bug where running the migrations could cause fatal errors on sites where plugins are installed remotely. Some remote plugin installers don't remove files that are removed in an update. Since our migration runner goes through all migrations on the server, this could lead to fatal errors.
218
+ * Fixes a bug where the `pre_get_document_title filter` could be skipped when other plugins were using this filter as well.
219
+ * Fixes a bug where an error would be thrown when the name of an indexable table had been converted to a different case.
220
+ * Fixes a bug where a taxonomy parent would not be present in the breadcrumbs even though it was set in the breadcrumbs settings.
221
+
222
+ Enhancements:
223
+
224
+ * Adds a missing index to the new indexables table. Props to [@pagelypete](https://github.com/pagelypete).
225
+
226
+ Other:
227
+
228
+ * Adds the wpseo_frontend_presentation filter that can be used by third-party plugins to easily alter all our meta output with 1 single filter.
229
+
230
  = 14.0.2 =
231
  Release Date: April 29th, 2020
232
 
{migrations → src/config/migrations}/20171228151840_WpYoastIndexable.php RENAMED
File without changes
{migrations → src/config/migrations}/20171228151841_WpYoastPrimaryTerm.php RENAMED
File without changes
{migrations → src/config/migrations}/20190529075038_WpYoastDropIndexableMetaTableIfExists.php RENAMED
File without changes
{migrations → src/config/migrations}/20191011111109_WpYoastIndexableHierarchy.php RENAMED
File without changes
{migrations → src/config/migrations}/20200408101900_AddCollationToTables.php RENAMED
File without changes
{migrations → src/config/migrations}/20200420073606_AddColumnsToIndexables.php RENAMED
File without changes
{migrations → src/config/migrations}/20200428123747_BreadcrumbTitleAndHierarchyReset.php RENAMED
File without changes
{migrations → src/config/migrations}/20200428194858_ExpandIndexableColumnLengths.php RENAMED
File without changes
{migrations → src/config/migrations}/20200429105310_TruncateIndexableTables.php RENAMED
File without changes
src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Yoast SEO Plugin File.
4
+ *
5
+ * @package WPSEO\Migrations
6
+ */
7
+
8
+ use Yoast\WP\Lib\Model;
9
+ use YoastSEO_Vendor\Ruckusing_Migration_Base;
10
+
11
+ /**
12
+ * AddIndexableObjectIdAndTypeIndex
13
+ */
14
+ class AddIndexableObjectIdAndTypeIndex extends Ruckusing_Migration_Base {
15
+
16
+ /**
17
+ * Migration up.
18
+ */
19
+ public function up() {
20
+ $this->add_index(
21
+ $this->get_table_name(),
22
+ [
23
+ 'object_id',
24
+ 'object_type',
25
+ ],
26
+ [
27
+ 'name' => 'object_id_and_type',
28
+ ]
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Migration down.
34
+ */
35
+ public function down() {
36
+ $this->remove_index(
37
+ $this->get_table_name(),
38
+ [
39
+ 'object_id',
40
+ 'object_type',
41
+ ],
42
+ [
43
+ 'name' => 'object_id_and_type',
44
+ ]
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Retrieves the table name to use for storing indexables.
50
+ *
51
+ * @return string The table name to use.
52
+ */
53
+ protected function get_table_name() {
54
+ return Model::get_table_name( 'Indexable' );
55
+ }
56
+ }
{migrations → src/config/migrations}/ruckusing/lib/Ruckusing/Adapter/why RENAMED
File without changes
{migrations → src/config/migrations}/ruckusing/lib/Task/why RENAMED
File without changes
src/config/ruckusing-framework.php CHANGED
@@ -119,7 +119,7 @@ class Ruckusing_Framework {
119
  */
120
  public function maybe_set_constant() {
121
  $constant_name = $this->dependency_management->prefixed_available() ? \YOAST_VENDOR_NS_PREFIX . '\RUCKUSING_BASE' : 'RUCKUSING_BASE';
122
- $constant_value = \WPSEO_PATH . 'migrations' . \DIRECTORY_SEPARATOR . 'ruckusing';
123
 
124
  if ( \defined( $constant_name ) ) {
125
  return \constant( $constant_name ) === $constant_value;
119
  */
120
  public function maybe_set_constant() {
121
  $constant_name = $this->dependency_management->prefixed_available() ? \YOAST_VENDOR_NS_PREFIX . '\RUCKUSING_BASE' : 'RUCKUSING_BASE';
122
+ $constant_value = \WPSEO_PATH . 'src/config/migrations' . \DIRECTORY_SEPARATOR . 'ruckusing';
123
 
124
  if ( \defined( $constant_name ) ) {
125
  return \constant( $constant_name ) === $constant_value;
src/generated/container.php CHANGED
@@ -1427,7 +1427,7 @@ class Cached_Container extends Container
1427
  */
1428
  protected function getWooCommerceService()
1429
  {
1430
- return $this->services['Yoast\\WP\\SEO\\Integrations\\Third_Party\\WooCommerce'] = new \Yoast\WP\SEO\Integrations\Third_Party\WooCommerce(${($_ = isset($this->services['Yoast\\WP\\SEO\\Helpers\\Options_Helper']) ? $this->services['Yoast\\WP\\SEO\\Helpers\\Options_Helper'] : ($this->services['Yoast\\WP\\SEO\\Helpers\\Options_Helper'] = new \Yoast\WP\SEO\Helpers\Options_Helper())) && false ?: '_'}, ${($_ = isset($this->services['WPSEO_Replace_Vars']) ? $this->services['WPSEO_Replace_Vars'] : $this->getWPSEOReplaceVarsService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer']) ? $this->services['Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer'] : $this->getMetaTagsContextMemoizerService()) && false ?: '_'});
1431
  }
1432
 
1433
  /**
1427
  */
1428
  protected function getWooCommerceService()
1429
  {
1430
+ return $this->services['Yoast\\WP\\SEO\\Integrations\\Third_Party\\WooCommerce'] = new \Yoast\WP\SEO\Integrations\Third_Party\WooCommerce(${($_ = isset($this->services['Yoast\\WP\\SEO\\Helpers\\Options_Helper']) ? $this->services['Yoast\\WP\\SEO\\Helpers\\Options_Helper'] : ($this->services['Yoast\\WP\\SEO\\Helpers\\Options_Helper'] = new \Yoast\WP\SEO\Helpers\Options_Helper())) && false ?: '_'}, ${($_ = isset($this->services['WPSEO_Replace_Vars']) ? $this->services['WPSEO_Replace_Vars'] : $this->getWPSEOReplaceVarsService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer']) ? $this->services['Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer'] : $this->getMetaTagsContextMemoizerService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository']) ? $this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository'] : $this->getIndexableRepositoryService()) && false ?: '_'});
1431
  }
1432
 
1433
  /**
src/generators/breadcrumbs-generator.php CHANGED
@@ -80,7 +80,7 @@ class Breadcrumbs_Generator implements Generator_Interface {
80
  }
81
  }
82
  $page_for_posts = \get_option( 'page_for_posts' );
83
- if ( $this->should_have_blog_crumb( $page_for_posts ) ) {
84
  $static_ancestor = $this->repository->find_by_id_and_type( $page_for_posts, 'post' );
85
  if ( $static_ancestor->post_status !== 'unindexed' ) {
86
  $static_ancestors[] = $static_ancestor;
@@ -93,6 +93,12 @@ class Breadcrumbs_Generator implements Generator_Interface {
93
  ) {
94
  $static_ancestors[] = $this->repository->find_for_post_type_archive( $context->indexable->object_sub_type );
95
  }
 
 
 
 
 
 
96
 
97
  // Get all ancestors of the indexable and append itself to get all indexables in the full crumb.
98
  $indexables = $this->repository->get_ancestors( $context->indexable );
@@ -102,6 +108,8 @@ class Breadcrumbs_Generator implements Generator_Interface {
102
  array_unshift( $indexables, ...$static_ancestors );
103
  }
104
 
 
 
105
  $crumbs = array_map( function ( Indexable $ancestor ) {
106
  $crumb = [
107
  'url' => $ancestor->permalink,
@@ -144,17 +152,23 @@ class Breadcrumbs_Generator implements Generator_Interface {
144
  /**
145
  * Returns whether or not a blog crumb should be added.
146
  *
147
- * @param int $page_for_posts The page for posts ID.
 
148
  *
149
  * @return bool Whether or not a blog crumb should be added.
150
  */
151
- protected function should_have_blog_crumb( $page_for_posts ) {
152
- if ( $this->options->get( 'breadcrumbs-display-blog-page' ) !== true ) {
 
153
  return false;
154
  }
155
 
156
- // When there is no page configured as blog page.
157
- if ( \get_option( 'show_on_front' ) !== 'page' || ! $page_for_posts ) {
 
 
 
 
158
  return false;
159
  }
160
 
@@ -165,4 +179,21 @@ class Breadcrumbs_Generator implements Generator_Interface {
165
 
166
  return true;
167
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  }
80
  }
81
  }
82
  $page_for_posts = \get_option( 'page_for_posts' );
83
+ if ( $this->should_have_blog_crumb( $page_for_posts, $context ) ) {
84
  $static_ancestor = $this->repository->find_by_id_and_type( $page_for_posts, 'post' );
85
  if ( $static_ancestor->post_status !== 'unindexed' ) {
86
  $static_ancestors[] = $static_ancestor;
93
  ) {
94
  $static_ancestors[] = $this->repository->find_for_post_type_archive( $context->indexable->object_sub_type );
95
  }
96
+ if ( $context->indexable->object_type === 'term' ) {
97
+ $parent = $this->get_taxonomy_post_type_parent( $context->indexable->object_sub_type );
98
+ if ( $parent && $parent !== 'post' ) {
99
+ $static_ancestors[] = $this->repository->find_for_post_type_archive( $parent );
100
+ }
101
+ }
102
 
103
  // Get all ancestors of the indexable and append itself to get all indexables in the full crumb.
104
  $indexables = $this->repository->get_ancestors( $context->indexable );
108
  array_unshift( $indexables, ...$static_ancestors );
109
  }
110
 
111
+ $indexables = \apply_filters( 'wpseo_breadcrumb_indexables', $indexables, $context );
112
+
113
  $crumbs = array_map( function ( Indexable $ancestor ) {
114
  $crumb = [
115
  'url' => $ancestor->permalink,
152
  /**
153
  * Returns whether or not a blog crumb should be added.
154
  *
155
+ * @param int $page_for_posts The page for posts ID.
156
+ * @param Meta_Tags_Context $context The meta tags context.
157
  *
158
  * @return bool Whether or not a blog crumb should be added.
159
  */
160
+ protected function should_have_blog_crumb( $page_for_posts, $context ) {
161
+ // When there is no page configured as blog page.
162
+ if ( \get_option( 'show_on_front' ) !== 'page' || ! $page_for_posts ) {
163
  return false;
164
  }
165
 
166
+ if ( $context->indexable->object_type === 'term' ) {
167
+ $parent = $this->get_taxonomy_post_type_parent( $context->indexable->object_sub_type );
168
+ return $parent === 'post';
169
+ }
170
+
171
+ if ( $this->options->get( 'breadcrumbs-display-blog-page' ) !== true ) {
172
  return false;
173
  }
174
 
179
 
180
  return true;
181
  }
182
+
183
+ /**
184
+ * Returns the post type parent of a given taxonomy.
185
+ *
186
+ * @param string $taxonomy The taxonomy.
187
+ *
188
+ * @return string|false The parent if it exists, false otherwise.
189
+ */
190
+ protected function get_taxonomy_post_type_parent( $taxonomy ) {
191
+ $parent = $this->options->get( 'taxonomy-' . $taxonomy . '-ptparent' );
192
+
193
+ if ( empty( $parent ) || (string) $parent === '0' ) {
194
+ return false;
195
+ }
196
+
197
+ return $parent;
198
+ }
199
  }
src/initializers/migration-runner.php CHANGED
@@ -71,7 +71,7 @@ class Migration_Runner implements Initializer_Interface {
71
  * @throws \Exception When a migration errored.
72
  */
73
  public function run_free_migrations() {
74
- $this->run_migrations( 'free', Model::get_table_name( 'migrations' ), \WPSEO_PATH . 'migrations' );
75
  }
76
 
77
  /**
71
  * @throws \Exception When a migration errored.
72
  */
73
  public function run_free_migrations() {
74
+ $this->run_migrations( 'free', Model::get_table_name( 'migrations' ), \WPSEO_PATH . 'src/config/migrations' );
75
  }
76
 
77
  /**
src/integrations/breadcrumbs-integration.php CHANGED
@@ -72,7 +72,10 @@ class Breadcrumbs_Integration implements Integration_Interface {
72
  * @return string The rendered breadcrumbs.
73
  */
74
  public function render() {
75
- $this->presenter->presentation = $this->context_memoizer->for_current_page()->presentation;
 
 
 
76
 
77
  return $this->presenter->present();
78
  }
72
  * @return string The rendered breadcrumbs.
73
  */
74
  public function render() {
75
+ $context = $this->context_memoizer->for_current_page();
76
+ /** This filter is documented in src/integrations/front-end-integration.php */
77
+ $presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context );
78
+ $this->presenter->presentation = $presentation;
79
 
80
  return $this->presenter->present();
81
  }
src/integrations/front-end-integration.php CHANGED
@@ -224,7 +224,8 @@ class Front_End_Integration implements Integration_Interface {
224
  $context = $this->context_memoizer->for_current_page();
225
 
226
  $title_presenter = new Title_Presenter();
227
- $title_presenter->presentation = $context->presentation;
 
228
  $title_presenter->replace_vars = $this->replace_vars;
229
  $title_presenter->helpers = $this->helpers;
230
 
@@ -253,9 +254,17 @@ class Front_End_Integration implements Integration_Interface {
253
  public function present_head() {
254
  $context = $this->context_memoizer->for_current_page();
255
  $presenters = $this->get_presenters( $context->page_type );
 
 
 
 
 
 
 
 
256
  echo PHP_EOL;
257
  foreach ( $presenters as $presenter ) {
258
- $presenter->presentation = $context->presentation;
259
  $presenter->helpers = $this->helpers;
260
  $presenter->replace_vars = $this->replace_vars;
261
  $output = $presenter->present();
224
  $context = $this->context_memoizer->for_current_page();
225
 
226
  $title_presenter = new Title_Presenter();
227
+ /** This filter is documented in src/integrations/front-end-integration.php */
228
+ $title_presenter->presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context );
229
  $title_presenter->replace_vars = $this->replace_vars;
230
  $title_presenter->helpers = $this->helpers;
231
 
254
  public function present_head() {
255
  $context = $this->context_memoizer->for_current_page();
256
  $presenters = $this->get_presenters( $context->page_type );
257
+
258
+ /**
259
+ * Filter 'wpseo_frontend_presentation' - Allow filtering the presentation used to output our meta values.
260
+ *
261
+ * @api Indexable_Presention The indexable presentation.
262
+ */
263
+ $presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context );
264
+
265
  echo PHP_EOL;
266
  foreach ( $presenters as $presenter ) {
267
+ $presenter->presentation = $presentation;
268
  $presenter->helpers = $this->helpers;
269
  $presenter->replace_vars = $this->replace_vars;
270
  $output = $presenter->present();
src/integrations/third-party/woocommerce.php CHANGED
@@ -13,7 +13,9 @@ use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional;
13
  use Yoast\WP\SEO\Helpers\Options_Helper;
14
  use Yoast\WP\SEO\Integrations\Integration_Interface;
15
  use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
 
16
  use Yoast\WP\SEO\Presentations\Indexable_Presentation;
 
17
 
18
  /**
19
  * Class WooCommerce
@@ -41,6 +43,11 @@ class WooCommerce implements Integration_Interface {
41
  */
42
  protected $context_memoizer;
43
 
 
 
 
 
 
44
  /**
45
  * @inheritDoc
46
  */
@@ -54,15 +61,18 @@ class WooCommerce implements Integration_Interface {
54
  * @param Options_Helper $options The options helper.
55
  * @param WPSEO_Replace_Vars $replace_vars The replace vars helper.
56
  * @param Meta_Tags_Context_Memoizer $context_memoizer The meta tags context memoizer.
 
57
  */
58
  public function __construct(
59
  Options_Helper $options,
60
  WPSEO_Replace_Vars $replace_vars,
61
- Meta_Tags_Context_Memoizer $context_memoizer
 
62
  ) {
63
  $this->options = $options;
64
  $this->replace_vars = $replace_vars;
65
  $this->context_memoizer = $context_memoizer;
 
66
  }
67
 
68
  /**
@@ -72,6 +82,30 @@ class WooCommerce implements Integration_Interface {
72
  \add_filter( 'wpseo_frontend_page_type_simple_page_id', [ $this, 'get_page_id' ] );
73
  \add_filter( 'wpseo_title', [ $this, 'title' ], 10, 2 );
74
  \add_filter( 'wpseo_metadesc', [ $this, 'description' ], 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
76
 
77
  /**
@@ -113,7 +147,7 @@ class WooCommerce implements Integration_Interface {
113
  }
114
 
115
  $shop_page_id = $this->get_shop_page_id();
116
- if ( $shop_page_id === -1 ) {
117
  return $title;
118
  }
119
 
@@ -149,7 +183,7 @@ class WooCommerce implements Integration_Interface {
149
  }
150
 
151
  $shop_page_id = $this->get_shop_page_id();
152
- if ( $shop_page_id === -1 ) {
153
  return $description;
154
  }
155
 
@@ -219,6 +253,7 @@ class WooCommerce implements Integration_Interface {
219
  }
220
 
221
  $context = $this->context_memoizer->for_current_page();
 
222
  return $context->presentation;
223
  }
224
  }
13
  use Yoast\WP\SEO\Helpers\Options_Helper;
14
  use Yoast\WP\SEO\Integrations\Integration_Interface;
15
  use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
16
+ use Yoast\WP\SEO\Models\Indexable;
17
  use Yoast\WP\SEO\Presentations\Indexable_Presentation;
18
+ use Yoast\WP\SEO\Repositories\Indexable_Repository;
19
 
20
  /**
21
  * Class WooCommerce
43
  */
44
  protected $context_memoizer;
45
 
46
+ /**
47
+ * @var Indexable_Repository
48
+ */
49
+ private $repository;
50
+
51
  /**
52
  * @inheritDoc
53
  */
61
  * @param Options_Helper $options The options helper.
62
  * @param WPSEO_Replace_Vars $replace_vars The replace vars helper.
63
  * @param Meta_Tags_Context_Memoizer $context_memoizer The meta tags context memoizer.
64
+ * @param Indexable_Repository $repository The indexable repository.
65
  */
66
  public function __construct(
67
  Options_Helper $options,
68
  WPSEO_Replace_Vars $replace_vars,
69
+ Meta_Tags_Context_Memoizer $context_memoizer,
70
+ Indexable_Repository $repository
71
  ) {
72
  $this->options = $options;
73
  $this->replace_vars = $replace_vars;
74
  $this->context_memoizer = $context_memoizer;
75
+ $this->repository = $repository;
76
  }
77
 
78
  /**
82
  \add_filter( 'wpseo_frontend_page_type_simple_page_id', [ $this, 'get_page_id' ] );
83
  \add_filter( 'wpseo_title', [ $this, 'title' ], 10, 2 );
84
  \add_filter( 'wpseo_metadesc', [ $this, 'description' ], 10, 2 );
85
+ \add_filter( 'wpseo_breadcrumb_indexables', [ $this, 'add_shop_to_breadcrumbs' ] );
86
+ }
87
+
88
+ /**
89
+ * Adds a breadcrumb for the shop page.
90
+ *
91
+ * @param Indexable[] $indexables The array with indexables.
92
+ *
93
+ * @return Indexable[] The indexables to be shown in the breadcrumbs, with the shop page added.
94
+ */
95
+ public function add_shop_to_breadcrumbs( $indexables ) {
96
+ $shop_page_id = $this->get_shop_page_id();
97
+
98
+ if ( $shop_page_id < 1 ) {
99
+ return $indexables;
100
+ }
101
+
102
+ foreach ( $indexables as $index => $indexable ) {
103
+ if ( $indexable->object_type === 'post-type-archive' && $indexable->object_sub_type === 'product' ) {
104
+ $indexables[ $index ] = $this->repository->find_by_id_and_type( $shop_page_id, 'post' );
105
+ }
106
+ }
107
+
108
+ return $indexables;
109
  }
110
 
111
  /**
147
  }
148
 
149
  $shop_page_id = $this->get_shop_page_id();
150
+ if ( $shop_page_id < 1 ) {
151
  return $title;
152
  }
153
 
183
  }
184
 
185
  $shop_page_id = $this->get_shop_page_id();
186
+ if ( $shop_page_id < 1 ) {
187
  return $description;
188
  }
189
 
253
  }
254
 
255
  $context = $this->context_memoizer->for_current_page();
256
+
257
  return $context->presentation;
258
  }
259
  }
src/presenters/title-presenter.php CHANGED
@@ -34,6 +34,19 @@ class Title_Presenter extends Abstract_Indexable_Tag_Presenter {
34
  * @return string The raw value.
35
  */
36
  public function get() {
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  $title = $this->replace_vars( $this->presentation->title );
38
  /**
39
  * Filter: 'wpseo_title' - Allow changing the Yoast SEO generated title.
34
  * @return string The raw value.
35
  */
36
  public function get() {
37
+ // This ensures backwards compatibility with other plugins using this filter as well.
38
+ \add_filter( 'pre_get_document_title', [ $this, 'get_title' ], 15 );
39
+ $title = \wp_get_document_title();
40
+ \remove_filter( 'pre_get_document_title', [ $this, 'get_title' ] );
41
+ return $title;
42
+ }
43
+
44
+ /**
45
+ * Returns the presentation title.
46
+ *
47
+ * @return string The title.
48
+ */
49
+ public function get_title() {
50
  $title = $this->replace_vars( $this->presentation->title );
51
  /**
52
  * Filter: 'wpseo_title' - Allow changing the Yoast SEO generated title.
src/repositories/indexable-hierarchy-repository.php CHANGED
@@ -2,20 +2,19 @@
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
- * @package Yoast\YoastSEO\ORM\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
 
 
10
  use Yoast\WP\SEO\Builders\Indexable_Hierarchy_Builder;
11
  use Yoast\WP\SEO\Models\Indexable;
12
  use Yoast\WP\SEO\Models\Indexable_Hierarchy;
13
- use Yoast\WP\Lib\Model;
14
 
15
  /**
16
  * Class Indexable_Hierarchy_Repository
17
- *
18
- * @package Yoast\WP\SEO\ORM\Repositories
19
  */
20
  class Indexable_Hierarchy_Repository {
21
 
@@ -98,7 +97,7 @@ class Indexable_Hierarchy_Repository {
98
  /**
99
  * Starts a query for this repository.
100
  *
101
- * @return \Yoast\WP\SEO\ORM\ORMWrapper
102
  */
103
  public function query() {
104
  return Model::of_type( 'Indexable_Hierarchy' );
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
+ * @package Yoast\WP\SEO\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
+ use Yoast\WP\Lib\Model;
11
+ use Yoast\WP\Lib\ORM;
12
  use Yoast\WP\SEO\Builders\Indexable_Hierarchy_Builder;
13
  use Yoast\WP\SEO\Models\Indexable;
14
  use Yoast\WP\SEO\Models\Indexable_Hierarchy;
 
15
 
16
  /**
17
  * Class Indexable_Hierarchy_Repository
 
 
18
  */
19
  class Indexable_Hierarchy_Repository {
20
 
97
  /**
98
  * Starts a query for this repository.
99
  *
100
+ * @return ORM
101
  */
102
  public function query() {
103
  return Model::of_type( 'Indexable_Hierarchy' );
src/repositories/indexable-repository.php CHANGED
@@ -2,23 +2,21 @@
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
- * @package Yoast\YoastSEO\ORM\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
  use Psr\Log\LoggerInterface;
 
11
  use Yoast\WP\SEO\Builders\Indexable_Builder;
12
  use Yoast\WP\SEO\Helpers\Current_Page_Helper;
13
  use Yoast\WP\SEO\Loggers\Logger;
14
  use Yoast\WP\SEO\Models\Indexable;
15
- use Yoast\WP\SEO\ORM\ORMWrapper;
16
  use Yoast\WP\Lib\Model;
17
 
18
  /**
19
  * Class Indexable_Repository
20
- *
21
- * @package Yoast\WP\SEO\ORM\Repositories
22
  */
23
  class Indexable_Repository {
24
 
@@ -74,7 +72,7 @@ class Indexable_Repository {
74
  /**
75
  * Starts a query for this repository.
76
  *
77
- * @return ORMWrapper
78
  */
79
  public function query() {
80
  return Model::of_type( 'Indexable' );
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
+ * @package Yoast\WP\SEO\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
  use Psr\Log\LoggerInterface;
11
+ use Yoast\WP\Lib\ORM;
12
  use Yoast\WP\SEO\Builders\Indexable_Builder;
13
  use Yoast\WP\SEO\Helpers\Current_Page_Helper;
14
  use Yoast\WP\SEO\Loggers\Logger;
15
  use Yoast\WP\SEO\Models\Indexable;
 
16
  use Yoast\WP\Lib\Model;
17
 
18
  /**
19
  * Class Indexable_Repository
 
 
20
  */
21
  class Indexable_Repository {
22
 
72
  /**
73
  * Starts a query for this repository.
74
  *
75
+ * @return ORM
76
  */
77
  public function query() {
78
  return Model::of_type( 'Indexable' );
src/repositories/primary-term-repository.php CHANGED
@@ -2,26 +2,24 @@
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
- * @package Yoast\YoastSEO\ORM\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
- use Yoast\WP\SEO\Models\Primary_Term;
11
- use Yoast\WP\SEO\ORM\ORMWrapper;
12
  use Yoast\WP\Lib\Model;
 
13
 
14
  /**
15
  * Class Primary_Term_Repository
16
- *
17
- * @package Yoast\WP\SEO\ORM\Repositories
18
  */
19
  class Primary_Term_Repository {
20
 
21
  /**
22
  * Starts a query for this repository.
23
  *
24
- * @return ORMWrapper
25
  */
26
  public function query() {
27
  return Model::of_type( 'Primary_Term' );
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
+ * @package Yoast\WP\SEO\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
+ use Yoast\WP\Lib\ORM;
 
11
  use Yoast\WP\Lib\Model;
12
+ use Yoast\WP\SEO\Models\Primary_Term;
13
 
14
  /**
15
  * Class Primary_Term_Repository
 
 
16
  */
17
  class Primary_Term_Repository {
18
 
19
  /**
20
  * Starts a query for this repository.
21
  *
22
+ * @return ORM
23
  */
24
  public function query() {
25
  return Model::of_type( 'Primary_Term' );
src/repositories/seo-links-repository.php CHANGED
@@ -2,25 +2,23 @@
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
- * @package Yoast\YoastSEO\ORM\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
- use Yoast\WP\SEO\ORM\ORMWrapper;
11
  use Yoast\WP\Lib\Model;
12
 
13
  /**
14
  * Class SEO_Links_Repository
15
- *
16
- * @package Yoast\WP\SEO\ORM\Repositories
17
  */
18
  class SEO_Links_Repository {
19
 
20
  /**
21
  * Starts a query for this repository.
22
  *
23
- * @return ORMWrapper
24
  */
25
  public function query() {
26
  return Model::of_type( 'SEO_Links' );
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
+ * @package Yoast\WP\SEO\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
+ use Yoast\WP\Lib\ORM;
11
  use Yoast\WP\Lib\Model;
12
 
13
  /**
14
  * Class SEO_Links_Repository
 
 
15
  */
16
  class SEO_Links_Repository {
17
 
18
  /**
19
  * Starts a query for this repository.
20
  *
21
+ * @return ORM
22
  */
23
  public function query() {
24
  return Model::of_type( 'SEO_Links' );
src/repositories/seo-meta-repository.php CHANGED
@@ -2,25 +2,23 @@
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
- * @package Yoast\YoastSEO\ORM\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
- use Yoast\WP\SEO\ORM\ORMWrapper;
11
  use Yoast\WP\Lib\Model;
12
 
13
  /**
14
  * Class SEO_Meta_Repository
15
- *
16
- * @package Yoast\WP\SEO\ORM\Repositories
17
  */
18
  class SEO_Meta_Repository {
19
 
20
  /**
21
  * Starts a query for this repository.
22
  *
23
- * @return ORMWrapper
24
  */
25
  public function query() {
26
  return Model::of_type( 'SEO_Meta' );
@@ -31,7 +29,7 @@ class SEO_Meta_Repository {
31
  *
32
  * @param int $post_id The post ID.
33
  *
34
- * @return \Yoast\WP\SEO\Models\SEO_Meta The SEO meta.
35
  */
36
  public function find_by_post_id( $post_id ) {
37
  return $this->query()
2
  /**
3
  * Yoast extension of the Model class.
4
  *
5
+ * @package Yoast\WP\SEO\Repositories
6
  */
7
 
8
  namespace Yoast\WP\SEO\Repositories;
9
 
10
+ use Yoast\WP\Lib\ORM;
11
  use Yoast\WP\Lib\Model;
12
 
13
  /**
14
  * Class SEO_Meta_Repository
 
 
15
  */
16
  class SEO_Meta_Repository {
17
 
18
  /**
19
  * Starts a query for this repository.
20
  *
21
+ * @return ORM
22
  */
23
  public function query() {
24
  return Model::of_type( 'SEO_Meta' );
29
  *
30
  * @param int $post_id The post ID.
31
  *
32
+ * @return bool|Model
33
  */
34
  public function find_by_post_id( $post_id ) {
35
  return $this->query()
src/routes/route-interface.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Route interface.
4
  *
5
- * @package Yoast\YoastSEO\ORM\Routes
6
  */
7
 
8
  namespace Yoast\WP\SEO\Routes;
2
  /**
3
  * Route interface.
4
  *
5
+ * @package Yoast\WP\SEO\Routes
6
  */
7
 
8
  namespace Yoast\WP\SEO\Routes;
src/surfaces/values/meta.php CHANGED
@@ -133,8 +133,10 @@ class Meta {
133
 
134
  $output = '';
135
 
 
 
136
  foreach ( $presenters as $presenter ) {
137
- $presenter->presentation = $this->context->presentation;
138
  $presenter->helpers = $this->helpers;
139
  $presenter->replace_vars = $this->replace_vars;
140
  $presenter_output = $presenter->present();
@@ -156,7 +158,10 @@ class Meta {
156
  * @throws Exception If an invalid property is accessed.
157
  */
158
  public function __get( $name ) {
159
- if ( ! isset( $this->context->presentation->{$name} ) ) {
 
 
 
160
  if ( isset( $this->context->{$name} ) ) {
161
  $this->{$name} = $this->context->{$name};
162
  return $this->{$name};
@@ -182,13 +187,13 @@ class Meta {
182
  * @var Abstract_Indexable_Presenter
183
  */
184
  $presenter = new $presenter_class();
185
- $presenter->presentation = $this->context->presentation;
186
  $presenter->helpers = $this->helpers;
187
  $presenter->replace_vars = $this->replace_vars;
188
  $value = $presenter->get();
189
  }
190
  else {
191
- $value = $this->context->presentation->{$name};
192
  }
193
 
194
  $this->{$name} = $value;
133
 
134
  $output = '';
135
 
136
+ /** This filter is documented in src/integrations/front-end-integration.php */
137
+ $presentation = \apply_filters( 'wpseo_frontend_presentation', $this->context->presentation, $this->context );
138
  foreach ( $presenters as $presenter ) {
139
+ $presenter->presentation = $presentation;
140
  $presenter->helpers = $this->helpers;
141
  $presenter->replace_vars = $this->replace_vars;
142
  $presenter_output = $presenter->present();
158
  * @throws Exception If an invalid property is accessed.
159
  */
160
  public function __get( $name ) {
161
+ /** This filter is documented in src/integrations/front-end-integration.php */
162
+ $presentation = \apply_filters( 'wpseo_frontend_presentation', $this->context->presentation, $this->context );
163
+
164
+ if ( ! isset( $presentation->{$name} ) ) {
165
  if ( isset( $this->context->{$name} ) ) {
166
  $this->{$name} = $this->context->{$name};
167
  return $this->{$name};
187
  * @var Abstract_Indexable_Presenter
188
  */
189
  $presenter = new $presenter_class();
190
+ $presenter->presentation = $presentation;
191
  $presenter->helpers = $this->helpers;
192
  $presenter->replace_vars = $this->replace_vars;
193
  $value = $presenter->get();
194
  }
195
  else {
196
+ $value = $presentation->{$name};
197
  }
198
 
199
  $this->{$name} = $value;
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit424d5d6160c52f59ba476750c190098f::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitd68966ec94af8b28648b9ed9a98a08f0::getLoader();
vendor/autoload_52.php DELETED
@@ -1,7 +0,0 @@
1
- <?php
2
-
3
- // autoload_52.php generated by xrstf/composer-php52
4
-
5
- require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
-
7
- return ComposerAutoloaderInitfd13764fbdc9191745a39fc948165309::getLoader();
 
 
 
 
 
 
 
vendor/composer/ClassLoader.php CHANGED
@@ -279,7 +279,7 @@ class ClassLoader
279
  */
280
  public function setApcuPrefix($apcuPrefix)
281
  {
282
- $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
  }
284
 
285
  /**
@@ -377,11 +377,11 @@ class ClassLoader
377
  $subPath = $class;
378
  while (false !== $lastPos = strrpos($subPath, '\\')) {
379
  $subPath = substr($subPath, 0, $lastPos);
380
- $search = $subPath . '\\';
381
  if (isset($this->prefixDirsPsr4[$search])) {
382
- $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
  foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
- if (file_exists($file = $dir . $pathEnd)) {
 
385
  return $file;
386
  }
387
  }
279
  */
280
  public function setApcuPrefix($apcuPrefix)
281
  {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
283
  }
284
 
285
  /**
377
  $subPath = $class;
378
  while (false !== $lastPos = strrpos($subPath, '\\')) {
379
  $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath.'\\';
381
  if (isset($this->prefixDirsPsr4[$search])) {
 
382
  foreach ($this->prefixDirsPsr4[$search] as $dir) {
383
+ $length = $this->prefixLengthsPsr4[$first][$search];
384
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
385
  return $file;
386
  }
387
  }
vendor/composer/ClassLoader52.php DELETED
@@ -1,271 +0,0 @@
1
- <?php
2
- /*
3
- * Copyright (c) 2013, Christoph Mewes, http://www.xrstf.de
4
- *
5
- * This file is released under the terms of the MIT license. You can find the
6
- * complete text in the attached LICENSE file or online at:
7
- *
8
- * http://www.opensource.org/licenses/mit-license.php
9
- *
10
- * --------------------------------------------------------------------------
11
- *
12
- * 99% of this is copied as-is from the original Composer source code and is
13
- * released under MIT license as well. Copyright goes to:
14
- *
15
- * - Fabien Potencier <fabien@symfony.com>
16
- * - Jordi Boggiano <j.boggiano@seld.be>
17
- */
18
-
19
- class xrstf_Composer52_ClassLoader {
20
- private $prefixes = array();
21
- private $fallbackDirs = array();
22
- private $useIncludePath = false;
23
- private $classMap = array();
24
- private $classMapAuthoratative = false;
25
- private $allowUnderscore = false;
26
-
27
- /**
28
- * @param boolean $flag true to allow class names with a leading underscore, false to disable
29
- */
30
- public function setAllowUnderscore($flag) {
31
- $this->allowUnderscore = (boolean) $flag;
32
- }
33
-
34
- /**
35
- * @return array
36
- */
37
- public function getPrefixes() {
38
- return $this->prefixes;
39
- }
40
-
41
- /**
42
- * Turns off searching the prefix and fallback directories for classes
43
- * that have not been registered with the class map.
44
- *
45
- * @param bool $classMapAuthoratative
46
- */
47
- public function setClassMapAuthoritative($classMapAuthoratative) {
48
- $this->classMapAuthoratative = $classMapAuthoratative;
49
- }
50
-
51
- /**
52
- * Should class lookup fail if not found in the current class map?
53
- *
54
- * @return bool
55
- */
56
- public function getClassMapAuthoratative() {
57
- return $this->classMapAuthoratative;
58
- }
59
-
60
- /**
61
- * @return array
62
- */
63
- public function getFallbackDirs() {
64
- return $this->fallbackDirs;
65
- }
66
-
67
- /**
68
- * @return array
69
- */
70
- public function getClassMap() {
71
- return $this->classMap;
72
- }
73
-
74
- /**
75
- * @param array $classMap class to filename map
76
- */
77
- public function addClassMap(array $classMap) {
78
- if ($this->classMap) {
79
- $this->classMap = array_merge($this->classMap, $classMap);
80
- }
81
- else {
82
- $this->classMap = $classMap;
83
- }
84
- }
85
-
86
- /**
87
- * Registers a set of classes, merging with any others previously set.
88
- *
89
- * @param string $prefix the classes prefix
90
- * @param array|string $paths the location(s) of the classes
91
- * @param bool $prepend prepend the location(s)
92
- */
93
- public function add($prefix, $paths, $prepend = false) {
94
- if (!$prefix) {
95
- if ($prepend) {
96
- $this->fallbackDirs = array_merge(
97
- (array) $paths,
98
- $this->fallbackDirs
99
- );
100
- }
101
- else {
102
- $this->fallbackDirs = array_merge(
103
- $this->fallbackDirs,
104
- (array) $paths
105
- );
106
- }
107
-
108
- return;
109
- }
110
-
111
- if (!isset($this->prefixes[$prefix])) {
112
- $this->prefixes[$prefix] = (array) $paths;
113
- return;
114
- }
115
-
116
- if ($prepend) {
117
- $this->prefixes[$prefix] = array_merge(
118
- (array) $paths,
119
- $this->prefixes[$prefix]
120
- );
121
- }
122
- else {
123
- $this->prefixes[$prefix] = array_merge(
124
- $this->prefixes[$prefix],
125
- (array) $paths
126
- );
127
- }
128
- }
129
-
130
- /**
131
- * Registers a set of classes, replacing any others previously set.
132
- *
133
- * @param string $prefix the classes prefix
134
- * @param array|string $paths the location(s) of the classes
135
- */
136
- public function set($prefix, $paths) {
137
- if (!$prefix) {
138
- $this->fallbackDirs = (array) $paths;
139
- return;
140
- }
141
-
142
- $this->prefixes[$prefix] = (array) $paths;
143
- }
144
-
145
- /**
146
- * Turns on searching the include path for class files.
147
- *
148
- * @param bool $useIncludePath
149
- */
150
- public function setUseIncludePath($useIncludePath) {
151
- $this->useIncludePath = $useIncludePath;
152
- }
153
-
154
- /**
155
- * Can be used to check if the autoloader uses the include path to check
156
- * for classes.
157
- *
158
- * @return bool
159
- */
160
- public function getUseIncludePath() {
161
- return $this->useIncludePath;
162
- }
163
-
164
- /**
165
- * Registers this instance as an autoloader.
166
- */
167
- public function register() {
168
- spl_autoload_register(array($this, 'loadClass'), true);
169
- }
170
-
171
- /**
172
- * Unregisters this instance as an autoloader.
173
- */
174
- public function unregister() {
175
- spl_autoload_unregister(array($this, 'loadClass'));
176
- }
177
-
178
- /**
179
- * Loads the given class or interface.
180
- *
181
- * @param string $class the name of the class
182
- * @return bool|null true, if loaded
183
- */
184
- public function loadClass($class) {
185
- if ($file = $this->findFile($class)) {
186
- include $file;
187
- return true;
188
- }
189
- }
190
-
191
- /**
192
- * Finds the path to the file where the class is defined.
193
- *
194
- * @param string $class the name of the class
195
- * @return string|null the path, if found
196
- */
197
- public function findFile($class) {
198
- if ('\\' === $class[0]) {
199
- $class = substr($class, 1);
200
- }
201
-
202
- if (isset($this->classMap[$class])) {
203
- return $this->classMap[$class];
204
- }
205
- elseif ($this->classMapAuthoratative) {
206
- return false;
207
- }
208
-
209
- $classPath = $this->getClassPath($class);
210
-
211
- foreach ($this->prefixes as $prefix => $dirs) {
212
- if (0 === strpos($class, $prefix)) {
213
- foreach ($dirs as $dir) {
214
- if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
215
- return $dir.DIRECTORY_SEPARATOR.$classPath;
216
- }
217
- }
218
- }
219
- }
220
-
221
- foreach ($this->fallbackDirs as $dir) {
222
- if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
223
- return $dir.DIRECTORY_SEPARATOR.$classPath;
224
- }
225
- }
226
-
227
- if ($this->useIncludePath && $file = self::resolveIncludePath($classPath)) {
228
- return $file;
229
- }
230
-
231
- return $this->classMap[$class] = false;
232
- }
233
-
234
- private function getClassPath($class) {
235
- if (false !== $pos = strrpos($class, '\\')) {
236
- // namespaced class name
237
- $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR;
238
- $className = substr($class, $pos + 1);
239
- }
240
- else {
241
- // PEAR-like class name
242
- $classPath = null;
243
- $className = $class;
244
- }
245
-
246
- $className = str_replace('_', DIRECTORY_SEPARATOR, $className);
247
-
248
- // restore the prefix
249
- if ($this->allowUnderscore && DIRECTORY_SEPARATOR === $className[0]) {
250
- $className[0] = '_';
251
- }
252
-
253
- $classPath .= $className.'.php';
254
-
255
- return $classPath;
256
- }
257
-
258
- public static function resolveIncludePath($classPath) {
259
- $paths = explode(PATH_SEPARATOR, get_include_path());
260
-
261
- foreach ($paths as $path) {
262
- $path = rtrim($path, '/\\');
263
-
264
- if ($file = file_exists($path.DIRECTORY_SEPARATOR.$file)) {
265
- return $file;
266
- }
267
- }
268
-
269
- return false;
270
- }
271
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/composer/autoload_classmap.php CHANGED
@@ -6,6 +6,10 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
 
 
 
9
  'Composer\\Installers\\AglInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AglInstaller.php',
10
  'Composer\\Installers\\AimeosInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AimeosInstaller.php',
11
  'Composer\\Installers\\AnnotateCmsInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php',
@@ -96,6 +100,8 @@ return array(
96
  'Composer\\Installers\\YawikInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/YawikInstaller.php',
97
  'Composer\\Installers\\ZendInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ZendInstaller.php',
98
  'Composer\\Installers\\ZikulaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ZikulaInstaller.php',
 
 
99
  'WPSEO_Abstract_Capability_Manager' => $baseDir . '/admin/capabilities/class-abstract-capability-manager.php',
100
  'WPSEO_Abstract_Metabox_Tab_With_Sections' => $baseDir . '/admin/metabox/class-abstract-sectioned-metabox-tab.php',
101
  'WPSEO_Abstract_Post_Filter' => $baseDir . '/admin/filters/class-abstract-post-filter.php',
@@ -461,6 +467,10 @@ return array(
461
  'WPSEO_WordPress_AJAX_Integration' => $baseDir . '/inc/interface-wpseo-wordpress-ajax-integration.php',
462
  'WPSEO_WordPress_Integration' => $baseDir . '/inc/interface-wpseo-wordpress-integration.php',
463
  'WPSEO_Yoast_Columns' => $baseDir . '/admin/class-yoast-columns.php',
 
 
 
 
464
  'YoastSEO_Vendor\\GuzzleHttp\\Client' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Client.php',
465
  'YoastSEO_Vendor\\GuzzleHttp\\ClientInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php',
466
  'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJar' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
@@ -530,10 +540,6 @@ return array(
530
  'YoastSEO_Vendor\\GuzzleHttp\\RetryMiddleware' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/RetryMiddleware.php',
531
  'YoastSEO_Vendor\\GuzzleHttp\\TransferStats' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php',
532
  'YoastSEO_Vendor\\GuzzleHttp\\UriTemplate' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php',
533
- 'YoastSEO_Vendor\\IdiormMethodMissingException' => $baseDir . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
534
- 'YoastSEO_Vendor\\IdiormResultSet' => $baseDir . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
535
- 'YoastSEO_Vendor\\IdiormString' => $baseDir . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
536
- 'YoastSEO_Vendor\\IdiormStringException' => $baseDir . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
537
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AbstractGrant' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/AbstractGrant.php',
538
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AuthorizationCode' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php',
539
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\ClientCredentials' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php',
@@ -560,7 +566,6 @@ return array(
560
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php',
561
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequestFactory' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php',
562
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php',
563
- 'YoastSEO_Vendor\\ORM' => $baseDir . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
564
  'YoastSEO_Vendor\\Psr\\Container\\ContainerExceptionInterface' => $baseDir . '/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php',
565
  'YoastSEO_Vendor\\Psr\\Container\\ContainerInterface' => $baseDir . '/vendor_prefixed/psr/container/src/ContainerInterface.php',
566
  'YoastSEO_Vendor\\Psr\\Container\\NotFoundExceptionInterface' => $baseDir . '/vendor_prefixed/psr/container/src/NotFoundExceptionInterface.php',
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'AddCollationToTables' => $baseDir . '/src/config/migrations/20200408101900_AddCollationToTables.php',
10
+ 'AddColumnsToIndexables' => $baseDir . '/src/config/migrations/20200420073606_AddColumnsToIndexables.php',
11
+ 'AddIndexableObjectIdAndTypeIndex' => $baseDir . '/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php',
12
+ 'BreadcrumbTitleAndHierarchyReset' => $baseDir . '/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php',
13
  'Composer\\Installers\\AglInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AglInstaller.php',
14
  'Composer\\Installers\\AimeosInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AimeosInstaller.php',
15
  'Composer\\Installers\\AnnotateCmsInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php',
100
  'Composer\\Installers\\YawikInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/YawikInstaller.php',
101
  'Composer\\Installers\\ZendInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ZendInstaller.php',
102
  'Composer\\Installers\\ZikulaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ZikulaInstaller.php',
103
+ 'ExpandIndexableColumnLengths' => $baseDir . '/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php',
104
+ 'TruncateIndexableTables' => $baseDir . '/src/config/migrations/20200429105310_TruncateIndexableTables.php',
105
  'WPSEO_Abstract_Capability_Manager' => $baseDir . '/admin/capabilities/class-abstract-capability-manager.php',
106
  'WPSEO_Abstract_Metabox_Tab_With_Sections' => $baseDir . '/admin/metabox/class-abstract-sectioned-metabox-tab.php',
107
  'WPSEO_Abstract_Post_Filter' => $baseDir . '/admin/filters/class-abstract-post-filter.php',
467
  'WPSEO_WordPress_AJAX_Integration' => $baseDir . '/inc/interface-wpseo-wordpress-ajax-integration.php',
468
  'WPSEO_WordPress_Integration' => $baseDir . '/inc/interface-wpseo-wordpress-integration.php',
469
  'WPSEO_Yoast_Columns' => $baseDir . '/admin/class-yoast-columns.php',
470
+ 'WpYoastDropIndexableMetaTableIfExists' => $baseDir . '/src/config/migrations/20190529075038_WpYoastDropIndexableMetaTableIfExists.php',
471
+ 'WpYoastIndexable' => $baseDir . '/src/config/migrations/20171228151840_WpYoastIndexable.php',
472
+ 'WpYoastIndexableHierarchy' => $baseDir . '/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php',
473
+ 'WpYoastPrimaryTerm' => $baseDir . '/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php',
474
  'YoastSEO_Vendor\\GuzzleHttp\\Client' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Client.php',
475
  'YoastSEO_Vendor\\GuzzleHttp\\ClientInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php',
476
  'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJar' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
540
  'YoastSEO_Vendor\\GuzzleHttp\\RetryMiddleware' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/RetryMiddleware.php',
541
  'YoastSEO_Vendor\\GuzzleHttp\\TransferStats' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php',
542
  'YoastSEO_Vendor\\GuzzleHttp\\UriTemplate' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php',
 
 
 
 
543
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AbstractGrant' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/AbstractGrant.php',
544
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AuthorizationCode' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php',
545
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\ClientCredentials' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php',
566
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php',
567
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequestFactory' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php',
568
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php',
 
569
  'YoastSEO_Vendor\\Psr\\Container\\ContainerExceptionInterface' => $baseDir . '/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php',
570
  'YoastSEO_Vendor\\Psr\\Container\\ContainerInterface' => $baseDir . '/vendor_prefixed/psr/container/src/ContainerInterface.php',
571
  'YoastSEO_Vendor\\Psr\\Container\\NotFoundExceptionInterface' => $baseDir . '/vendor_prefixed/psr/container/src/NotFoundExceptionInterface.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit424d5d6160c52f59ba476750c190098f
6
  {
7
  private static $loader;
8
 
@@ -13,24 +13,21 @@ class ComposerAutoloaderInit424d5d6160c52f59ba476750c190098f
13
  }
14
  }
15
 
16
- /**
17
- * @return \Composer\Autoload\ClassLoader
18
- */
19
  public static function getLoader()
20
  {
21
  if (null !== self::$loader) {
22
  return self::$loader;
23
  }
24
 
25
- spl_autoload_register(array('ComposerAutoloaderInit424d5d6160c52f59ba476750c190098f', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
- spl_autoload_unregister(array('ComposerAutoloaderInit424d5d6160c52f59ba476750c190098f', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
- call_user_func(\Composer\Autoload\ComposerStaticInit424d5d6160c52f59ba476750c190098f::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitd68966ec94af8b28648b9ed9a98a08f0
6
  {
7
  private static $loader;
8
 
13
  }
14
  }
15
 
 
 
 
16
  public static function getLoader()
17
  {
18
  if (null !== self::$loader) {
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitd68966ec94af8b28648b9ed9a98a08f0', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitd68966ec94af8b28648b9ed9a98a08f0', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInitd68966ec94af8b28648b9ed9a98a08f0::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
vendor/composer/autoload_real_52.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
-
3
- // autoload_real_52.php generated by xrstf/composer-php52
4
-
5
- class ComposerAutoloaderInitfd13764fbdc9191745a39fc948165309 {
6
- private static $loader;
7
-
8
- public static function loadClassLoader($class) {
9
- if ('xrstf_Composer52_ClassLoader' === $class) {
10
- require dirname(__FILE__).'/ClassLoader52.php';
11
- }
12
- }
13
-
14
- /**
15
- * @return xrstf_Composer52_ClassLoader
16
- */
17
- public static function getLoader() {
18
- if (null !== self::$loader) {
19
- return self::$loader;
20
- }
21
-
22
- spl_autoload_register(array('ComposerAutoloaderInitfd13764fbdc9191745a39fc948165309', 'loadClassLoader'), true /*, true */);
23
- self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitfd13764fbdc9191745a39fc948165309', 'loadClassLoader'));
25
-
26
- $vendorDir = dirname(dirname(__FILE__));
27
- $baseDir = dirname($vendorDir);
28
- $dir = dirname(__FILE__);
29
-
30
- $map = require $dir.'/autoload_namespaces.php';
31
- foreach ($map as $namespace => $path) {
32
- $loader->add($namespace, $path);
33
- }
34
-
35
- $classMap = require $dir.'/autoload_classmap.php';
36
- if ($classMap) {
37
- $loader->addClassMap($classMap);
38
- }
39
-
40
- $loader->register(true);
41
-
42
- // require $vendorDir . '/symfony/polyfill-ctype/bootstrap.php'; // disabled because of PHP 5.3 syntax
43
- // require $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php'; // disabled because of PHP 5.3 syntax
44
- // require $vendorDir . '/symfony/polyfill-php73/bootstrap.php'; // disabled because of PHP 5.3 syntax
45
- require $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php';
46
- // require $vendorDir . '/guzzlehttp/promises/src/functions_include.php'; // disabled because of PHP 5.3 syntax
47
- // require $vendorDir . '/guzzlehttp/psr7/src/functions_include.php'; // disabled because of PHP 5.3 syntax
48
- // require $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php'; // disabled because of PHP 5.3 syntax
49
- // require $vendorDir . '/jetbrains/phpstorm-stubs/PhpStormStubsMap.php'; // disabled because of PHP 5.3 syntax
50
- // require $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php'; // disabled because of PHP 5.3 syntax
51
- // require $vendorDir . '/brain/monkey/inc/api.php'; // disabled because of PHP 5.3 syntax
52
- // require $vendorDir . '/humbug/php-scoper/src/functions.php'; // disabled because of PHP 5.3 syntax
53
- // require $vendorDir . '/humbug/php-scoper/src/json.php'; // disabled because of PHP 5.3 syntax
54
- require $vendorDir . '/yoast/php-development-environment/define.php';
55
-
56
- return $loader;
57
- }
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit424d5d6160c52f59ba476750c190098f
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'C' =>
@@ -21,6 +21,10 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
21
  );
22
 
23
  public static $classMap = array (
 
 
 
 
24
  'Composer\\Installers\\AglInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AglInstaller.php',
25
  'Composer\\Installers\\AimeosInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AimeosInstaller.php',
26
  'Composer\\Installers\\AnnotateCmsInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php',
@@ -111,6 +115,8 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
111
  'Composer\\Installers\\YawikInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/YawikInstaller.php',
112
  'Composer\\Installers\\ZendInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ZendInstaller.php',
113
  'Composer\\Installers\\ZikulaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ZikulaInstaller.php',
 
 
114
  'WPSEO_Abstract_Capability_Manager' => __DIR__ . '/../..' . '/admin/capabilities/class-abstract-capability-manager.php',
115
  'WPSEO_Abstract_Metabox_Tab_With_Sections' => __DIR__ . '/../..' . '/admin/metabox/class-abstract-sectioned-metabox-tab.php',
116
  'WPSEO_Abstract_Post_Filter' => __DIR__ . '/../..' . '/admin/filters/class-abstract-post-filter.php',
@@ -476,6 +482,10 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
476
  'WPSEO_WordPress_AJAX_Integration' => __DIR__ . '/../..' . '/inc/interface-wpseo-wordpress-ajax-integration.php',
477
  'WPSEO_WordPress_Integration' => __DIR__ . '/../..' . '/inc/interface-wpseo-wordpress-integration.php',
478
  'WPSEO_Yoast_Columns' => __DIR__ . '/../..' . '/admin/class-yoast-columns.php',
 
 
 
 
479
  'YoastSEO_Vendor\\GuzzleHttp\\Client' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Client.php',
480
  'YoastSEO_Vendor\\GuzzleHttp\\ClientInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php',
481
  'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJar' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
@@ -545,10 +555,6 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
545
  'YoastSEO_Vendor\\GuzzleHttp\\RetryMiddleware' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/RetryMiddleware.php',
546
  'YoastSEO_Vendor\\GuzzleHttp\\TransferStats' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php',
547
  'YoastSEO_Vendor\\GuzzleHttp\\UriTemplate' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php',
548
- 'YoastSEO_Vendor\\IdiormMethodMissingException' => __DIR__ . '/../..' . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
549
- 'YoastSEO_Vendor\\IdiormResultSet' => __DIR__ . '/../..' . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
550
- 'YoastSEO_Vendor\\IdiormString' => __DIR__ . '/../..' . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
551
- 'YoastSEO_Vendor\\IdiormStringException' => __DIR__ . '/../..' . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
552
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AbstractGrant' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/AbstractGrant.php',
553
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AuthorizationCode' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php',
554
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\ClientCredentials' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php',
@@ -575,7 +581,6 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
575
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php',
576
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequestFactory' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php',
577
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php',
578
- 'YoastSEO_Vendor\\ORM' => __DIR__ . '/../..' . '/vendor_prefixed/j4mie/idiorm/idiorm.php',
579
  'YoastSEO_Vendor\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php',
580
  'YoastSEO_Vendor\\Psr\\Container\\ContainerInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/ContainerInterface.php',
581
  'YoastSEO_Vendor\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/NotFoundExceptionInterface.php',
@@ -887,9 +892,9 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
887
  public static function getInitializer(ClassLoader $loader)
888
  {
889
  return \Closure::bind(function () use ($loader) {
890
- $loader->prefixLengthsPsr4 = ComposerStaticInit424d5d6160c52f59ba476750c190098f::$prefixLengthsPsr4;
891
- $loader->prefixDirsPsr4 = ComposerStaticInit424d5d6160c52f59ba476750c190098f::$prefixDirsPsr4;
892
- $loader->classMap = ComposerStaticInit424d5d6160c52f59ba476750c190098f::$classMap;
893
 
894
  }, null, ClassLoader::class);
895
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitd68966ec94af8b28648b9ed9a98a08f0
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'C' =>
21
  );
22
 
23
  public static $classMap = array (
24
+ 'AddCollationToTables' => __DIR__ . '/../..' . '/src/config/migrations/20200408101900_AddCollationToTables.php',
25
+ 'AddColumnsToIndexables' => __DIR__ . '/../..' . '/src/config/migrations/20200420073606_AddColumnsToIndexables.php',
26
+ 'AddIndexableObjectIdAndTypeIndex' => __DIR__ . '/../..' . '/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php',
27
+ 'BreadcrumbTitleAndHierarchyReset' => __DIR__ . '/../..' . '/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php',
28
  'Composer\\Installers\\AglInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AglInstaller.php',
29
  'Composer\\Installers\\AimeosInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AimeosInstaller.php',
30
  'Composer\\Installers\\AnnotateCmsInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php',
115
  'Composer\\Installers\\YawikInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/YawikInstaller.php',
116
  'Composer\\Installers\\ZendInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ZendInstaller.php',
117
  'Composer\\Installers\\ZikulaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ZikulaInstaller.php',
118
+ 'ExpandIndexableColumnLengths' => __DIR__ . '/../..' . '/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php',
119
+ 'TruncateIndexableTables' => __DIR__ . '/../..' . '/src/config/migrations/20200429105310_TruncateIndexableTables.php',
120
  'WPSEO_Abstract_Capability_Manager' => __DIR__ . '/../..' . '/admin/capabilities/class-abstract-capability-manager.php',
121
  'WPSEO_Abstract_Metabox_Tab_With_Sections' => __DIR__ . '/../..' . '/admin/metabox/class-abstract-sectioned-metabox-tab.php',
122
  'WPSEO_Abstract_Post_Filter' => __DIR__ . '/../..' . '/admin/filters/class-abstract-post-filter.php',
482
  'WPSEO_WordPress_AJAX_Integration' => __DIR__ . '/../..' . '/inc/interface-wpseo-wordpress-ajax-integration.php',
483
  'WPSEO_WordPress_Integration' => __DIR__ . '/../..' . '/inc/interface-wpseo-wordpress-integration.php',
484
  'WPSEO_Yoast_Columns' => __DIR__ . '/../..' . '/admin/class-yoast-columns.php',
485
+ 'WpYoastDropIndexableMetaTableIfExists' => __DIR__ . '/../..' . '/src/config/migrations/20190529075038_WpYoastDropIndexableMetaTableIfExists.php',
486
+ 'WpYoastIndexable' => __DIR__ . '/../..' . '/src/config/migrations/20171228151840_WpYoastIndexable.php',
487
+ 'WpYoastIndexableHierarchy' => __DIR__ . '/../..' . '/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php',
488
+ 'WpYoastPrimaryTerm' => __DIR__ . '/../..' . '/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php',
489
  'YoastSEO_Vendor\\GuzzleHttp\\Client' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Client.php',
490
  'YoastSEO_Vendor\\GuzzleHttp\\ClientInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php',
491
  'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJar' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
555
  'YoastSEO_Vendor\\GuzzleHttp\\RetryMiddleware' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/RetryMiddleware.php',
556
  'YoastSEO_Vendor\\GuzzleHttp\\TransferStats' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php',
557
  'YoastSEO_Vendor\\GuzzleHttp\\UriTemplate' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php',
 
 
 
 
558
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AbstractGrant' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/AbstractGrant.php',
559
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AuthorizationCode' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php',
560
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\ClientCredentials' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php',
581
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php',
582
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequestFactory' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php',
583
  'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php',
 
584
  'YoastSEO_Vendor\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php',
585
  'YoastSEO_Vendor\\Psr\\Container\\ContainerInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/ContainerInterface.php',
586
  'YoastSEO_Vendor\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/NotFoundExceptionInterface.php',
892
  public static function getInitializer(ClassLoader $loader)
893
  {
894
  return \Closure::bind(function () use ($loader) {
895
+ $loader->prefixLengthsPsr4 = ComposerStaticInitd68966ec94af8b28648b9ed9a98a08f0::$prefixLengthsPsr4;
896
+ $loader->prefixDirsPsr4 = ComposerStaticInitd68966ec94af8b28648b9ed9a98a08f0::$prefixDirsPsr4;
897
+ $loader->classMap = ComposerStaticInitd68966ec94af8b28648b9ed9a98a08f0::$classMap;
898
 
899
  }, null, ClassLoader::class);
900
  }
vendor_prefixed/j4mie/idiorm/idiorm.php DELETED
@@ -1,2415 +0,0 @@
1
- <?php
2
-
3
- namespace YoastSEO_Vendor;
4
-
5
- /**
6
- *
7
- * Idiorm
8
- *
9
- * http://github.com/j4mie/idiorm/
10
- *
11
- * A single-class super-simple database abstraction layer for PHP.
12
- * Provides (nearly) zero-configuration object-relational mapping
13
- * and a fluent interface for building basic, commonly-used queries.
14
- *
15
- * BSD Licensed.
16
- *
17
- * Copyright (c) 2010, Jamie Matthews
18
- * All rights reserved.
19
- *
20
- * Redistribution and use in source and binary forms, with or without
21
- * modification, are permitted provided that the following conditions are met:
22
- *
23
- * * Redistributions of source code must retain the above copyright notice, this
24
- * list of conditions and the following disclaimer.
25
- *
26
- * * Redistributions in binary form must reproduce the above copyright notice,
27
- * this list of conditions and the following disclaimer in the documentation
28
- * and/or other materials provided with the distribution.
29
- *
30
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
34
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
- *
41
- *
42
- * The methods documented below are magic methods that conform to PSR-1.
43
- * This documentation exposes these methods to doc generators and IDEs.
44
- * @see http://www.php-fig.org/psr/psr-1/
45
- *
46
- * @method static array|string getConfig($key = null, $connection_name = self::DEFAULT_CONNECTION)
47
- * @method static null resetConfig()
48
- * @method static \ORM forTable($table_name, $connection_name = self::DEFAULT_CONNECTION)
49
- * @method static null setDb($db, $connection_name = self::DEFAULT_CONNECTION)
50
- * @method static null resetDb()
51
- * @method static null setupLimitClauseStyle($connection_name)
52
- * @method static \PDO getDb($connection_name = self::DEFAULT_CONNECTION)
53
- * @method static bool rawExecute($query, $parameters = array())
54
- * @method static \PDOStatement getLastStatement()
55
- * @method static string getLastQuery($connection_name = null)
56
- * @method static array getQueryLog($connection_name = self::DEFAULT_CONNECTION)
57
- * @method array getConnectionNames()
58
- * @method $this useIdColumn($id_column)
59
- * @method \ORM|bool findOne($id=null)
60
- * @method array|\IdiormResultSet findMany()
61
- * @method \IdiormResultSet findResultSet()
62
- * @method array findArray()
63
- * @method $this forceAllDirty()
64
- * @method $this rawQuery($query, $parameters = array())
65
- * @method $this tableAlias($alias)
66
- * @method int countNullIdColumns()
67
- * @method $this selectExpr($expr, $alias=null)
68
- * @method \ORM selectMany($values)
69
- * @method \ORM selectManyExpr($values)
70
- * @method $this rawJoin($table, $constraint, $table_alias, $parameters = array())
71
- * @method $this innerJoin($table, $constraint, $table_alias=null)
72
- * @method $this leftOuterJoin($table, $constraint, $table_alias=null)
73
- * @method $this rightOuterJoin($table, $constraint, $table_alias=null)
74
- * @method $this fullOuterJoin($table, $constraint, $table_alias=null)
75
- * @method $this whereEqual($column_name, $value=null)
76
- * @method $this whereNotEqual($column_name, $value=null)
77
- * @method $this whereIdIs($id)
78
- * @method $this whereAnyIs($values, $operator='=')
79
- * @method array|string whereIdIn($ids)
80
- * @method $this whereLike($column_name, $value=null)
81
- * @method $this whereNotLike($column_name, $value=null)
82
- * @method $this whereGt($column_name, $value=null)
83
- * @method $this whereLt($column_name, $value=null)
84
- * @method $this whereGte($column_name, $value=null)
85
- * @method $this whereLte($column_name, $value=null)
86
- * @method $this whereIn($column_name, $values)
87
- * @method $this whereNotIn($column_name, $values)
88
- * @method $this whereNull($column_name)
89
- * @method $this whereNotNull($column_name)
90
- * @method $this whereRaw($clause, $parameters=array())
91
- * @method $this orderByDesc($column_name)
92
- * @method $this orderByAsc($column_name)
93
- * @method $this orderByExpr($clause)
94
- * @method $this groupBy($column_name)
95
- * @method $this groupByExpr($expr)
96
- * @method $this havingEqual($column_name, $value=null)
97
- * @method $this havingNotEqual($column_name, $value=null)
98
- * @method $this havingIdIs($id)
99
- * @method $this havingLike($column_name, $value=null)
100
- * @method $this havingNotLike($column_name, $value=null)
101
- * @method $this havingGt($column_name, $value=null)
102
- * @method $this havingLt($column_name, $value=null)
103
- * @method $this havingGte($column_name, $value=null)
104
- * @method $this havingLte($column_name, $value=null)
105
- * @method $this havingIn($column_name, $values=null)
106
- * @method $this havingNotIn($column_name, $values=null)
107
- * @method $this havingNull($column_name)
108
- * @method $this havingNotNull($column_name)
109
- * @method $this havingRaw($clause, $parameters=array())
110
- * @method static this clearCache($table_name = null, $connection_name = self::DEFAULT_CONNECTION)
111
- * @method array asArray()
112
- * @method bool setExpr($key, $value = null)
113
- * @method bool isDirty($key)
114
- * @method bool isNew()
115
- */
116
- class ORM implements \ArrayAccess
117
- {
118
- // ----------------------- //
119
- // --- CLASS CONSTANTS --- //
120
- // ----------------------- //
121
- // WHERE and HAVING condition array keys
122
- const CONDITION_FRAGMENT = 0;
123
- const CONDITION_VALUES = 1;
124
- const DEFAULT_CONNECTION = 'default';
125
- // Limit clause style
126
- const LIMIT_STYLE_TOP_N = "top";
127
- const LIMIT_STYLE_LIMIT = "limit";
128
- // ------------------------ //
129
- // --- CLASS PROPERTIES --- //
130
- // ------------------------ //
131
- // Class configuration
132
- protected static $_default_config = array(
133
- 'connection_string' => 'sqlite::memory:',
134
- 'id_column' => 'id',
135
- 'id_column_overrides' => array(),
136
- 'error_mode' => \PDO::ERRMODE_EXCEPTION,
137
- 'username' => null,
138
- 'password' => null,
139
- 'driver_options' => null,
140
- 'identifier_quote_character' => null,
141
- // if this is null, will be autodetected
142
- 'limit_clause_style' => null,
143
- // if this is null, will be autodetected
144
- 'logging' => \false,
145
- 'logger' => null,
146
- 'caching' => \false,
147
- 'caching_auto_clear' => \false,
148
- 'return_result_sets' => \false,
149
- );
150
- // Map of configuration settings
151
- protected static $_config = array();
152
- // Map of database connections, instances of the PDO class
153
- protected static $_db = array();
154
- // Last query run, only populated if logging is enabled
155
- protected static $_last_query;
156
- // Log of all queries run, mapped by connection key, only populated if logging is enabled
157
- protected static $_query_log = array();
158
- // Query cache, only used if query caching is enabled
159
- protected static $_query_cache = array();
160
- // Reference to previously used PDOStatement object to enable low-level access, if needed
161
- protected static $_last_statement = null;
162
- // --------------------------- //
163
- // --- INSTANCE PROPERTIES --- //
164
- // --------------------------- //
165
- // Key name of the connections in self::$_db used by this instance
166
- protected $_connection_name;
167
- // The name of the table the current ORM instance is associated with
168
- protected $_table_name;
169
- // Alias for the table to be used in SELECT queries
170
- protected $_table_alias = null;
171
- // Values to be bound to the query
172
- protected $_values = array();
173
- // Columns to select in the result
174
- protected $_result_columns = array('*');
175
- // Are we using the default result column or have these been manually changed?
176
- protected $_using_default_result_columns = \true;
177
- // Join sources
178
- protected $_join_sources = array();
179
- // Should the query include a DISTINCT keyword?
180
- protected $_distinct = \false;
181
- // Is this a raw query?
182
- protected $_is_raw_query = \false;
183
- // The raw query
184
- protected $_raw_query = '';
185
- // The raw query parameters
186
- protected $_raw_parameters = array();
187
- // Array of WHERE clauses
188
- protected $_where_conditions = array();
189
- // LIMIT
190
- protected $_limit = null;
191
- // OFFSET
192
- protected $_offset = null;
193
- // ORDER BY
194
- protected $_order_by = array();
195
- // GROUP BY
196
- protected $_group_by = array();
197
- // HAVING
198
- protected $_having_conditions = array();
199
- // The data for a hydrated instance of the class
200
- protected $_data = array();
201
- // Fields that have been modified during the
202
- // lifetime of the object
203
- protected $_dirty_fields = array();
204
- // Fields that are to be inserted in the DB raw
205
- protected $_expr_fields = array();
206
- // Is this a new object (has create() been called)?
207
- protected $_is_new = \false;
208
- // Name of the column to use as the primary key for
209
- // this instance only. Overrides the config settings.
210
- protected $_instance_id_column = null;
211
- // ---------------------- //
212
- // --- STATIC METHODS --- //
213
- // ---------------------- //
214
- /**
215
- * Pass configuration settings to the class in the form of
216
- * key/value pairs. As a shortcut, if the second argument
217
- * is omitted and the key is a string, the setting is
218
- * assumed to be the DSN string used by PDO to connect
219
- * to the database (often, this will be the only configuration
220
- * required to use Idiorm). If you have more than one setting
221
- * you wish to configure, another shortcut is to pass an array
222
- * of settings (and omit the second argument).
223
- * @param string|array $key
224
- * @param mixed $value
225
- * @param string $connection_name Which connection to use
226
- */
227
- public static function configure($key, $value = null, $connection_name = self::DEFAULT_CONNECTION)
228
- {
229
- self::_setup_db_config($connection_name);
230
- //ensures at least default config is set
231
- if (\is_array($key)) {
232
- // Shortcut: If only one array argument is passed,
233
- // assume it's an array of configuration settings
234
- foreach ($key as $conf_key => $conf_value) {
235
- self::configure($conf_key, $conf_value, $connection_name);
236
- }
237
- } else {
238
- if (\is_null($value)) {
239
- // Shortcut: If only one string argument is passed,
240
- // assume it's a connection string
241
- $value = $key;
242
- $key = 'connection_string';
243
- }
244
- self::$_config[$connection_name][$key] = $value;
245
- }
246
- }
247
- /**
248
- * Retrieve configuration options by key, or as whole array.
249
- * @param string $key
250
- * @param string $connection_name Which connection to use
251
- */
252
- public static function get_config($key = null, $connection_name = self::DEFAULT_CONNECTION)
253
- {
254
- if ($key) {
255
- return self::$_config[$connection_name][$key];
256
- } else {
257
- return self::$_config[$connection_name];
258
- }
259
- }
260
- /**
261
- * Delete all configs in _config array.
262
- */
263
- public static function reset_config()
264
- {
265
- self::$_config = array();
266
- }
267
- /**
268
- * Despite its slightly odd name, this is actually the factory
269
- * method used to acquire instances of the class. It is named
270
- * this way for the sake of a readable interface, ie
271
- * ORM::for_table('table_name')->find_one()-> etc. As such,
272
- * this will normally be the first method called in a chain.
273
- * @param string $table_name
274
- * @param string $connection_name Which connection to use
275
- * @return ORM
276
- */
277
- public static function for_table($table_name, $connection_name = self::DEFAULT_CONNECTION)
278
- {
279
- self::_setup_db($connection_name);
280
- return new self($table_name, array(), $connection_name);
281
- }
282
- /**
283
- * Set up the database connection used by the class
284
- * @param string $connection_name Which connection to use
285
- */
286
- protected static function _setup_db($connection_name = self::DEFAULT_CONNECTION)
287
- {
288
- if (!\array_key_exists($connection_name, self::$_db) || !\is_object(self::$_db[$connection_name])) {
289
- self::_setup_db_config($connection_name);
290
- $db = new \PDO(self::$_config[$connection_name]['connection_string'], self::$_config[$connection_name]['username'], self::$_config[$connection_name]['password'], self::$_config[$connection_name]['driver_options']);
291
- $db->setAttribute(\PDO::ATTR_ERRMODE, self::$_config[$connection_name]['error_mode']);
292
- self::set_db($db, $connection_name);
293
- }
294
- }
295
- /**
296
- * Ensures configuration (multiple connections) is at least set to default.
297
- * @param string $connection_name Which connection to use
298
- */
299
- protected static function _setup_db_config($connection_name)
300
- {
301
- if (!\array_key_exists($connection_name, self::$_config)) {
302
- self::$_config[$connection_name] = self::$_default_config;
303
- }
304
- }
305
- /**
306
- * Set the PDO object used by Idiorm to communicate with the database.
307
- * This is public in case the ORM should use a ready-instantiated
308
- * PDO object as its database connection. Accepts an optional string key
309
- * to identify the connection if multiple connections are used.
310
- * @param PDO $db
311
- * @param string $connection_name Which connection to use
312
- */
313
- public static function set_db($db, $connection_name = self::DEFAULT_CONNECTION)
314
- {
315
- self::_setup_db_config($connection_name);
316
- self::$_db[$connection_name] = $db;
317
- if (!\is_null(self::$_db[$connection_name])) {
318
- self::_setup_identifier_quote_character($connection_name);
319
- self::_setup_limit_clause_style($connection_name);
320
- }
321
- }
322
- /**
323
- * Close and delete all registered PDO objects in _db array.
324
- */
325
- public static function reset_db()
326
- {
327
- self::$_db = null;
328
- self::$_db = array();
329
- }
330
- /**
331
- * Detect and initialise the character used to quote identifiers
332
- * (table names, column names etc). If this has been specified
333
- * manually using ORM::configure('identifier_quote_character', 'some-char'),
334
- * this will do nothing.
335
- * @param string $connection_name Which connection to use
336
- */
337
- protected static function _setup_identifier_quote_character($connection_name)
338
- {
339
- if (\is_null(self::$_config[$connection_name]['identifier_quote_character'])) {
340
- self::$_config[$connection_name]['identifier_quote_character'] = self::_detect_identifier_quote_character($connection_name);
341
- }
342
- }
343
- /**
344
- * Detect and initialise the limit clause style ("SELECT TOP 5" /
345
- * "... LIMIT 5"). If this has been specified manually using
346
- * ORM::configure('limit_clause_style', 'top'), this will do nothing.
347
- * @param string $connection_name Which connection to use
348
- */
349
- public static function _setup_limit_clause_style($connection_name)
350
- {
351
- if (\is_null(self::$_config[$connection_name]['limit_clause_style'])) {
352
- self::$_config[$connection_name]['limit_clause_style'] = self::_detect_limit_clause_style($connection_name);
353
- }
354
- }
355
- /**
356
- * Return the correct character used to quote identifiers (table
357
- * names, column names etc) by looking at the driver being used by PDO.
358
- * @param string $connection_name Which connection to use
359
- * @return string
360
- */
361
- protected static function _detect_identifier_quote_character($connection_name)
362
- {
363
- switch (self::get_db($connection_name)->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
364
- case 'pgsql':
365
- case 'sqlsrv':
366
- case 'dblib':
367
- case 'mssql':
368
- case 'sybase':
369
- case 'firebird':
370
- return '"';
371
- case 'mysql':
372
- case 'sqlite':
373
- case 'sqlite2':
374
- default:
375
- return '`';
376
- }
377
- }
378
- /**
379
- * Returns a constant after determining the appropriate limit clause
380
- * style
381
- * @param string $connection_name Which connection to use
382
- * @return string Limit clause style keyword/constant
383
- */
384
- protected static function _detect_limit_clause_style($connection_name)
385
- {
386
- switch (self::get_db($connection_name)->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
387
- case 'sqlsrv':
388
- case 'dblib':
389
- case 'mssql':
390
- return \YoastSEO_Vendor\ORM::LIMIT_STYLE_TOP_N;
391
- default:
392
- return \YoastSEO_Vendor\ORM::LIMIT_STYLE_LIMIT;
393
- }
394
- }
395
- /**
396
- * Returns the PDO instance used by the the ORM to communicate with
397
- * the database. This can be called if any low-level DB access is
398
- * required outside the class. If multiple connections are used,
399
- * accepts an optional key name for the connection.
400
- * @param string $connection_name Which connection to use
401
- * @return PDO
402
- */
403
- public static function get_db($connection_name = self::DEFAULT_CONNECTION)
404
- {
405
- self::_setup_db($connection_name);
406
- // required in case this is called before Idiorm is instantiated
407
- return self::$_db[$connection_name];
408
- }
409
- /**
410
- * Executes a raw query as a wrapper for PDOStatement::execute.
411
- * Useful for queries that can't be accomplished through Idiorm,
412
- * particularly those using engine-specific features.
413
- * @example raw_execute('SELECT `name`, AVG(`order`) FROM `customer` GROUP BY `name` HAVING AVG(`order`) > 10')
414
- * @example raw_execute('INSERT OR REPLACE INTO `widget` (`id`, `name`) SELECT `id`, `name` FROM `other_table`')
415
- * @param string $query The raw SQL query
416
- * @param array $parameters Optional bound parameters
417
- * @param string $connection_name Which connection to use
418
- * @return bool Success
419
- */
420
- public static function raw_execute($query, $parameters = array(), $connection_name = self::DEFAULT_CONNECTION)
421
- {
422
- self::_setup_db($connection_name);
423
- return self::_execute($query, $parameters, $connection_name);
424
- }
425
- /**
426
- * Returns the PDOStatement instance last used by any connection wrapped by the ORM.
427
- * Useful for access to PDOStatement::rowCount() or error information
428
- * @return PDOStatement
429
- */
430
- public static function get_last_statement()
431
- {
432
- return self::$_last_statement;
433
- }
434
- /**
435
- * Internal helper method for executing statments. Logs queries, and
436
- * stores statement object in ::_last_statment, accessible publicly
437
- * through ::get_last_statement()
438
- * @param string $query
439
- * @param array $parameters An array of parameters to be bound in to the query
440
- * @param string $connection_name Which connection to use
441
- * @return bool Response of PDOStatement::execute()
442
- */
443
- protected static function _execute($query, $parameters = array(), $connection_name = self::DEFAULT_CONNECTION)
444
- {
445
- $statement = self::get_db($connection_name)->prepare($query);
446
- self::$_last_statement = $statement;
447
- $time = \microtime(\true);
448
- foreach ($parameters as $key => &$param) {
449
- if (\is_null($param)) {
450
- $type = \PDO::PARAM_NULL;
451
- } else {
452
- if (\is_bool($param)) {
453
- $type = \PDO::PARAM_BOOL;
454
- } else {
455
- if (\is_int($param)) {
456
- $type = \PDO::PARAM_INT;
457
- } else {
458
- $type = \PDO::PARAM_STR;
459
- }
460
- }
461
- }
462
- $statement->bindParam(\is_int($key) ? ++$key : $key, $param, $type);
463
- }
464
- $q = $statement->execute();
465
- self::_log_query($query, $parameters, $connection_name, \microtime(\true) - $time);
466
- return $q;
467
- }
468
- /**
469
- * Add a query to the internal query log. Only works if the
470
- * 'logging' config option is set to true.
471
- *
472
- * This works by manually binding the parameters to the query - the
473
- * query isn't executed like this (PDO normally passes the query and
474
- * parameters to the database which takes care of the binding) but
475
- * doing it this way makes the logged queries more readable.
476
- * @param string $query
477
- * @param array $parameters An array of parameters to be bound in to the query
478
- * @param string $connection_name Which connection to use
479
- * @param float $query_time Query time
480
- * @return bool
481
- */
482
- protected static function _log_query($query, $parameters, $connection_name, $query_time)
483
- {
484
- // If logging is not enabled, do nothing
485
- if (!self::$_config[$connection_name]['logging']) {
486
- return \false;
487
- }
488
- if (!isset(self::$_query_log[$connection_name])) {
489
- self::$_query_log[$connection_name] = array();
490
- }
491
- if (empty($parameters)) {
492
- $bound_query = $query;
493
- } else {
494
- // Escape the parameters
495
- $parameters = \array_map(array(self::get_db($connection_name), 'quote'), $parameters);
496
- if (\array_values($parameters) === $parameters) {
497
- // ? placeholders
498
- // Avoid %format collision for vsprintf
499
- $query = \str_replace("%", "%%", $query);
500
- // Replace placeholders in the query for vsprintf
501
- if (\false !== \strpos($query, "'") || \false !== \strpos($query, '"')) {
502
- $query = \YoastSEO_Vendor\IdiormString::str_replace_outside_quotes("?", "%s", $query);
503
- } else {
504
- $query = \str_replace("?", "%s", $query);
505
- }
506
- // Replace the question marks in the query with the parameters
507
- $bound_query = \vsprintf($query, $parameters);
508
- } else {
509
- // named placeholders
510
- foreach ($parameters as $key => $val) {
511
- $query = \str_replace($key, $val, $query);
512
- }
513
- $bound_query = $query;
514
- }
515
- }
516
- self::$_last_query = $bound_query;
517
- self::$_query_log[$connection_name][] = $bound_query;
518
- if (\is_callable(self::$_config[$connection_name]['logger'])) {
519
- $logger = self::$_config[$connection_name]['logger'];
520
- $logger($bound_query, $query_time);
521
- }
522
- return \true;
523
- }
524
- /**
525
- * Get the last query executed. Only works if the
526
- * 'logging' config option is set to true. Otherwise
527
- * this will return null. Returns last query from all connections if
528
- * no connection_name is specified
529
- * @param null|string $connection_name Which connection to use
530
- * @return string
531
- */
532
- public static function get_last_query($connection_name = null)
533
- {
534
- if ($connection_name === null) {
535
- return self::$_last_query;
536
- }
537
- if (!isset(self::$_query_log[$connection_name])) {
538
- return '';
539
- }
540
- return \end(self::$_query_log[$connection_name]);
541
- }
542
- /**
543
- * Get an array containing all the queries run on a
544
- * specified connection up to now.
545
- * Only works if the 'logging' config option is
546
- * set to true. Otherwise, returned array will be empty.
547
- * @param string $connection_name Which connection to use
548
- */
549
- public static function get_query_log($connection_name = self::DEFAULT_CONNECTION)
550
- {
551
- if (isset(self::$_query_log[$connection_name])) {
552
- return self::$_query_log[$connection_name];
553
- }
554
- return array();
555
- }
556
- /**
557
- * Get a list of the available connection names
558
- * @return array
559
- */
560
- public static function get_connection_names()
561
- {
562
- return \array_keys(self::$_db);
563
- }
564
- // ------------------------ //
565
- // --- INSTANCE METHODS --- //
566
- // ------------------------ //
567
- /**
568
- * "Private" constructor; shouldn't be called directly.
569
- * Use the ORM::for_table factory method instead.
570
- */
571
- protected function __construct($table_name, $data = array(), $connection_name = self::DEFAULT_CONNECTION)
572
- {
573
- $this->_table_name = $table_name;
574
- $this->_data = $data;
575
- $this->_connection_name = $connection_name;
576
- self::_setup_db_config($connection_name);
577
- }
578
- /**
579
- * Create a new, empty instance of the class. Used
580
- * to add a new row to your database. May optionally
581
- * be passed an associative array of data to populate
582
- * the instance. If so, all fields will be flagged as
583
- * dirty so all will be saved to the database when
584
- * save() is called.
585
- */
586
- public function create($data = null)
587
- {
588
- $this->_is_new = \true;
589
- if (!\is_null($data)) {
590
- return $this->hydrate($data)->force_all_dirty();
591
- }
592
- return $this;
593
- }
594
- /**
595
- * Specify the ID column to use for this instance or array of instances only.
596
- * This overrides the id_column and id_column_overrides settings.
597
- *
598
- * This is mostly useful for libraries built on top of Idiorm, and will
599
- * not normally be used in manually built queries. If you don't know why
600
- * you would want to use this, you should probably just ignore it.
601
- */
602
- public function use_id_column($id_column)
603
- {
604
- $this->_instance_id_column = $id_column;
605
- return $this;
606
- }
607
- /**
608
- * Create an ORM instance from the given row (an associative
609
- * array of data fetched from the database)
610
- */
611
- protected function _create_instance_from_row($row)
612
- {
613
- $instance = self::for_table($this->_table_name, $this->_connection_name);
614
- $instance->use_id_column($this->_instance_id_column);
615
- $instance->hydrate($row);
616
- return $instance;
617
- }
618
- /**
619
- * Tell the ORM that you are expecting a single result
620
- * back from your query, and execute it. Will return
621
- * a single instance of the ORM class, or false if no
622
- * rows were returned.
623
- * As a shortcut, you may supply an ID as a parameter
624
- * to this method. This will perform a primary key
625
- * lookup on the table.
626
- */
627
- public function find_one($id = null)
628
- {
629
- if (!\is_null($id)) {
630
- $this->where_id_is($id);
631
- }
632
- $this->limit(1);
633
- $rows = $this->_run();
634
- if (empty($rows)) {
635
- return \false;
636
- }
637
- return $this->_create_instance_from_row($rows[0]);
638
- }
639
- /**
640
- * Tell the ORM that you are expecting multiple results
641
- * from your query, and execute it. Will return an array
642
- * of instances of the ORM class, or an empty array if
643
- * no rows were returned.
644
- * @return array|\IdiormResultSet
645
- */
646
- public function find_many()
647
- {
648
- if (self::$_config[$this->_connection_name]['return_result_sets']) {
649
- return $this->find_result_set();
650
- }
651
- return $this->_find_many();
652
- }
653
- /**
654
- * Tell the ORM that you are expecting multiple results
655
- * from your query, and execute it. Will return an array
656
- * of instances of the ORM class, or an empty array if
657
- * no rows were returned.
658
- * @return array
659
- */
660
- protected function _find_many()
661
- {
662
- $rows = $this->_run();
663
- return \array_map(array($this, '_create_instance_from_row'), $rows);
664
- }
665
- /**
666
- * Tell the ORM that you are expecting multiple results
667
- * from your query, and execute it. Will return a result set object
668
- * containing instances of the ORM class.
669
- * @return \IdiormResultSet
670
- */
671
- public function find_result_set()
672
- {
673
- return new \YoastSEO_Vendor\IdiormResultSet($this->_find_many());
674
- }
675
- /**
676
- * Tell the ORM that you are expecting multiple results
677
- * from your query, and execute it. Will return an array,
678
- * or an empty array if no rows were returned.
679
- * @return array
680
- */
681
- public function find_array()
682
- {
683
- return $this->_run();
684
- }
685
- /**
686
- * Tell the ORM that you wish to execute a COUNT query.
687
- * Will return an integer representing the number of
688
- * rows returned.
689
- */
690
- public function count($column = '*')
691
- {
692
- return $this->_call_aggregate_db_function(__FUNCTION__, $column);
693
- }
694
- /**
695
- * Tell the ORM that you wish to execute a MAX query.
696
- * Will return the max value of the choosen column.
697
- */
698
- public function max($column)
699
- {
700
- return $this->_call_aggregate_db_function(__FUNCTION__, $column);
701
- }
702
- /**
703
- * Tell the ORM that you wish to execute a MIN query.
704
- * Will return the min value of the choosen column.
705
- */
706
- public function min($column)
707
- {
708
- return $this->_call_aggregate_db_function(__FUNCTION__, $column);
709
- }
710
- /**
711
- * Tell the ORM that you wish to execute a AVG query.
712
- * Will return the average value of the choosen column.
713
- */
714
- public function avg($column)
715
- {
716
- return $this->_call_aggregate_db_function(__FUNCTION__, $column);
717
- }
718
- /**
719
- * Tell the ORM that you wish to execute a SUM query.
720
- * Will return the sum of the choosen column.
721
- */
722
- public function sum($column)
723
- {
724
- return $this->_call_aggregate_db_function(__FUNCTION__, $column);
725
- }
726
- /**
727
- * Execute an aggregate query on the current connection.
728
- * @param string $sql_function The aggregate function to call eg. MIN, COUNT, etc
729
- * @param string $column The column to execute the aggregate query against
730
- * @return int
731
- */
732
- protected function _call_aggregate_db_function($sql_function, $column)
733
- {
734
- $alias = \strtolower($sql_function);
735
- $sql_function = \strtoupper($sql_function);
736
- if ('*' != $column) {
737
- $column = $this->_quote_identifier($column);
738
- }
739
- $result_columns = $this->_result_columns;
740
- $this->_result_columns = array();
741
- $this->select_expr("{$sql_function}({$column})", $alias);
742
- $result = $this->find_one();
743
- $this->_result_columns = $result_columns;
744
- $return_value = 0;
745
- if ($result !== \false && isset($result->{$alias})) {
746
- if (!\is_numeric($result->{$alias})) {
747
- $return_value = $result->{$alias};
748
- } elseif ((int) $result->{$alias} == (float) $result->{$alias}) {
749
- $return_value = (int) $result->{$alias};
750
- } else {
751
- $return_value = (float) $result->{$alias};
752
- }
753
- }
754
- return $return_value;
755
- }
756
- /**
757
- * This method can be called to hydrate (populate) this
758
- * instance of the class from an associative array of data.
759
- * This will usually be called only from inside the class,
760
- * but it's public in case you need to call it directly.
761
- */
762
- public function hydrate($data = array())
763
- {
764
- $this->_data = $data;
765
- return $this;
766
- }
767
- /**
768
- * Force the ORM to flag all the fields in the $data array
769
- * as "dirty" and therefore update them when save() is called.
770
- */
771
- public function force_all_dirty()
772
- {
773
- $this->_dirty_fields = $this->_data;
774
- return $this;
775
- }
776
- /**
777
- * Perform a raw query. The query can contain placeholders in
778
- * either named or question mark style. If placeholders are
779
- * used, the parameters should be an array of values which will
780
- * be bound to the placeholders in the query. If this method
781
- * is called, all other query building methods will be ignored.
782
- */
783
- public function raw_query($query, $parameters = array())
784
- {
785
- $this->_is_raw_query = \true;
786
- $this->_raw_query = $query;
787
- $this->_raw_parameters = $parameters;
788
- return $this;
789
- }
790
- /**
791
- * Add an alias for the main table to be used in SELECT queries
792
- */
793
- public function table_alias($alias)
794
- {
795
- $this->_table_alias = $alias;
796
- return $this;
797
- }
798
- /**
799
- * Internal method to add an unquoted expression to the set
800
- * of columns returned by the SELECT query. The second optional
801
- * argument is the alias to return the expression as.
802
- */
803
- protected function _add_result_column($expr, $alias = null)
804
- {
805
- if (!\is_null($alias)) {
806
- $expr .= " AS " . $this->_quote_identifier($alias);
807
- }
808
- if ($this->_using_default_result_columns) {
809
- $this->_result_columns = array($expr);
810
- $this->_using_default_result_columns = \false;
811
- } else {
812
- $this->_result_columns[] = $expr;
813
- }
814
- return $this;
815
- }
816
- /**
817
- * Counts the number of columns that belong to the primary
818
- * key and their value is null.
819
- */
820
- public function count_null_id_columns()
821
- {
822
- if (\is_array($this->_get_id_column_name())) {
823
- return \count(\array_filter($this->id(), 'is_null'));
824
- } else {
825
- return \is_null($this->id()) ? 1 : 0;
826
- }
827
- }
828
- /**
829
- * Add a column to the list of columns returned by the SELECT
830
- * query. This defaults to '*'. The second optional argument is
831
- * the alias to return the column as.
832
- */
833
- public function select($column, $alias = null)
834
- {
835
- $column = $this->_quote_identifier($column);
836
- return $this->_add_result_column($column, $alias);
837
- }
838
- /**
839
- * Add an unquoted expression to the list of columns returned
840
- * by the SELECT query. The second optional argument is
841
- * the alias to return the column as.
842
- */
843
- public function select_expr($expr, $alias = null)
844
- {
845
- return $this->_add_result_column($expr, $alias);
846
- }
847
- /**
848
- * Add columns to the list of columns returned by the SELECT
849
- * query. This defaults to '*'. Many columns can be supplied
850
- * as either an array or as a list of parameters to the method.
851
- *
852
- * Note that the alias must not be numeric - if you want a
853
- * numeric alias then prepend it with some alpha chars. eg. a1
854
- *
855
- * @example select_many(array('alias' => 'column', 'column2', 'alias2' => 'column3'), 'column4', 'column5');
856
- * @example select_many('column', 'column2', 'column3');
857
- * @example select_many(array('column', 'column2', 'column3'), 'column4', 'column5');
858
- *
859
- * @return \ORM
860
- */
861
- public function select_many()
862
- {
863
- $columns = \func_get_args();
864
- if (!empty($columns)) {
865
- $columns = $this->_normalise_select_many_columns($columns);
866
- foreach ($columns as $alias => $column) {
867
- if (\is_numeric($alias)) {
868
- $alias = null;
869
- }
870
- $this->select($column, $alias);
871
- }
872
- }
873
- return $this;
874
- }
875
- /**
876
- * Add an unquoted expression to the list of columns returned
877
- * by the SELECT query. Many columns can be supplied as either
878
- * an array or as a list of parameters to the method.
879
- *
880
- * Note that the alias must not be numeric - if you want a
881
- * numeric alias then prepend it with some alpha chars. eg. a1
882
- *
883
- * @example select_many_expr(array('alias' => 'column', 'column2', 'alias2' => 'column3'), 'column4', 'column5')
884
- * @example select_many_expr('column', 'column2', 'column3')
885
- * @example select_many_expr(array('column', 'column2', 'column3'), 'column4', 'column5')
886
- *
887
- * @return \ORM
888
- */
889
- public function select_many_expr()
890
- {
891
- $columns = \func_get_args();
892
- if (!empty($columns)) {
893
- $columns = $this->_normalise_select_many_columns($columns);
894
- foreach ($columns as $alias => $column) {
895
- if (\is_numeric($alias)) {
896
- $alias = null;
897
- }
898
- $this->select_expr($column, $alias);
899
- }
900
- }
901
- return $this;
902
- }
903
- /**
904
- * Take a column specification for the select many methods and convert it
905
- * into a normalised array of columns and aliases.
906
- *
907
- * It is designed to turn the following styles into a normalised array:
908
- *
909
- * array(array('alias' => 'column', 'column2', 'alias2' => 'column3'), 'column4', 'column5'))
910
- *
911
- * @param array $columns
912
- * @return array
913
- */
914
- protected function _normalise_select_many_columns($columns)
915
- {
916
- $return = array();
917
- foreach ($columns as $column) {
918
- if (\is_array($column)) {
919
- foreach ($column as $key => $value) {
920
- if (!\is_numeric($key)) {
921
- $return[$key] = $value;
922
- } else {
923
- $return[] = $value;
924
- }
925
- }
926
- } else {
927
- $return[] = $column;
928
- }
929
- }
930
- return $return;
931
- }
932
- /**
933
- * Add a DISTINCT keyword before the list of columns in the SELECT query
934
- */
935
- public function distinct()
936
- {
937
- $this->_distinct = \true;
938
- return $this;
939
- }
940
- /**
941
- * Internal method to add a JOIN source to the query.
942
- *
943
- * The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this
944
- * will be prepended to JOIN.
945
- *
946
- * The table should be the name of the table to join to.
947
- *
948
- * The constraint may be either a string or an array with three elements. If it
949
- * is a string, it will be compiled into the query as-is, with no escaping. The
950
- * recommended way to supply the constraint is as an array with three elements:
951
- *
952
- * first_column, operator, second_column
953
- *
954
- * Example: array('user.id', '=', 'profile.user_id')
955
- *
956
- * will compile to
957
- *
958
- * ON `user`.`id` = `profile`.`user_id`
959
- *
960
- * The final (optional) argument specifies an alias for the joined table.
961
- */
962
- protected function _add_join_source($join_operator, $table, $constraint, $table_alias = null)
963
- {
964
- $join_operator = \trim("{$join_operator} JOIN");
965
- $table = $this->_quote_identifier($table);
966
- // Add table alias if present
967
- if (!\is_null($table_alias)) {
968
- $table_alias = $this->_quote_identifier($table_alias);
969
- $table .= " {$table_alias}";
970
- }
971
- // Build the constraint
972
- if (\is_array($constraint)) {
973
- list($first_column, $operator, $second_column) = $constraint;
974
- $first_column = $this->_quote_identifier($first_column);
975
- $second_column = $this->_quote_identifier($second_column);
976
- $constraint = "{$first_column} {$operator} {$second_column}";
977
- }
978
- $this->_join_sources[] = "{$join_operator} {$table} ON {$constraint}";
979
- return $this;
980
- }
981
- /**
982
- * Add a RAW JOIN source to the query
983
- */
984
- public function raw_join($table, $constraint, $table_alias, $parameters = array())
985
- {
986
- // Add table alias if present
987
- if (!\is_null($table_alias)) {
988
- $table_alias = $this->_quote_identifier($table_alias);
989
- $table .= " {$table_alias}";
990
- }
991
- $this->_values = \array_merge($this->_values, $parameters);
992
- // Build the constraint
993
- if (\is_array($constraint)) {
994
- list($first_column, $operator, $second_column) = $constraint;
995
- $first_column = $this->_quote_identifier($first_column);
996
- $second_column = $this->_quote_identifier($second_column);
997
- $constraint = "{$first_column} {$operator} {$second_column}";
998
- }
999
- $this->_join_sources[] = "{$table} ON {$constraint}";
1000
- return $this;
1001
- }
1002
- /**
1003
- * Add a simple JOIN source to the query
1004
- */
1005
- public function join($table, $constraint, $table_alias = null)
1006
- {
1007
- return $this->_add_join_source("", $table, $constraint, $table_alias);
1008
- }
1009
- /**
1010
- * Add an INNER JOIN souce to the query
1011
- */
1012
- public function inner_join($table, $constraint, $table_alias = null)
1013
- {
1014
- return $this->_add_join_source("INNER", $table, $constraint, $table_alias);
1015
- }
1016
- /**
1017
- * Add a LEFT OUTER JOIN souce to the query
1018
- */
1019
- public function left_outer_join($table, $constraint, $table_alias = null)
1020
- {
1021
- return $this->_add_join_source("LEFT OUTER", $table, $constraint, $table_alias);
1022
- }
1023
- /**
1024
- * Add an RIGHT OUTER JOIN souce to the query
1025
- */
1026
- public function right_outer_join($table, $constraint, $table_alias = null)
1027
- {
1028
- return $this->_add_join_source("RIGHT OUTER", $table, $constraint, $table_alias);
1029
- }
1030
- /**
1031
- * Add an FULL OUTER JOIN souce to the query
1032
- */
1033
- public function full_outer_join($table, $constraint, $table_alias = null)
1034
- {
1035
- return $this->_add_join_source("FULL OUTER", $table, $constraint, $table_alias);
1036
- }
1037
- /**
1038
- * Internal method to add a HAVING condition to the query
1039
- */
1040
- protected function _add_having($fragment, $values = array())
1041
- {
1042
- return $this->_add_condition('having', $fragment, $values);
1043
- }
1044
- /**
1045
- * Internal method to add a HAVING condition to the query
1046
- */
1047
- protected function _add_simple_having($column_name, $separator, $value)
1048
- {
1049
- return $this->_add_simple_condition('having', $column_name, $separator, $value);
1050
- }
1051
- /**
1052
- * Internal method to add a HAVING clause with multiple values (like IN and NOT IN)
1053
- */
1054
- public function _add_having_placeholder($column_name, $separator, $values)
1055
- {
1056
- if (!\is_array($column_name)) {
1057
- $data = array($column_name => $values);
1058
- } else {
1059
- $data = $column_name;
1060
- }
1061
- $result = $this;
1062
- foreach ($data as $key => $val) {
1063
- $column = $result->_quote_identifier($key);
1064
- $placeholders = $result->_create_placeholders($val);
1065
- $result = $result->_add_having("{$column} {$separator} ({$placeholders})", $val);
1066
- }
1067
- return $result;
1068
- }
1069
- /**
1070
- * Internal method to add a HAVING clause with no parameters(like IS NULL and IS NOT NULL)
1071
- */
1072
- public function _add_having_no_value($column_name, $operator)
1073
- {
1074
- $conditions = \is_array($column_name) ? $column_name : array($column_name);
1075
- $result = $this;
1076
- foreach ($conditions as $column) {
1077
- $column = $this->_quote_identifier($column);
1078
- $result = $result->_add_having("{$column} {$operator}");
1079
- }
1080
- return $result;
1081
- }
1082
- /**
1083
- * Internal method to add a WHERE condition to the query
1084
- */
1085
- protected function _add_where($fragment, $values = array())
1086
- {
1087
- return $this->_add_condition('where', $fragment, $values);
1088
- }
1089
- /**
1090
- * Internal method to add a WHERE condition to the query
1091
- */
1092
- protected function _add_simple_where($column_name, $separator, $value)
1093
- {
1094
- return $this->_add_simple_condition('where', $column_name, $separator, $value);
1095
- }
1096
- /**
1097
- * Add a WHERE clause with multiple values (like IN and NOT IN)
1098
- */
1099
- public function _add_where_placeholder($column_name, $separator, $values)
1100
- {
1101
- if (!\is_array($column_name)) {
1102
- $data = array($column_name => $values);
1103
- } else {
1104
- $data = $column_name;
1105
- }
1106
- $result = $this;
1107
- foreach ($data as $key => $val) {
1108
- $column = $result->_quote_identifier($key);
1109
- $placeholders = $result->_create_placeholders($val);
1110
- $result = $result->_add_where("{$column} {$separator} ({$placeholders})", $val);
1111
- }
1112
- return $result;
1113
- }
1114
- /**
1115
- * Add a WHERE clause with no parameters(like IS NULL and IS NOT NULL)
1116
- */
1117
- public function _add_where_no_value($column_name, $operator)
1118
- {
1119
- $conditions = \is_array($column_name) ? $column_name : array($column_name);
1120
- $result = $this;
1121
- foreach ($conditions as $column) {
1122
- $column = $this->_quote_identifier($column);
1123
- $result = $result->_add_where("{$column} {$operator}");
1124
- }
1125
- return $result;
1126
- }
1127
- /**
1128
- * Internal method to add a HAVING or WHERE condition to the query
1129
- */
1130
- protected function _add_condition($type, $fragment, $values = array())
1131
- {
1132
- $conditions_class_property_name = "_{$type}_conditions";
1133
- if (!\is_array($values)) {
1134
- $values = array($values);
1135
- }
1136
- \array_push($this->{$conditions_class_property_name}, array(self::CONDITION_FRAGMENT => $fragment, self::CONDITION_VALUES => $values));
1137
- return $this;
1138
- }
1139
- /**
1140
- * Helper method to compile a simple COLUMN SEPARATOR VALUE
1141
- * style HAVING or WHERE condition into a string and value ready to
1142
- * be passed to the _add_condition method. Avoids duplication
1143
- * of the call to _quote_identifier
1144
- *
1145
- * If column_name is an associative array, it will add a condition for each column
1146
- */
1147
- protected function _add_simple_condition($type, $column_name, $separator, $value)
1148
- {
1149
- $multiple = \is_array($column_name) ? $column_name : array($column_name => $value);
1150
- $result = $this;
1151
- foreach ($multiple as $key => $val) {
1152
- // Add the table name in case of ambiguous columns
1153
- if (\count($result->_join_sources) > 0 && \strpos($key, '.') === \false) {
1154
- $table = $result->_table_name;
1155
- if (!\is_null($result->_table_alias)) {
1156
- $table = $result->_table_alias;
1157
- }
1158
- $key = "{$table}.{$key}";
1159
- }
1160
- $key = $result->_quote_identifier($key);
1161
- $result = $result->_add_condition($type, "{$key} {$separator} ?", $val);
1162
- }
1163
- return $result;
1164
- }
1165
- /**
1166
- * Return a string containing the given number of question marks,
1167
- * separated by commas. Eg "?, ?, ?"
1168
- */
1169
- protected function _create_placeholders($fields)
1170
- {
1171
- if (!empty($fields)) {
1172
- $db_fields = array();
1173
- foreach ($fields as $key => $value) {
1174
- // Process expression fields directly into the query
1175
- if (\array_key_exists($key, $this->_expr_fields)) {
1176
- $db_fields[] = $value;
1177
- } else {
1178
- $db_fields[] = '?';
1179
- }
1180
- }
1181
- return \implode(', ', $db_fields);
1182
- }
1183
- }
1184
- /**
1185
- * Helper method that filters a column/value array returning only those
1186
- * columns that belong to a compound primary key.
1187
- *
1188
- * If the key contains a column that does not exist in the given array,
1189
- * a null value will be returned for it.
1190
- */
1191
- protected function _get_compound_id_column_values($value)
1192
- {
1193
- $filtered = array();
1194
- foreach ($this->_get_id_column_name() as $key) {
1195
- $filtered[$key] = isset($value[$key]) ? $value[$key] : null;
1196
- }
1197
- return $filtered;
1198
- }
1199
- /**
1200
- * Helper method that filters an array containing compound column/value
1201
- * arrays.
1202
- */
1203
- protected function _get_compound_id_column_values_array($values)
1204
- {
1205
- $filtered = array();
1206
- foreach ($values as $value) {
1207
- $filtered[] = $this->_get_compound_id_column_values($value);
1208
- }
1209
- return $filtered;
1210
- }
1211
- /**
1212
- * Add a WHERE column = value clause to your query. Each time
1213
- * this is called in the chain, an additional WHERE will be
1214
- * added, and these will be ANDed together when the final query
1215
- * is built.
1216
- *
1217
- * If you use an array in $column_name, a new clause will be
1218
- * added for each element. In this case, $value is ignored.
1219
- */
1220
- public function where($column_name, $value = null)
1221
- {
1222
- return $this->where_equal($column_name, $value);
1223
- }
1224
- /**
1225
- * More explicitly named version of for the where() method.
1226
- * Can be used if preferred.
1227
- */
1228
- public function where_equal($column_name, $value = null)
1229
- {
1230
- return $this->_add_simple_where($column_name, '=', $value);
1231
- }
1232
- /**
1233
- * Add a WHERE column != value clause to your query.
1234
- */
1235
- public function where_not_equal($column_name, $value = null)
1236
- {
1237
- return $this->_add_simple_where($column_name, '!=', $value);
1238
- }
1239
- /**
1240
- * Special method to query the table by its primary key
1241
- *
1242
- * If primary key is compound, only the columns that
1243
- * belong to they key will be used for the query
1244
- */
1245
- public function where_id_is($id)
1246
- {
1247
- return \is_array($this->_get_id_column_name()) ? $this->where($this->_get_compound_id_column_values($id), null) : $this->where($this->_get_id_column_name(), $id);
1248
- }
1249
- /**
1250
- * Allows adding a WHERE clause that matches any of the conditions
1251
- * specified in the array. Each element in the associative array will
1252
- * be a different condition, where the key will be the column name.
1253
- *
1254
- * By default, an equal operator will be used against all columns, but
1255
- * it can be overriden for any or every column using the second parameter.
1256
- *
1257
- * Each condition will be ORed together when added to the final query.
1258
- */
1259
- public function where_any_is($values, $operator = '=')
1260
- {
1261
- $data = array();
1262
- $query = array("((");
1263
- $first = \true;
1264
- foreach ($values as $value) {
1265
- if ($first) {
1266
- $first = \false;
1267
- } else {
1268
- $query[] = ") OR (";
1269
- }
1270
- $firstsub = \true;
1271
- foreach ($value as $key => $item) {
1272
- $op = \is_string($operator) ? $operator : (isset($operator[$key]) ? $operator[$key] : '=');
1273
- if ($firstsub) {
1274
- $firstsub = \false;
1275
- } else {
1276
- $query[] = "AND";
1277
- }
1278
- $query[] = $this->_quote_identifier($key);
1279
- $data[] = $item;
1280
- $query[] = $op . " ?";
1281
- }
1282
- }
1283
- $query[] = "))";
1284
- return $this->where_raw(\join($query, ' '), $data);
1285
- }
1286
- /**
1287
- * Similar to where_id_is() but allowing multiple primary keys.
1288
- *
1289
- * If primary key is compound, only the columns that
1290
- * belong to they key will be used for the query
1291
- */
1292
- public function where_id_in($ids)
1293
- {
1294
- return \is_array($this->_get_id_column_name()) ? $this->where_any_is($this->_get_compound_id_column_values_array($ids)) : $this->where_in($this->_get_id_column_name(), $ids);
1295
- }
1296
- /**
1297
- * Add a WHERE ... LIKE clause to your query.
1298
- */
1299
- public function where_like($column_name, $value = null)
1300
- {
1301
- return $this->_add_simple_where($column_name, 'LIKE', $value);
1302
- }
1303
- /**
1304
- * Add where WHERE ... NOT LIKE clause to your query.
1305
- */
1306
- public function where_not_like($column_name, $value = null)
1307
- {
1308
- return $this->_add_simple_where($column_name, 'NOT LIKE', $value);
1309
- }
1310
- /**
1311
- * Add a WHERE ... > clause to your query
1312
- */
1313
- public function where_gt($column_name, $value = null)
1314
- {
1315
- return $this->_add_simple_where($column_name, '>', $value);
1316
- }
1317
- /**
1318
- * Add a WHERE ... < clause to your query
1319
- */
1320
- public function where_lt($column_name, $value = null)
1321
- {
1322
- return $this->_add_simple_where($column_name, '<', $value);
1323
- }
1324
- /**
1325
- * Add a WHERE ... >= clause to your query
1326
- */
1327
- public function where_gte($column_name, $value = null)
1328
- {
1329
- return $this->_add_simple_where($column_name, '>=', $value);
1330
- }
1331
- /**
1332
- * Add a WHERE ... <= clause to your query
1333
- */
1334
- public function where_lte($column_name, $value = null)
1335
- {
1336
- return $this->_add_simple_where($column_name, '<=', $value);
1337
- }
1338
- /**
1339
- * Add a WHERE ... IN clause to your query
1340
- */
1341
- public function where_in($column_name, $values)
1342
- {
1343
- return $this->_add_where_placeholder($column_name, 'IN', $values);
1344
- }
1345
- /**
1346
- * Add a WHERE ... NOT IN clause to your query
1347
- */
1348
- public function where_not_in($column_name, $values)
1349
- {
1350
- return $this->_add_where_placeholder($column_name, 'NOT IN', $values);
1351
- }
1352
- /**
1353
- * Add a WHERE column IS NULL clause to your query
1354
- */
1355
- public function where_null($column_name)
1356
- {
1357
- return $this->_add_where_no_value($column_name, "IS NULL");
1358
- }
1359
- /**
1360
- * Add a WHERE column IS NOT NULL clause to your query
1361
- */
1362
- public function where_not_null($column_name)
1363
- {
1364
- return $this->_add_where_no_value($column_name, "IS NOT NULL");
1365
- }
1366
- /**
1367
- * Add a raw WHERE clause to the query. The clause should
1368
- * contain question mark placeholders, which will be bound
1369
- * to the parameters supplied in the second argument.
1370
- */
1371
- public function where_raw($clause, $parameters = array())
1372
- {
1373
- return $this->_add_where($clause, $parameters);
1374
- }
1375
- /**
1376
- * Add a LIMIT to the query
1377
- */
1378
- public function limit($limit)
1379
- {
1380
- $this->_limit = $limit;
1381
- return $this;
1382
- }
1383
- /**
1384
- * Add an OFFSET to the query
1385
- */
1386
- public function offset($offset)
1387
- {
1388
- $this->_offset = $offset;
1389
- return $this;
1390
- }
1391
- /**
1392
- * Add an ORDER BY clause to the query
1393
- */
1394
- protected function _add_order_by($column_name, $ordering)
1395
- {
1396
- $column_name = $this->_quote_identifier($column_name);
1397
- $this->_order_by[] = "{$column_name} {$ordering}";
1398
- return $this;
1399
- }
1400
- /**
1401
- * Add an ORDER BY column DESC clause
1402
- */
1403
- public function order_by_desc($column_name)
1404
- {
1405
- return $this->_add_order_by($column_name, 'DESC');
1406
- }
1407
- /**
1408
- * Add an ORDER BY column ASC clause
1409
- */
1410
- public function order_by_asc($column_name)
1411
- {
1412
- return $this->_add_order_by($column_name, 'ASC');
1413
- }
1414
- /**
1415
- * Add an unquoted expression as an ORDER BY clause
1416
- */
1417
- public function order_by_expr($clause)
1418
- {
1419
- $this->_order_by[] = $clause;
1420
- return $this;
1421
- }
1422
- /**
1423
- * Add a column to the list of columns to GROUP BY
1424
- */
1425
- public function group_by($column_name)
1426
- {
1427
- $column_name = $this->_quote_identifier($column_name);
1428
- $this->_group_by[] = $column_name;
1429
- return $this;
1430
- }
1431
- /**
1432
- * Add an unquoted expression to the list of columns to GROUP BY
1433
- */
1434
- public function group_by_expr($expr)
1435
- {
1436
- $this->_group_by[] = $expr;
1437
- return $this;
1438
- }
1439
- /**
1440
- * Add a HAVING column = value clause to your query. Each time
1441
- * this is called in the chain, an additional HAVING will be
1442
- * added, and these will be ANDed together when the final query
1443
- * is built.
1444
- *
1445
- * If you use an array in $column_name, a new clause will be
1446
- * added for each element. In this case, $value is ignored.
1447
- */
1448
- public function having($column_name, $value = null)
1449
- {
1450
- return $this->having_equal($column_name, $value);
1451
- }
1452
- /**
1453
- * More explicitly named version of for the having() method.
1454
- * Can be used if preferred.
1455
- */
1456
- public function having_equal($column_name, $value = null)
1457
- {
1458
- return $this->_add_simple_having($column_name, '=', $value);
1459
- }
1460
- /**
1461
- * Add a HAVING column != value clause to your query.
1462
- */
1463
- public function having_not_equal($column_name, $value = null)
1464
- {
1465
- return $this->_add_simple_having($column_name, '!=', $value);
1466
- }
1467
- /**
1468
- * Special method to query the table by its primary key.
1469
- *
1470
- * If primary key is compound, only the columns that
1471
- * belong to they key will be used for the query
1472
- */
1473
- public function having_id_is($id)
1474
- {
1475
- return \is_array($this->_get_id_column_name()) ? $this->having($this->_get_compound_id_column_values($id), null) : $this->having($this->_get_id_column_name(), $id);
1476
- }
1477
- /**
1478
- * Add a HAVING ... LIKE clause to your query.
1479
- */
1480
- public function having_like($column_name, $value = null)
1481
- {
1482
- return $this->_add_simple_having($column_name, 'LIKE', $value);
1483
- }
1484
- /**
1485
- * Add where HAVING ... NOT LIKE clause to your query.
1486
- */
1487
- public function having_not_like($column_name, $value = null)
1488
- {
1489
- return $this->_add_simple_having($column_name, 'NOT LIKE', $value);
1490
- }
1491
- /**
1492
- * Add a HAVING ... > clause to your query
1493
- */
1494
- public function having_gt($column_name, $value = null)
1495
- {
1496
- return $this->_add_simple_having($column_name, '>', $value);
1497
- }
1498
- /**
1499
- * Add a HAVING ... < clause to your query
1500
- */
1501
- public function having_lt($column_name, $value = null)
1502
- {
1503
- return $this->_add_simple_having($column_name, '<', $value);
1504
- }
1505
- /**
1506
- * Add a HAVING ... >= clause to your query
1507
- */
1508
- public function having_gte($column_name, $value = null)
1509
- {
1510
- return $this->_add_simple_having($column_name, '>=', $value);
1511
- }
1512
- /**
1513
- * Add a HAVING ... <= clause to your query
1514
- */
1515
- public function having_lte($column_name, $value = null)
1516
- {
1517
- return $this->_add_simple_having($column_name, '<=', $value);
1518
- }
1519
- /**
1520
- * Add a HAVING ... IN clause to your query
1521
- */
1522
- public function having_in($column_name, $values = null)
1523
- {
1524
- return $this->_add_having_placeholder($column_name, 'IN', $values);
1525
- }
1526
- /**
1527
- * Add a HAVING ... NOT IN clause to your query
1528
- */
1529
- public function having_not_in($column_name, $values = null)
1530
- {
1531
- return $this->_add_having_placeholder($column_name, 'NOT IN', $values);
1532
- }
1533
- /**
1534
- * Add a HAVING column IS NULL clause to your query
1535
- */
1536
- public function having_null($column_name)
1537
- {
1538
- return $this->_add_having_no_value($column_name, 'IS NULL');
1539
- }
1540
- /**
1541
- * Add a HAVING column IS NOT NULL clause to your query
1542
- */
1543
- public function having_not_null($column_name)
1544
- {
1545
- return $this->_add_having_no_value($column_name, 'IS NOT NULL');
1546
- }
1547
- /**
1548
- * Add a raw HAVING clause to the query. The clause should
1549
- * contain question mark placeholders, which will be bound
1550
- * to the parameters supplied in the second argument.
1551
- */
1552
- public function having_raw($clause, $parameters = array())
1553
- {
1554
- return $this->_add_having($clause, $parameters);
1555
- }
1556
- /**
1557
- * Build a SELECT statement based on the clauses that have
1558
- * been passed to this instance by chaining method calls.
1559
- */
1560
- protected function _build_select()
1561
- {
1562
- // If the query is raw, just set the $this->_values to be
1563
- // the raw query parameters and return the raw query
1564
- if ($this->_is_raw_query) {
1565
- $this->_values = $this->_raw_parameters;
1566
- return $this->_raw_query;
1567
- }
1568
- // Build and return the full SELECT statement by concatenating
1569
- // the results of calling each separate builder method.
1570
- return $this->_join_if_not_empty(" ", array($this->_build_select_start(), $this->_build_join(), $this->_build_where(), $this->_build_group_by(), $this->_build_having(), $this->_build_order_by(), $this->_build_limit(), $this->_build_offset()));
1571
- }
1572
- /**
1573
- * Build the start of the SELECT statement
1574
- */
1575
- protected function _build_select_start()
1576
- {
1577
- $fragment = 'SELECT ';
1578
- $result_columns = \join(', ', $this->_result_columns);
1579
- if (!\is_null($this->_limit) && self::$_config[$this->_connection_name]['limit_clause_style'] === \YoastSEO_Vendor\ORM::LIMIT_STYLE_TOP_N) {
1580
- $fragment .= "TOP {$this->_limit} ";
1581
- }
1582
- if ($this->_distinct) {
1583
- $result_columns = 'DISTINCT ' . $result_columns;
1584
- }
1585
- $fragment .= "{$result_columns} FROM " . $this->_quote_identifier($this->_table_name);
1586
- if (!\is_null($this->_table_alias)) {
1587
- $fragment .= " " . $this->_quote_identifier($this->_table_alias);
1588
- }
1589
- return $fragment;
1590
- }
1591
- /**
1592
- * Build the JOIN sources
1593
- */
1594
- protected function _build_join()
1595
- {
1596
- if (\count($this->_join_sources) === 0) {
1597
- return '';
1598
- }
1599
- return \join(" ", $this->_join_sources);
1600
- }
1601
- /**
1602
- * Build the WHERE clause(s)
1603
- */
1604
- protected function _build_where()
1605
- {
1606
- return $this->_build_conditions('where');
1607
- }
1608
- /**
1609
- * Build the HAVING clause(s)
1610
- */
1611
- protected function _build_having()
1612
- {
1613
- return $this->_build_conditions('having');
1614
- }
1615
- /**
1616
- * Build GROUP BY
1617
- */
1618
- protected function _build_group_by()
1619
- {
1620
- if (\count($this->_group_by) === 0) {
1621
- return '';
1622
- }
1623
- return "GROUP BY " . \join(", ", $this->_group_by);
1624
- }
1625
- /**
1626
- * Build a WHERE or HAVING clause
1627
- * @param string $type
1628
- * @return string
1629
- */
1630
- protected function _build_conditions($type)
1631
- {
1632
- $conditions_class_property_name = "_{$type}_conditions";
1633
- // If there are no clauses, return empty string
1634
- if (\count($this->{$conditions_class_property_name}) === 0) {
1635
- return '';
1636
- }
1637
- $conditions = array();
1638
- foreach ($this->{$conditions_class_property_name} as $condition) {
1639
- $conditions[] = $condition[self::CONDITION_FRAGMENT];
1640
- $this->_values = \array_merge($this->_values, $condition[self::CONDITION_VALUES]);
1641
- }
1642
- return \strtoupper($type) . " " . \join(" AND ", $conditions);
1643
- }
1644
- /**
1645
- * Build ORDER BY
1646
- */
1647
- protected function _build_order_by()
1648
- {
1649
- if (\count($this->_order_by) === 0) {
1650
- return '';
1651
- }
1652
- return "ORDER BY " . \join(", ", $this->_order_by);
1653
- }
1654
- /**
1655
- * Build LIMIT
1656
- */
1657
- protected function _build_limit()
1658
- {
1659
- $fragment = '';
1660
- if (!\is_null($this->_limit) && self::$_config[$this->_connection_name]['limit_clause_style'] == \YoastSEO_Vendor\ORM::LIMIT_STYLE_LIMIT) {
1661
- if (self::get_db($this->_connection_name)->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'firebird') {
1662
- $fragment = 'ROWS';
1663
- } else {
1664
- $fragment = 'LIMIT';
1665
- }
1666
- $fragment .= " {$this->_limit}";
1667
- }
1668
- return $fragment;
1669
- }
1670
- /**
1671
- * Build OFFSET
1672
- */
1673
- protected function _build_offset()
1674
- {
1675
- if (!\is_null($this->_offset)) {
1676
- $clause = 'OFFSET';
1677
- if (self::get_db($this->_connection_name)->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'firebird') {
1678
- $clause = 'TO';
1679
- }
1680
- return "{$clause} " . $this->_offset;
1681
- }
1682
- return '';
1683
- }
1684
- /**
1685
- * Wrapper around PHP's join function which
1686
- * only adds the pieces if they are not empty.
1687
- */
1688
- protected function _join_if_not_empty($glue, $pieces)
1689
- {
1690
- $filtered_pieces = array();
1691
- foreach ($pieces as $piece) {
1692
- if (\is_string($piece)) {
1693
- $piece = \trim($piece);
1694
- }
1695
- if (!empty($piece)) {
1696
- $filtered_pieces[] = $piece;
1697
- }
1698
- }
1699
- return \join($glue, $filtered_pieces);
1700
- }
1701
- /**
1702
- * Quote a string that is used as an identifier
1703
- * (table names, column names etc). This method can
1704
- * also deal with dot-separated identifiers eg table.column
1705
- */
1706
- protected function _quote_one_identifier($identifier)
1707
- {
1708
- $parts = \explode('.', $identifier);
1709
- $parts = \array_map(array($this, '_quote_identifier_part'), $parts);
1710
- return \join('.', $parts);
1711
- }
1712
- /**
1713
- * Quote a string that is used as an identifier
1714
- * (table names, column names etc) or an array containing
1715
- * multiple identifiers. This method can also deal with
1716
- * dot-separated identifiers eg table.column
1717
- */
1718
- protected function _quote_identifier($identifier)
1719
- {
1720
- if (\is_array($identifier)) {
1721
- $result = \array_map(array($this, '_quote_one_identifier'), $identifier);
1722
- return \join(', ', $result);
1723
- } else {
1724
- return $this->_quote_one_identifier($identifier);
1725
- }
1726
- }
1727
- /**
1728
- * This method performs the actual quoting of a single
1729
- * part of an identifier, using the identifier quote
1730
- * character specified in the config (or autodetected).
1731
- */
1732
- protected function _quote_identifier_part($part)
1733
- {
1734
- if ($part === '*') {
1735
- return $part;
1736
- }
1737
- $quote_character = self::$_config[$this->_connection_name]['identifier_quote_character'];
1738
- // double up any identifier quotes to escape them
1739
- return $quote_character . \str_replace($quote_character, $quote_character . $quote_character, $part) . $quote_character;
1740
- }
1741
- /**
1742
- * Create a cache key for the given query and parameters.
1743
- */
1744
- protected static function _create_cache_key($query, $parameters, $table_name = null, $connection_name = self::DEFAULT_CONNECTION)
1745
- {
1746
- if (isset(self::$_config[$connection_name]['create_cache_key']) and \is_callable(self::$_config[$connection_name]['create_cache_key'])) {
1747
- return \call_user_func_array(self::$_config[$connection_name]['create_cache_key'], array($query, $parameters, $table_name, $connection_name));
1748
- }
1749
- $parameter_string = \join(',', $parameters);
1750
- $key = $query . ':' . $parameter_string;
1751
- return \sha1($key);
1752
- }
1753
- /**
1754
- * Check the query cache for the given cache key. If a value
1755
- * is cached for the key, return the value. Otherwise, return false.
1756
- */
1757
- protected static function _check_query_cache($cache_key, $table_name = null, $connection_name = self::DEFAULT_CONNECTION)
1758
- {
1759
- if (isset(self::$_config[$connection_name]['check_query_cache']) and \is_callable(self::$_config[$connection_name]['check_query_cache'])) {
1760
- return \call_user_func_array(self::$_config[$connection_name]['check_query_cache'], array($cache_key, $table_name, $connection_name));
1761
- } elseif (isset(self::$_query_cache[$connection_name][$cache_key])) {
1762
- return self::$_query_cache[$connection_name][$cache_key];
1763
- }
1764
- return \false;
1765
- }
1766
- /**
1767
- * Clear the query cache
1768
- */
1769
- public static function clear_cache($table_name = null, $connection_name = self::DEFAULT_CONNECTION)
1770
- {
1771
- self::$_query_cache = array();
1772
- if (isset(self::$_config[$connection_name]['clear_cache']) and \is_callable(self::$_config[$connection_name]['clear_cache'])) {
1773
- return \call_user_func_array(self::$_config[$connection_name]['clear_cache'], array($table_name, $connection_name));
1774
- }
1775
- }
1776
- /**
1777
- * Add the given value to the query cache.
1778
- */
1779
- protected static function _cache_query_result($cache_key, $value, $table_name = null, $connection_name = self::DEFAULT_CONNECTION)
1780
- {
1781
- if (isset(self::$_config[$connection_name]['cache_query_result']) and \is_callable(self::$_config[$connection_name]['cache_query_result'])) {
1782
- return \call_user_func_array(self::$_config[$connection_name]['cache_query_result'], array($cache_key, $value, $table_name, $connection_name));
1783
- } elseif (!isset(self::$_query_cache[$connection_name])) {
1784
- self::$_query_cache[$connection_name] = array();
1785
- }
1786
- self::$_query_cache[$connection_name][$cache_key] = $value;
1787
- }
1788
- /**
1789
- * Execute the SELECT query that has been built up by chaining methods
1790
- * on this class. Return an array of rows as associative arrays.
1791
- */
1792
- protected function _run()
1793
- {
1794
- $query = $this->_build_select();
1795
- $caching_enabled = self::$_config[$this->_connection_name]['caching'];
1796
- if ($caching_enabled) {
1797
- $cache_key = self::_create_cache_key($query, $this->_values, $this->_table_name, $this->_connection_name);
1798
- $cached_result = self::_check_query_cache($cache_key, $this->_table_name, $this->_connection_name);
1799
- if ($cached_result !== \false) {
1800
- $this->_reset_idiorm_state();
1801
- return $cached_result;
1802
- }
1803
- }
1804
- self::_execute($query, $this->_values, $this->_connection_name);
1805
- $statement = self::get_last_statement();
1806
- $rows = array();
1807
- while ($row = $statement->fetch(\PDO::FETCH_ASSOC)) {
1808
- $rows[] = $row;
1809
- }
1810
- if ($caching_enabled) {
1811
- self::_cache_query_result($cache_key, $rows, $this->_table_name, $this->_connection_name);
1812
- }
1813
- $this->_reset_idiorm_state();
1814
- return $rows;
1815
- }
1816
- /**
1817
- * Reset the Idiorm instance state
1818
- */
1819
- private function _reset_idiorm_state()
1820
- {
1821
- $this->_values = array();
1822
- $this->_result_columns = array('*');
1823
- $this->_using_default_result_columns = \true;
1824
- }
1825
- /**
1826
- * Return the raw data wrapped by this ORM
1827
- * instance as an associative array. Column
1828
- * names may optionally be supplied as arguments,
1829
- * if so, only those keys will be returned.
1830
- */
1831
- public function as_array()
1832
- {
1833
- if (\func_num_args() === 0) {
1834
- return $this->_data;
1835
- }
1836
- $args = \func_get_args();
1837
- return \array_intersect_key($this->_data, \array_flip($args));
1838
- }
1839
- /**
1840
- * Return the value of a property of this object (database row)
1841
- * or null if not present.
1842
- *
1843
- * If a column-names array is passed, it will return a associative array
1844
- * with the value of each column or null if it is not present.
1845
- */
1846
- public function get($key)
1847
- {
1848
- if (\is_array($key)) {
1849
- $result = array();
1850
- foreach ($key as $column) {
1851
- $result[$column] = isset($this->_data[$column]) ? $this->_data[$column] : null;
1852
- }
1853
- return $result;
1854
- } else {
1855
- return isset($this->_data[$key]) ? $this->_data[$key] : null;
1856
- }
1857
- }
1858
- /**
1859
- * Return the name of the column in the database table which contains
1860
- * the primary key ID of the row.
1861
- */
1862
- protected function _get_id_column_name()
1863
- {
1864
- if (!\is_null($this->_instance_id_column)) {
1865
- return $this->_instance_id_column;
1866
- }
1867
- if (isset(self::$_config[$this->_connection_name]['id_column_overrides'][$this->_table_name])) {
1868
- return self::$_config[$this->_connection_name]['id_column_overrides'][$this->_table_name];
1869
- }
1870
- return self::$_config[$this->_connection_name]['id_column'];
1871
- }
1872
- /**
1873
- * Get the primary key ID of this object.
1874
- */
1875
- public function id($disallow_null = \false)
1876
- {
1877
- $id = $this->get($this->_get_id_column_name());
1878
- if ($disallow_null) {
1879
- if (\is_array($id)) {
1880
- foreach ($id as $id_part) {
1881
- if ($id_part === null) {
1882
- throw new \Exception('Primary key ID contains null value(s)');
1883
- }
1884
- }
1885
- } else {
1886
- if ($id === null) {
1887
- throw new \Exception('Primary key ID missing from row or is null');
1888
- }
1889
- }
1890
- }
1891
- return $id;
1892
- }
1893
- /**
1894
- * Set a property to a particular value on this object.
1895
- * To set multiple properties at once, pass an associative array
1896
- * as the first parameter and leave out the second parameter.
1897
- * Flags the properties as 'dirty' so they will be saved to the
1898
- * database when save() is called.
1899
- */
1900
- public function set($key, $value = null)
1901
- {
1902
- return $this->_set_orm_property($key, $value);
1903
- }
1904
- /**
1905
- * Set a property to a particular value on this object.
1906
- * To set multiple properties at once, pass an associative array
1907
- * as the first parameter and leave out the second parameter.
1908
- * Flags the properties as 'dirty' so they will be saved to the
1909
- * database when save() is called.
1910
- * @param string|array $key
1911
- * @param string|null $value
1912
- */
1913
- public function set_expr($key, $value = null)
1914
- {
1915
- return $this->_set_orm_property($key, $value, \true);
1916
- }
1917
- /**
1918
- * Set a property on the ORM object.
1919
- * @param string|array $key
1920
- * @param string|null $value
1921
- * @param bool $raw Whether this value should be treated as raw or not
1922
- */
1923
- protected function _set_orm_property($key, $value = null, $expr = \false)
1924
- {
1925
- if (!\is_array($key)) {
1926
- $key = array($key => $value);
1927
- }
1928
- foreach ($key as $field => $value) {
1929
- $this->_data[$field] = $value;
1930
- $this->_dirty_fields[$field] = $value;
1931
- if (\false === $expr and isset($this->_expr_fields[$field])) {
1932
- unset($this->_expr_fields[$field]);
1933
- } else {
1934
- if (\true === $expr) {
1935
- $this->_expr_fields[$field] = \true;
1936
- }
1937
- }
1938
- }
1939
- return $this;
1940
- }
1941
- /**
1942
- * Check whether the given field has been changed since this
1943
- * object was saved.
1944
- */
1945
- public function is_dirty($key)
1946
- {
1947
- return \array_key_exists($key, $this->_dirty_fields);
1948
- }
1949
- /**
1950
- * Check whether the model was the result of a call to create() or not
1951
- * @return bool
1952
- */
1953
- public function is_new()
1954
- {
1955
- return $this->_is_new;
1956
- }
1957
- /**
1958
- * Save any fields which have been modified on this object
1959
- * to the database.
1960
- */
1961
- public function save()
1962
- {
1963
- $query = array();
1964
- // remove any expression fields as they are already baked into the query
1965
- $values = \array_values(\array_diff_key($this->_dirty_fields, $this->_expr_fields));
1966
- if (!$this->_is_new) {
1967
- // UPDATE
1968
- // If there are no dirty values, do nothing
1969
- if (empty($values) && empty($this->_expr_fields)) {
1970
- return \true;
1971
- }
1972
- $query = $this->_build_update();
1973
- $id = $this->id(\true);
1974
- if (\is_array($id)) {
1975
- $values = \array_merge($values, \array_values($id));
1976
- } else {
1977
- $values[] = $id;
1978
- }
1979
- } else {
1980
- // INSERT
1981
- $query = $this->_build_insert();
1982
- }
1983
- $success = self::_execute($query, $values, $this->_connection_name);
1984
- $caching_auto_clear_enabled = self::$_config[$this->_connection_name]['caching_auto_clear'];
1985
- if ($caching_auto_clear_enabled) {
1986
- self::clear_cache($this->_table_name, $this->_connection_name);
1987
- }
1988
- // If we've just inserted a new record, set the ID of this object
1989
- if ($this->_is_new) {
1990
- $this->_is_new = \false;
1991
- if ($this->count_null_id_columns() != 0) {
1992
- $db = self::get_db($this->_connection_name);
1993
- if ($db->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'pgsql') {
1994
- // it may return several columns if a compound primary
1995
- // key is used
1996
- $row = self::get_last_statement()->fetch(\PDO::FETCH_ASSOC);
1997
- foreach ($row as $key => $value) {
1998
- $this->_data[$key] = $value;
1999
- }
2000
- } else {
2001
- $column = $this->_get_id_column_name();
2002
- // if the primary key is compound, assign the last inserted id
2003
- // to the first column
2004
- if (\is_array($column)) {
2005
- $column = \reset($column);
2006
- }
2007
- $this->_data[$column] = $db->lastInsertId();
2008
- }
2009
- }
2010
- }
2011
- $this->_dirty_fields = $this->_expr_fields = array();
2012
- return $success;
2013
- }
2014
- /**
2015
- * Add a WHERE clause for every column that belongs to the primary key
2016
- */
2017
- public function _add_id_column_conditions(&$query)
2018
- {
2019
- $query[] = "WHERE";
2020
- $keys = \is_array($this->_get_id_column_name()) ? $this->_get_id_column_name() : array($this->_get_id_column_name());
2021
- $first = \true;
2022
- foreach ($keys as $key) {
2023
- if ($first) {
2024
- $first = \false;
2025
- } else {
2026
- $query[] = "AND";
2027
- }
2028
- $query[] = $this->_quote_identifier($key);
2029
- $query[] = "= ?";
2030
- }
2031
- }
2032
- /**
2033
- * Build an UPDATE query
2034
- */
2035
- protected function _build_update()
2036
- {
2037
- $query = array();
2038
- $query[] = "UPDATE {$this->_quote_identifier($this->_table_name)} SET";
2039
- $field_list = array();
2040
- foreach ($this->_dirty_fields as $key => $value) {
2041
- if (!\array_key_exists($key, $this->_expr_fields)) {
2042
- $value = '?';
2043
- }
2044
- $field_list[] = "{$this->_quote_identifier($key)} = {$value}";
2045
- }
2046
- $query[] = \join(", ", $field_list);
2047
- $this->_add_id_column_conditions($query);
2048
- return \join(" ", $query);
2049
- }
2050
- /**
2051
- * Build an INSERT query
2052
- */
2053
- protected function _build_insert()
2054
- {
2055
- $query[] = "INSERT INTO";
2056
- $query[] = $this->_quote_identifier($this->_table_name);
2057
- $field_list = \array_map(array($this, '_quote_identifier'), \array_keys($this->_dirty_fields));
2058
- $query[] = "(" . \join(", ", $field_list) . ")";
2059
- $query[] = "VALUES";
2060
- $placeholders = $this->_create_placeholders($this->_dirty_fields);
2061
- $query[] = "({$placeholders})";
2062
- if (self::get_db($this->_connection_name)->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'pgsql') {
2063
- $query[] = 'RETURNING ' . $this->_quote_identifier($this->_get_id_column_name());
2064
- }
2065
- return \join(" ", $query);
2066
- }
2067
- /**
2068
- * Delete this record from the database
2069
- */
2070
- public function delete()
2071
- {
2072
- $query = array("DELETE FROM", $this->_quote_identifier($this->_table_name));
2073
- $this->_add_id_column_conditions($query);
2074
- return self::_execute(\join(" ", $query), \is_array($this->id(\true)) ? \array_values($this->id(\true)) : array($this->id(\true)), $this->_connection_name);
2075
- }
2076
- /**
2077
- * Delete many records from the database
2078
- */
2079
- public function delete_many()
2080
- {
2081
- // Build and return the full DELETE statement by concatenating
2082
- // the results of calling each separate builder method.
2083
- $query = $this->_join_if_not_empty(" ", array("DELETE FROM", $this->_quote_identifier($this->_table_name), $this->_build_where()));
2084
- return self::_execute($query, $this->_values, $this->_connection_name);
2085
- }
2086
- // --------------------- //
2087
- // --- ArrayAccess --- //
2088
- // --------------------- //
2089
- public function offsetExists($key)
2090
- {
2091
- return \array_key_exists($key, $this->_data);
2092
- }
2093
- public function offsetGet($key)
2094
- {
2095
- return $this->get($key);
2096
- }
2097
- public function offsetSet($key, $value)
2098
- {
2099
- if (\is_null($key)) {
2100
- throw new \InvalidArgumentException('You must specify a key/array index.');
2101
- }
2102
- $this->set($key, $value);
2103
- }
2104
- public function offsetUnset($key)
2105
- {
2106
- unset($this->_data[$key]);
2107
- unset($this->_dirty_fields[$key]);
2108
- }
2109
- // --------------------- //
2110
- // --- MAGIC METHODS --- //
2111
- // --------------------- //
2112
- public function __get($key)
2113
- {
2114
- return $this->offsetGet($key);
2115
- }
2116
- public function __set($key, $value)
2117
- {
2118
- $this->offsetSet($key, $value);
2119
- }
2120
- public function __unset($key)
2121
- {
2122
- $this->offsetUnset($key);
2123
- }
2124
- public function __isset($key)
2125
- {
2126
- return $this->offsetExists($key);
2127
- }
2128
- /**
2129
- * Magic method to capture calls to undefined class methods.
2130
- * In this case we are attempting to convert camel case formatted
2131
- * methods into underscore formatted methods.
2132
- *
2133
- * This allows us to call ORM methods using camel case and remain
2134
- * backwards compatible.
2135
- *
2136
- * @param string $name
2137
- * @param array $arguments
2138
- * @return ORM
2139
- */
2140
- public function __call($name, $arguments)
2141
- {
2142
- $method = \strtolower(\preg_replace('/([a-z])([A-Z])/', '$1_$2', $name));
2143
- if (\method_exists($this, $method)) {
2144
- return \call_user_func_array(array($this, $method), $arguments);
2145
- } else {
2146
- throw new \YoastSEO_Vendor\IdiormMethodMissingException("Method {$name}() does not exist in class " . \get_class($this));
2147
- }
2148
- }
2149
- /**
2150
- * Magic method to capture calls to undefined static class methods.
2151
- * In this case we are attempting to convert camel case formatted
2152
- * methods into underscore formatted methods.
2153
- *
2154
- * This allows us to call ORM methods using camel case and remain
2155
- * backwards compatible.
2156
- *
2157
- * @param string $name
2158
- * @param array $arguments
2159
- * @return ORM
2160
- */
2161
- public static function __callStatic($name, $arguments)
2162
- {
2163
- $method = \strtolower(\preg_replace('/([a-z])([A-Z])/', '$1_$2', $name));
2164
- return \call_user_func_array(array('ORM', $method), $arguments);
2165
- }
2166
- }
2167
- /**
2168
- * A class to handle str_replace operations that involve quoted strings
2169
- * @example IdiormString::str_replace_outside_quotes('?', '%s', 'columnA = "Hello?" AND columnB = ?');
2170
- * @example IdiormString::value('columnA = "Hello?" AND columnB = ?')->replace_outside_quotes('?', '%s');
2171
- * @author Jeff Roberson <ridgerunner@fluxbb.org>
2172
- * @author Simon Holywell <treffynnon@php.net>
2173
- * @link http://stackoverflow.com/a/13370709/461813 StackOverflow answer
2174
- */
2175
- class IdiormString
2176
- {
2177
- protected $subject;
2178
- protected $search;
2179
- protected $replace;
2180
- /**
2181
- * Get an easy to use instance of the class
2182
- * @param string $subject
2183
- * @return \self
2184
- */
2185
- public static function value($subject)
2186
- {
2187
- return new self($subject);
2188
- }
2189
- /**
2190
- * Shortcut method: Replace all occurrences of the search string with the replacement
2191
- * string where they appear outside quotes.
2192
- * @param string $search
2193
- * @param string $replace
2194
- * @param string $subject
2195
- * @return string
2196
- */
2197
- public static function str_replace_outside_quotes($search, $replace, $subject)
2198
- {
2199
- return self::value($subject)->replace_outside_quotes($search, $replace);
2200
- }
2201
- /**
2202
- * Set the base string object
2203
- * @param string $subject
2204
- */
2205
- public function __construct($subject)
2206
- {
2207
- $this->subject = (string) $subject;
2208
- }
2209
- /**
2210
- * Replace all occurrences of the search string with the replacement
2211
- * string where they appear outside quotes
2212
- * @param string $search
2213
- * @param string $replace
2214
- * @return string
2215
- */
2216
- public function replace_outside_quotes($search, $replace)
2217
- {
2218
- $this->search = $search;
2219
- $this->replace = $replace;
2220
- return $this->_str_replace_outside_quotes();
2221
- }
2222
- /**
2223
- * Validate an input string and perform a replace on all ocurrences
2224
- * of $this->search with $this->replace
2225
- * @author Jeff Roberson <ridgerunner@fluxbb.org>
2226
- * @link http://stackoverflow.com/a/13370709/461813 StackOverflow answer
2227
- * @return string
2228
- */
2229
- protected function _str_replace_outside_quotes()
2230
- {
2231
- $re_valid = '/
2232
- # Validate string having embedded quoted substrings.
2233
- ^ # Anchor to start of string.
2234
- (?: # Zero or more string chunks.
2235
- "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" # Either a double quoted chunk,
2236
- | \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' # or a single quoted chunk,
2237
- | [^\'"\\\\]+ # or an unquoted chunk (no escapes).
2238
- )* # Zero or more string chunks.
2239
- \\z # Anchor to end of string.
2240
- /sx';
2241
- if (!\preg_match($re_valid, $this->subject)) {
2242
- throw new \YoastSEO_Vendor\IdiormStringException("Subject string is not valid in the replace_outside_quotes context.");
2243
- }
2244
- $re_parse = '/
2245
- # Match one chunk of a valid string having embedded quoted substrings.
2246
- ( # Either $1: Quoted chunk.
2247
- "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" # Either a double quoted chunk,
2248
- | \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' # or a single quoted chunk.
2249
- ) # End $1: Quoted chunk.
2250
- | ([^\'"\\\\]+) # or $2: an unquoted chunk (no escapes).
2251
- /sx';
2252
- return \preg_replace_callback($re_parse, array($this, '_str_replace_outside_quotes_cb'), $this->subject);
2253
- }
2254
- /**
2255
- * Process each matching chunk from preg_replace_callback replacing
2256
- * each occurrence of $this->search with $this->replace
2257
- * @author Jeff Roberson <ridgerunner@fluxbb.org>
2258
- * @link http://stackoverflow.com/a/13370709/461813 StackOverflow answer
2259
- * @param array $matches
2260
- * @return string
2261
- */
2262
- protected function _str_replace_outside_quotes_cb($matches)
2263
- {
2264
- // Return quoted string chunks (in group $1) unaltered.
2265
- if ($matches[1]) {
2266
- return $matches[1];
2267
- }
2268
- // Process only unquoted chunks (in group $2).
2269
- return \preg_replace('/' . \preg_quote($this->search, '/') . '/', $this->replace, $matches[2]);
2270
- }
2271
- }
2272
- /**
2273
- * A result set class for working with collections of model instances
2274
- * @author Simon Holywell <treffynnon@php.net>
2275
- * @method null setResults(array $results)
2276
- * @method array getResults()
2277
- */
2278
- class IdiormResultSet implements \Countable, \IteratorAggregate, \ArrayAccess, \Serializable
2279
- {
2280
- /**
2281
- * The current result set as an array
2282
- * @var array
2283
- */
2284
- protected $_results = array();
2285
- /**
2286
- * Optionally set the contents of the result set by passing in array
2287
- * @param array $results
2288
- */
2289
- public function __construct(array $results = array())
2290
- {
2291
- $this->set_results($results);
2292
- }
2293
- /**
2294
- * Set the contents of the result set by passing in array
2295
- * @param array $results
2296
- */
2297
- public function set_results(array $results)
2298
- {
2299
- $this->_results = $results;
2300
- }
2301
- /**
2302
- * Get the current result set as an array
2303
- * @return array
2304
- */
2305
- public function get_results()
2306
- {
2307
- return $this->_results;
2308
- }
2309
- /**
2310
- * Get the current result set as an array
2311
- * @return array
2312
- */
2313
- public function as_array()
2314
- {
2315
- return $this->get_results();
2316
- }
2317
- /**
2318
- * Get the number of records in the result set
2319
- * @return int
2320
- */
2321
- public function count()
2322
- {
2323
- return \count($this->_results);
2324
- }
2325
- /**
2326
- * Get an iterator for this object. In this case it supports foreaching
2327
- * over the result set.
2328
- * @return \ArrayIterator
2329
- */
2330
- public function getIterator()
2331
- {
2332
- return new \ArrayIterator($this->_results);
2333
- }
2334
- /**
2335
- * ArrayAccess
2336
- * @param int|string $offset
2337
- * @return bool
2338
- */
2339
- public function offsetExists($offset)
2340
- {
2341
- return isset($this->_results[$offset]);
2342
- }
2343
- /**
2344
- * ArrayAccess
2345
- * @param int|string $offset
2346
- * @return mixed
2347
- */
2348
- public function offsetGet($offset)
2349
- {
2350
- return $this->_results[$offset];
2351
- }
2352
- /**
2353
- * ArrayAccess
2354
- * @param int|string $offset
2355
- * @param mixed $value
2356
- */
2357
- public function offsetSet($offset, $value)
2358
- {
2359
- $this->_results[$offset] = $value;
2360
- }
2361
- /**
2362
- * ArrayAccess
2363
- * @param int|string $offset
2364
- */
2365
- public function offsetUnset($offset)
2366
- {
2367
- unset($this->_results[$offset]);
2368
- }
2369
- /**
2370
- * Serializable
2371
- * @return string
2372
- */
2373
- public function serialize()
2374
- {
2375
- return \serialize($this->_results);
2376
- }
2377
- /**
2378
- * Serializable
2379
- * @param string $serialized
2380
- * @return array
2381
- */
2382
- public function unserialize($serialized)
2383
- {
2384
- return \unserialize($serialized);
2385
- }
2386
- /**
2387
- * Call a method on all models in a result set. This allows for method
2388
- * chaining such as setting a property on all models in a result set or
2389
- * any other batch operation across models.
2390
- * @example ORM::for_table('Widget')->find_many()->set('field', 'value')->save();
2391
- * @param string $method
2392
- * @param array $params
2393
- * @return \IdiormResultSet
2394
- */
2395
- public function __call($method, $params = array())
2396
- {
2397
- foreach ($this->_results as $model) {
2398
- if (\method_exists($model, $method)) {
2399
- \call_user_func_array(array($model, $method), $params);
2400
- } else {
2401
- throw new \YoastSEO_Vendor\IdiormMethodMissingException("Method {$method}() does not exist in class " . \get_class($this));
2402
- }
2403
- }
2404
- return $this;
2405
- }
2406
- }
2407
- /**
2408
- * A placeholder for exceptions eminating from the IdiormString class
2409
- */
2410
- class IdiormStringException extends \Exception
2411
- {
2412
- }
2413
- class IdiormMethodMissingException extends \Exception
2414
- {
2415
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wp-seo-main.php CHANGED
@@ -15,7 +15,7 @@ if ( ! function_exists( 'add_filter' ) ) {
15
  * {@internal Nobody should be able to overrule the real version number as this can cause
16
  * serious issues with the options, so no if ( ! defined() ).}}
17
  */
18
- define( 'WPSEO_VERSION', '14.0.2' );
19
 
20
 
21
  if ( ! defined( 'WPSEO_PATH' ) ) {
15
  * {@internal Nobody should be able to overrule the real version number as this can cause
16
  * serious issues with the options, so no if ( ! defined() ).}}
17
  */
18
+ define( 'WPSEO_VERSION', '14.0.3' );
19
 
20
 
21
  if ( ! defined( 'WPSEO_PATH' ) ) {
wp-seo.php CHANGED
@@ -8,7 +8,7 @@
8
  *
9
  * @wordpress-plugin
10
  * Plugin Name: Yoast SEO
11
- * Version: 14.0.2
12
  * Plugin URI: https://yoa.st/1uj
13
  * Description: The first true all-in-one SEO solution for WordPress, including on-page content analysis, XML sitemaps and much more.
14
  * Author: Team Yoast
8
  *
9
  * @wordpress-plugin
10
  * Plugin Name: Yoast SEO
11
+ * Version: 14.0.3
12
  * Plugin URI: https://yoa.st/1uj
13
  * Description: The first true all-in-one SEO solution for WordPress, including on-page content analysis, XML sitemaps and much more.
14
  * Author: Team Yoast