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 | Yoast SEO |
Version | 14.0.3 |
Comparing to | |
See all releases |
Code changes from version 14.0.2 to 14.0.3
- config/dependency-injection/services.php +1 -0
- css/dist/{admin-global-1402-rtl.css → admin-global-1403-rtl.css} +0 -0
- css/dist/{admin-global-1402.css → admin-global-1403.css} +0 -0
- css/dist/{adminbar-1402-rtl.css → adminbar-1403-rtl.css} +0 -0
- css/dist/{adminbar-1402.css → adminbar-1403.css} +0 -0
- css/dist/{alerts-1402-rtl.css → alerts-1403-rtl.css} +0 -0
- css/dist/{alerts-1402.css → alerts-1403.css} +0 -0
- css/dist/{dashboard-1402-rtl.css → dashboard-1403-rtl.css} +0 -0
- css/dist/{dashboard-1402.css → dashboard-1403.css} +0 -0
- css/dist/{edit-page-1402-rtl.css → edit-page-1403-rtl.css} +0 -0
- css/dist/{edit-page-1402.css → edit-page-1403.css} +0 -0
- css/dist/{featured-image-1402-rtl.css → featured-image-1403-rtl.css} +0 -0
- css/dist/{featured-image-1402.css → featured-image-1403.css} +0 -0
- css/dist/{filter-explanation-1402-rtl.css → filter-explanation-1403-rtl.css} +0 -0
- css/dist/{filter-explanation-1402.css → filter-explanation-1403.css} +0 -0
- css/dist/{inside-editor-1402-rtl.css → inside-editor-1403-rtl.css} +0 -0
- css/dist/{inside-editor-1402.css → inside-editor-1403.css} +0 -0
- css/dist/{metabox-1402-rtl.css → metabox-1403-rtl.css} +0 -0
- css/dist/{metabox-1402.css → metabox-1403.css} +0 -0
- css/dist/{metabox-primary-category-1402-rtl.css → metabox-primary-category-1403-rtl.css} +0 -0
- css/dist/{metabox-primary-category-1402.css → metabox-primary-category-1403.css} +0 -0
- css/dist/{monorepo-1402-rtl.css → monorepo-1403-rtl.css} +0 -0
- css/dist/{monorepo-1402.css → monorepo-1403.css} +0 -0
- css/dist/{search-appearance-1402-rtl.css → search-appearance-1403-rtl.css} +0 -0
- css/dist/{search-appearance-1402.css → search-appearance-1403.css} +0 -0
- css/dist/{structured-data-blocks-1402-rtl.css → structured-data-blocks-1403-rtl.css} +0 -0
- css/dist/{structured-data-blocks-1402.css → structured-data-blocks-1403.css} +0 -0
- css/dist/{toggle-switch-1402-rtl.css → toggle-switch-1403-rtl.css} +0 -0
- css/dist/{toggle-switch-1402.css → toggle-switch-1403.css} +0 -0
- css/dist/{wpseo-dismissible-1402-rtl.css → wpseo-dismissible-1403-rtl.css} +0 -0
- css/dist/{wpseo-dismissible-1402.css → wpseo-dismissible-1403.css} +0 -0
- css/dist/{yoast-components-1402-rtl.css → yoast-components-1403-rtl.css} +0 -0
- css/dist/{yoast-components-1402.css → yoast-components-1403.css} +0 -0
- css/dist/{yoast-extensions-1402-rtl.css → yoast-extensions-1403-rtl.css} +0 -0
- css/dist/{yoast-extensions-1402.css → yoast-extensions-1403.css} +0 -0
- css/dist/{yst_plugin_tools-1402-rtl.css → yst_plugin_tools-1403-rtl.css} +0 -0
- css/dist/{yst_plugin_tools-1402.css → yst_plugin_tools-1403.css} +0 -0
- css/dist/{yst_seo_score-1402-rtl.css → yst_seo_score-1403-rtl.css} +0 -0
- css/dist/{yst_seo_score-1402.css → yst_seo_score-1403.css} +0 -0
- deprecated/frontend/breadcrumbs.php +4 -1
- deprecated/frontend/frontend.php +31 -20
- inc/class-upgrade.php +41 -33
- js/dist/{analysis-1402.js → analysis-1403.js} +0 -0
- js/dist/{babel-polyfill-1402.js → babel-polyfill-1403.js} +0 -0
- js/dist/{commons-1402.js → commons-1403.js} +0 -0
- js/dist/{components-1402.js → components-1403.js} +0 -0
- js/dist/{configuration-wizard-1402.js → configuration-wizard-1403.js} +0 -0
- js/dist/{help-scout-beacon-1402.js → help-scout-beacon-1403.js} +0 -0
- js/dist/{jed-1402.js → jed-1403.js} +0 -0
- js/dist/{redux-1402.js → redux-1403.js} +0 -0
- js/dist/{search-appearance-1402.js → search-appearance-1403.js} +0 -0
- js/dist/{styled-components-1402.js → styled-components-1403.js} +0 -0
- js/dist/{wp-seo-admin-1402.js → wp-seo-admin-1403.js} +0 -0
- js/dist/{wp-seo-admin-global-1402.js → wp-seo-admin-global-1403.js} +0 -0
- js/dist/{wp-seo-admin-gsc-1402.js → wp-seo-admin-gsc-1403.js} +0 -0
- js/dist/{wp-seo-admin-media-1402.js → wp-seo-admin-media-1403.js} +0 -0
- js/dist/{wp-seo-analysis-worker-1402.js → wp-seo-analysis-worker-1403.js} +0 -0
- js/dist/{wp-seo-api-1402.js → wp-seo-api-1403.js} +0 -0
- js/dist/{wp-seo-bulk-editor-1402.js → wp-seo-bulk-editor-1403.js} +0 -0
- js/dist/{wp-seo-dashboard-widget-1402.js → wp-seo-dashboard-widget-1403.js} +0 -0
- js/dist/{wp-seo-edit-page-1402.js → wp-seo-edit-page-1403.js} +0 -0
- js/dist/{wp-seo-featured-image-1402.js → wp-seo-featured-image-1403.js} +0 -0
- js/dist/{wp-seo-filter-explanation-1402.js → wp-seo-filter-explanation-1403.js} +0 -0
- js/dist/{wp-seo-indexation-1402.js → wp-seo-indexation-1403.js} +0 -0
- js/dist/{wp-seo-metabox-1402.js → wp-seo-metabox-1403.js} +0 -0
- js/dist/{wp-seo-metabox-category-1402.js → wp-seo-metabox-category-1403.js} +0 -0
- js/dist/{wp-seo-modal-1402.js → wp-seo-modal-1403.js} +0 -0
- js/dist/{wp-seo-network-admin-1402.js → wp-seo-network-admin-1403.js} +0 -0
- js/dist/{wp-seo-post-scraper-1402.js → wp-seo-post-scraper-1403.js} +0 -0
- js/dist/{wp-seo-quick-edit-handler-1402.js → wp-seo-quick-edit-handler-1403.js} +0 -0
- js/dist/{wp-seo-recalculate-1402.js → wp-seo-recalculate-1403.js} +0 -0
- js/dist/{wp-seo-reindex-links-1402.js → wp-seo-reindex-links-1403.js} +0 -0
- js/dist/{wp-seo-replacevar-plugin-1402.js → wp-seo-replacevar-plugin-1403.js} +0 -0
- js/dist/{wp-seo-shortcode-plugin-1402.js → wp-seo-shortcode-plugin-1403.js} +0 -0
- js/dist/{wp-seo-structured-data-blocks-1402.js → wp-seo-structured-data-blocks-1403.js} +0 -0
- js/dist/{wp-seo-term-scraper-1402.js → wp-seo-term-scraper-1403.js} +0 -0
- js/dist/{wp-seo-used-keywords-assessment-1402.js → wp-seo-used-keywords-assessment-1403.js} +0 -0
- languages/wordpress-seo-ro_RO.json +1 -1
- languages/wordpress-seojs-ro_RO.json +1 -1
- lib/orm.php +3 -4
- lib/ruckusing-adapter.php +186 -56
- readme.txt +19 -1
- {migrations → src/config/migrations}/20171228151840_WpYoastIndexable.php +0 -0
- {migrations → src/config/migrations}/20171228151841_WpYoastPrimaryTerm.php +0 -0
- {migrations → src/config/migrations}/20190529075038_WpYoastDropIndexableMetaTableIfExists.php +0 -0
- {migrations → src/config/migrations}/20191011111109_WpYoastIndexableHierarchy.php +0 -0
- {migrations → src/config/migrations}/20200408101900_AddCollationToTables.php +0 -0
- {migrations → src/config/migrations}/20200420073606_AddColumnsToIndexables.php +0 -0
- {migrations → src/config/migrations}/20200428123747_BreadcrumbTitleAndHierarchyReset.php +0 -0
- {migrations → src/config/migrations}/20200428194858_ExpandIndexableColumnLengths.php +0 -0
- {migrations → src/config/migrations}/20200429105310_TruncateIndexableTables.php +0 -0
- src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php +56 -0
- {migrations → src/config/migrations}/ruckusing/lib/Ruckusing/Adapter/why +0 -0
- {migrations → src/config/migrations}/ruckusing/lib/Task/why +0 -0
- src/config/ruckusing-framework.php +1 -1
- src/generated/container.php +1 -1
- src/generators/breadcrumbs-generator.php +37 -6
- src/initializers/migration-runner.php +1 -1
- src/integrations/breadcrumbs-integration.php +4 -1
- src/integrations/front-end-integration.php +11 -2
- src/integrations/third-party/woocommerce.php +38 -3
- src/presenters/title-presenter.php +13 -0
- src/repositories/indexable-hierarchy-repository.php +4 -5
- src/repositories/indexable-repository.php +3 -5
- src/repositories/primary-term-repository.php +4 -6
- src/repositories/seo-links-repository.php +3 -5
- src/repositories/seo-meta-repository.php +4 -6
- src/routes/route-interface.php +1 -1
- src/surfaces/values/meta.php +9 -4
- vendor/autoload.php +1 -1
- vendor/autoload_52.php +0 -7
- vendor/composer/ClassLoader.php +4 -4
- vendor/composer/ClassLoader52.php +0 -271
- vendor/composer/autoload_classmap.php +10 -5
- vendor/composer/autoload_real.php +4 -7
- vendor/composer/autoload_real_52.php +0 -58
- vendor/composer/autoload_static.php +14 -9
- vendor_prefixed/j4mie/idiorm/idiorm.php +0 -2415
- wp-seo-main.php +1 -1
- 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 |
-
$
|
|
|
|
|
|
|
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 |
-
$
|
112 |
if ( ! $echo ) {
|
113 |
-
return $
|
114 |
}
|
115 |
|
116 |
$presenter = new Canonical_Presenter();
|
117 |
-
|
|
|
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 |
-
$
|
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 |
-
$
|
143 |
-
$presenter
|
144 |
-
$presenter->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 |
-
$
|
162 |
|
163 |
-
return $
|
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 |
-
$
|
177 |
-
$title
|
178 |
|
179 |
-
return $this->replace_vars->replace( $title, $
|
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 |
-
$
|
226 |
|
227 |
$rel_prev_presenter = new Rel_Prev_Presenter();
|
228 |
-
$rel_prev_presenter->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 = $
|
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 |
-
$
|
251 |
|
252 |
if ( ! $echo ) {
|
253 |
-
return $
|
254 |
}
|
255 |
|
256 |
$presenter = new Meta_Description_Presenter();
|
257 |
-
$presenter->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'
|
23 |
-
'2.0'
|
24 |
-
'2.1'
|
25 |
-
'2.2'
|
26 |
-
'2.3'
|
27 |
-
'3.0'
|
28 |
-
'3.3'
|
29 |
-
'3.6'
|
30 |
-
'4.0'
|
31 |
-
'4.4'
|
32 |
-
'4.7'
|
33 |
-
'4.9'
|
34 |
-
'5.0'
|
35 |
-
'5.1'
|
36 |
-
'5.5'
|
37 |
-
'5.6'
|
38 |
-
'6.1'
|
39 |
-
'6.3'
|
40 |
-
'7.0-RC0'
|
41 |
-
'7.1-RC0'
|
42 |
-
'7.3-RC0'
|
43 |
-
'7.4-RC0'
|
44 |
-
'7.5.3'
|
45 |
-
'7.7-RC0'
|
46 |
-
'7.7.2-RC0'
|
47 |
-
'9.0-RC0'
|
48 |
-
'10.0-RC0'
|
49 |
-
'11.1-RC0'
|
50 |
/** Reset notifications because we removed the AMP Glue plugin notification */
|
51 |
-
'12.1-RC0'
|
52 |
-
'12.3-RC0'
|
53 |
-
'12.4-RC0'
|
54 |
-
'12.8-RC0'
|
55 |
-
'13.2-RC0'
|
|
|
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ă.
|
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
|
230 |
*
|
231 |
-
* @return ORM Instance of the ORM
|
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 = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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
|
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
|
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
|
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 |
-
|
253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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
|
|
|
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
|
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
|
432 |
* @param string $column_name the column name
|
433 |
-
* @param string $type
|
434 |
-
* @param array $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
|
481 |
-
* @param string $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
|
498 |
$current_type = $column_info['type'];
|
499 |
-
$sql
|
500 |
-
$sql
|
|
|
501 |
return $this->execute_ddl( $sql );
|
502 |
}
|
503 |
// rename_column
|
|
|
504 |
/**
|
505 |
* Change a column
|
506 |
*
|
507 |
-
* @param string $table_name
|
508 |
* @param string $column_name the column name
|
509 |
-
* @param string $type
|
510 |
-
* @param array $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
|
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
|
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
|
573 |
* @param string $column_name the column name
|
574 |
-
* @param array $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
|
621 |
* @param string $column_name the column name
|
622 |
-
* @param array $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', [
|
|
|
|
|
|
|
|
|
|
|
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
|
693 |
* @param string $column_name the column name
|
694 |
-
* @param array $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
|
729 |
-
$result
|
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
|
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
|
768 |
$precision = null;
|
769 |
-
$limit
|
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( [
|
|
|
|
|
|
|
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
|
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
|
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
|
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.
|
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
|
|
|
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 |
-
|
|
|
153 |
return false;
|
154 |
}
|
155 |
|
156 |
-
|
157 |
-
|
|
|
|
|
|
|
|
|
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 |
-
$
|
|
|
|
|
|
|
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 |
-
|
|
|
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 = $
|
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
|
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
|
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\
|
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
|
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\
|
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
|
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\
|
6 |
*/
|
7 |
|
8 |
namespace Yoast\WP\SEO\Repositories;
|
9 |
|
10 |
-
use Yoast\WP\
|
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
|
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\
|
6 |
*/
|
7 |
|
8 |
namespace Yoast\WP\SEO\Repositories;
|
9 |
|
10 |
-
use Yoast\WP\
|
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
|
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\
|
6 |
*/
|
7 |
|
8 |
namespace Yoast\WP\SEO\Repositories;
|
9 |
|
10 |
-
use Yoast\WP\
|
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
|
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
|
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\
|
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 = $
|
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 |
-
|
|
|
|
|
|
|
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 = $
|
186 |
$presenter->helpers = $this->helpers;
|
187 |
$presenter->replace_vars = $this->replace_vars;
|
188 |
$value = $presenter->get();
|
189 |
}
|
190 |
else {
|
191 |
-
$value = $
|
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
|
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') &&
|
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 |
-
|
|
|
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
|
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('
|
26 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
27 |
-
spl_autoload_unregister(array('
|
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\
|
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
|
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 =
|
891 |
-
$loader->prefixDirsPsr4 =
|
892 |
-
$loader->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.
|
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.
|
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
|