Version Description
Release Date: April 29th, 2020
Because weve changed the underlying framework of our Indexables technology, weve chosen to rebuild the table. This means you will have to go through the indexing process again. Were sorry. For sites with more than 10,000 posts, we advise using the WP CLI command to do the indexation on the server.
Bugfixes:
- Fixes a bug where a fatal error would be thrown when a title contained more than 191 characters.
- Fixes a bug where a fatal error would be thrown when a focus keyphrase contained more than 191 characters.
- Fixes a bug where a fatal error would be thrown when search engines were disallowed from indexing the site.
- Fixes a bug where a fatal error would be thrown on WooCommerce installations when the
wpseo_metadesc
filter was called with only 1 argument. - Fixes a bug where a fatal error would be thrown when using the
WPSEO_Frontend
class to get the meta description. - Fixes a bug where a fatal error would be thrown when
WPSEO_Frontend
orWPSEO_Breadcrumbs
was called before theinit
action. - Fixes a bug where a non-object property retrieval notice would be thrown when the site's content was being indexed.
- Fixes a bug where a trailing slash would be added to canonical URLs and some
rel="prev"
URLs, even when the permalink structure settings didn't contain that trailing slash. - Fixes a bug where a double breadcrumb would be shown on home pages.
- Fixes a bug where the indexation would continue indefinitely under specific circumstances.
Other:
- Removes all usages of
PDO
andmysqli
directly and useswpdb
everywhere. This should prevent a lot of errors for database installations that have different encodings or configurations than what is generally seen.
Download this release
Release Info
Developer | Yoast |
Plugin | Yoast SEO |
Version | 14.0.2 |
Comparing to | |
See all releases |
Code changes from version 14.0.1 to 14.0.2
- config/php-scoper/idiorm.inc.php +0 -37
- css/dist/{admin-global-1401-rtl.css → admin-global-1402-rtl.css} +0 -0
- css/dist/{admin-global-1401.css → admin-global-1402.css} +0 -0
- css/dist/{adminbar-1401-rtl.css → adminbar-1402-rtl.css} +0 -0
- css/dist/{adminbar-1401.css → adminbar-1402.css} +0 -0
- css/dist/{alerts-1401-rtl.css → alerts-1402-rtl.css} +0 -0
- css/dist/{alerts-1401.css → alerts-1402.css} +0 -0
- css/dist/{dashboard-1401-rtl.css → dashboard-1402-rtl.css} +0 -0
- css/dist/{dashboard-1401.css → dashboard-1402.css} +0 -0
- css/dist/{edit-page-1401-rtl.css → edit-page-1402-rtl.css} +0 -0
- css/dist/{edit-page-1401.css → edit-page-1402.css} +0 -0
- css/dist/{featured-image-1401-rtl.css → featured-image-1402-rtl.css} +0 -0
- css/dist/{featured-image-1401.css → featured-image-1402.css} +0 -0
- css/dist/{filter-explanation-1401-rtl.css → filter-explanation-1402-rtl.css} +0 -0
- css/dist/{filter-explanation-1401.css → filter-explanation-1402.css} +0 -0
- css/dist/{inside-editor-1401-rtl.css → inside-editor-1402-rtl.css} +0 -0
- css/dist/{inside-editor-1401.css → inside-editor-1402.css} +0 -0
- css/dist/{metabox-1401-rtl.css → metabox-1402-rtl.css} +0 -0
- css/dist/{metabox-1401.css → metabox-1402.css} +0 -0
- css/dist/{metabox-primary-category-1401-rtl.css → metabox-primary-category-1402-rtl.css} +0 -0
- css/dist/{metabox-primary-category-1401.css → metabox-primary-category-1402.css} +0 -0
- css/dist/{monorepo-1401-rtl.css → monorepo-1402-rtl.css} +0 -0
- css/dist/{monorepo-1401.css → monorepo-1402.css} +0 -0
- css/dist/{search-appearance-1401-rtl.css → search-appearance-1402-rtl.css} +0 -0
- css/dist/{search-appearance-1401.css → search-appearance-1402.css} +0 -0
- css/dist/{structured-data-blocks-1401-rtl.css → structured-data-blocks-1402-rtl.css} +0 -0
- css/dist/{structured-data-blocks-1401.css → structured-data-blocks-1402.css} +0 -0
- css/dist/{toggle-switch-1401-rtl.css → toggle-switch-1402-rtl.css} +0 -0
- css/dist/{toggle-switch-1401.css → toggle-switch-1402.css} +0 -0
- css/dist/{wpseo-dismissible-1401-rtl.css → wpseo-dismissible-1402-rtl.css} +0 -0
- css/dist/{wpseo-dismissible-1401.css → wpseo-dismissible-1402.css} +0 -0
- css/dist/{yoast-components-1401-rtl.css → yoast-components-1402-rtl.css} +0 -0
- css/dist/{yoast-components-1401.css → yoast-components-1402.css} +0 -0
- css/dist/{yoast-extensions-1401-rtl.css → yoast-extensions-1402-rtl.css} +0 -0
- css/dist/{yoast-extensions-1401.css → yoast-extensions-1402.css} +0 -0
- css/dist/{yst_plugin_tools-1401-rtl.css → yst_plugin_tools-1402-rtl.css} +0 -0
- css/dist/{yst_plugin_tools-1401.css → yst_plugin_tools-1402.css} +0 -0
- css/dist/{yst_seo_score-1401-rtl.css → yst_seo_score-1402-rtl.css} +0 -0
- css/dist/{yst_seo_score-1401.css → yst_seo_score-1402.css} +0 -0
- {src/backwards-compatibility → deprecated/frontend}/breadcrumbs.php +11 -26
- {src/backwards-compatibility → deprecated/frontend}/frontend.php +28 -26
- js/dist/{analysis-1401.js → analysis-1402.js} +0 -0
- js/dist/{babel-polyfill-1401.js → babel-polyfill-1402.js} +0 -0
- js/dist/{commons-1401.js → commons-1402.js} +0 -0
- js/dist/{components-1401.js → components-1402.js} +0 -0
- js/dist/{configuration-wizard-1401.js → configuration-wizard-1402.js} +0 -0
- js/dist/{help-scout-beacon-1401.js → help-scout-beacon-1402.js} +0 -0
- js/dist/{jed-1401.js → jed-1402.js} +0 -0
- js/dist/{redux-1401.js → redux-1402.js} +0 -0
- js/dist/{search-appearance-1401.js → search-appearance-1402.js} +0 -0
- js/dist/{styled-components-1401.js → styled-components-1402.js} +0 -0
- js/dist/{wp-seo-admin-1401.js → wp-seo-admin-1402.js} +0 -0
- js/dist/{wp-seo-admin-global-1401.js → wp-seo-admin-global-1402.js} +0 -0
- js/dist/{wp-seo-admin-gsc-1401.js → wp-seo-admin-gsc-1402.js} +0 -0
- js/dist/{wp-seo-admin-media-1401.js → wp-seo-admin-media-1402.js} +0 -0
- js/dist/{wp-seo-analysis-worker-1401.js → wp-seo-analysis-worker-1402.js} +0 -0
- js/dist/{wp-seo-api-1401.js → wp-seo-api-1402.js} +0 -0
- js/dist/{wp-seo-bulk-editor-1401.js → wp-seo-bulk-editor-1402.js} +0 -0
- js/dist/{wp-seo-dashboard-widget-1401.js → wp-seo-dashboard-widget-1402.js} +0 -0
- js/dist/{wp-seo-edit-page-1401.js → wp-seo-edit-page-1402.js} +0 -0
- js/dist/{wp-seo-featured-image-1401.js → wp-seo-featured-image-1402.js} +0 -0
- js/dist/{wp-seo-filter-explanation-1401.js → wp-seo-filter-explanation-1402.js} +0 -0
- js/dist/{wp-seo-indexation-1401.js → wp-seo-indexation-1402.js} +0 -0
- js/dist/{wp-seo-metabox-1401.js → wp-seo-metabox-1402.js} +0 -0
- js/dist/{wp-seo-metabox-category-1401.js → wp-seo-metabox-category-1402.js} +0 -0
- js/dist/{wp-seo-modal-1401.js → wp-seo-modal-1402.js} +0 -0
- js/dist/{wp-seo-network-admin-1401.js → wp-seo-network-admin-1402.js} +0 -0
- js/dist/{wp-seo-post-scraper-1401.js → wp-seo-post-scraper-1402.js} +0 -0
- js/dist/{wp-seo-quick-edit-handler-1401.js → wp-seo-quick-edit-handler-1402.js} +0 -0
- js/dist/{wp-seo-recalculate-1401.js → wp-seo-recalculate-1402.js} +0 -0
- js/dist/{wp-seo-reindex-links-1401.js → wp-seo-reindex-links-1402.js} +0 -0
- js/dist/{wp-seo-replacevar-plugin-1401.js → wp-seo-replacevar-plugin-1402.js} +0 -0
- js/dist/{wp-seo-shortcode-plugin-1401.js → wp-seo-shortcode-plugin-1402.js} +0 -0
- js/dist/{wp-seo-structured-data-blocks-1401.js → wp-seo-structured-data-blocks-1402.js} +0 -0
- js/dist/{wp-seo-term-scraper-1401.js → wp-seo-term-scraper-1402.js} +0 -0
- js/dist/{wp-seo-used-keywords-assessment-1401.js → wp-seo-used-keywords-assessment-1402.js} +0 -0
- languages/wordpress-seojs-de_DE.json +1 -1
- languages/yoast-components-de_DE.json +1 -1
- src/orm/yoast-model.php → lib/model.php +28 -80
- lib/orm.php +2342 -0
- lib/ruckusing-adapter.php +1084 -0
- lib/ruckusing-framework-runner.php +266 -0
- migrations/20171228151840_WpYoastIndexable.php +2 -2
- migrations/20171228151841_WpYoastPrimaryTerm.php +2 -2
- migrations/20190529075038_WpYoastDropIndexableMetaTableIfExists.php +2 -2
- migrations/20191011111109_WpYoastIndexableHierarchy.php +2 -2
- migrations/20200408101900_AddCollationToTables.php +5 -5
- migrations/20200420073606_AddColumnsToIndexables.php +4 -4
- migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php +3 -3
- migrations/20200428194858_ExpandIndexableColumnLengths.php +71 -0
- migrations/20200429105310_TruncateIndexableTables.php +48 -0
- polyfills/pdo/pdo-mysqli-polyfill.php +0 -297
- polyfills/pdo/pdo-mysqli-statement-polyfill.php +0 -448
- readme.txt +23 -1
- src/actions/indexation/indexable-post-indexation-action.php +3 -6
- src/actions/indexation/indexable-term-indexation-action.php +3 -6
- src/builders/indexable-builder.php +11 -3
- src/builders/indexable-hierarchy-builder.php +3 -3
- src/config/ruckusing-framework.php +4 -41
- src/generated/container.php +6 -33
- src/generators/breadcrumbs-generator.php +3 -3
- src/helpers/author-archive-helper.php +3 -3
- src/helpers/post-helper.php +4 -4
- src/helpers/robots-helper.php +13 -6
- src/initializers/database-setup.php +0 -115
- src/initializers/migration-runner.php +4 -42
- src/integrations/third-party/woocommerce.php +41 -7
- src/integrations/watchers/indexable-permalink-watcher.php +2 -2
- src/integrations/watchers/indexable-post-watcher.php +0 -4
- src/integrations/watchers/option-titles-watcher.php +5 -5
- src/loggers/database-logger.php +0 -173
- src/models/indexable-extension.php +2 -2
- src/models/indexable-hierarchy.php +2 -2
- src/models/indexable.php +9 -3
- src/models/primary-term.php +2 -2
- src/models/seo-links.php +2 -2
- src/models/seo-meta.php +2 -2
- src/orm/yoast-orm-wrapper.php +0 -234
- src/presenters/admin/indexation-warning-presenter.php +2 -1
- src/repositories/indexable-hierarchy-repository.php +3 -3
- src/repositories/indexable-repository.php +4 -11
- src/repositories/primary-term-repository.php +2 -2
- src/repositories/seo-links-repository.php +2 -2
- src/repositories/seo-meta-repository.php +2 -2
- vendor/composer/autoload_classmap.php +6 -6
- vendor/composer/autoload_static.php +6 -6
- wp-seo-main.php +1 -6
- wp-seo.php +1 -1
config/php-scoper/idiorm.inc.php
DELETED
@@ -1,37 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
declare(strict_types = 1);
|
4 |
-
|
5 |
-
use Isolated\Symfony\Component\Finder\Finder;
|
6 |
-
|
7 |
-
return array(
|
8 |
-
|
9 |
-
/*
|
10 |
-
* By default when running php-scoper add-prefix, it will prefix all relevant code found in the current working
|
11 |
-
* directory. You can however define which files should be scoped by defining a collection of Finders in the
|
12 |
-
* following configuration key.
|
13 |
-
*
|
14 |
-
* For more see: https://github.com/humbug/php-scoper#finders-and-paths
|
15 |
-
*/
|
16 |
-
'finders' => array(
|
17 |
-
Finder::create()->files()->in( 'vendor/j4mie/idiorm' )->name( [ 'idiorm.php', 'LICENSE', 'composer.json' ] ),
|
18 |
-
),
|
19 |
-
|
20 |
-
/*
|
21 |
-
* When scoping PHP files, there will be scenarios where some of the code being scoped indirectly references the
|
22 |
-
* original namespace. These will include, for example, strings or string manipulations. PHP-Scoper has limited
|
23 |
-
* support for prefixing such strings. To circumvent that, you can define patchers to manipulate the file to your
|
24 |
-
* heart contents.
|
25 |
-
*
|
26 |
-
* For more see: https://github.com/humbug/php-scoper#patchers
|
27 |
-
*/
|
28 |
-
'patchers' => array(),
|
29 |
-
|
30 |
-
/*
|
31 |
-
* By default, PHP-Scoper will not prefix the user defined constants, classes and functions belonging to the global
|
32 |
-
* namespace. You can however change that setting for them to be prefixed as usual unless explicitly whitelisted.
|
33 |
-
*
|
34 |
-
* https://github.com/humbug/php-scoper#whitelist
|
35 |
-
*/
|
36 |
-
'whitelist-global-classes' => false,
|
37 |
-
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
css/dist/{admin-global-1401-rtl.css → admin-global-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{admin-global-1401.css → admin-global-1402.css}
RENAMED
File without changes
|
css/dist/{adminbar-1401-rtl.css → adminbar-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{adminbar-1401.css → adminbar-1402.css}
RENAMED
File without changes
|
css/dist/{alerts-1401-rtl.css → alerts-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{alerts-1401.css → alerts-1402.css}
RENAMED
File without changes
|
css/dist/{dashboard-1401-rtl.css → dashboard-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{dashboard-1401.css → dashboard-1402.css}
RENAMED
File without changes
|
css/dist/{edit-page-1401-rtl.css → edit-page-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{edit-page-1401.css → edit-page-1402.css}
RENAMED
File without changes
|
css/dist/{featured-image-1401-rtl.css → featured-image-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{featured-image-1401.css → featured-image-1402.css}
RENAMED
File without changes
|
css/dist/{filter-explanation-1401-rtl.css → filter-explanation-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{filter-explanation-1401.css → filter-explanation-1402.css}
RENAMED
File without changes
|
css/dist/{inside-editor-1401-rtl.css → inside-editor-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{inside-editor-1401.css → inside-editor-1402.css}
RENAMED
File without changes
|
css/dist/{metabox-1401-rtl.css → metabox-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{metabox-1401.css → metabox-1402.css}
RENAMED
File without changes
|
css/dist/{metabox-primary-category-1401-rtl.css → metabox-primary-category-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{metabox-primary-category-1401.css → metabox-primary-category-1402.css}
RENAMED
File without changes
|
css/dist/{monorepo-1401-rtl.css → monorepo-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{monorepo-1401.css → monorepo-1402.css}
RENAMED
File without changes
|
css/dist/{search-appearance-1401-rtl.css → search-appearance-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{search-appearance-1401.css → search-appearance-1402.css}
RENAMED
File without changes
|
css/dist/{structured-data-blocks-1401-rtl.css → structured-data-blocks-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{structured-data-blocks-1401.css → structured-data-blocks-1402.css}
RENAMED
File without changes
|
css/dist/{toggle-switch-1401-rtl.css → toggle-switch-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{toggle-switch-1401.css → toggle-switch-1402.css}
RENAMED
File without changes
|
css/dist/{wpseo-dismissible-1401-rtl.css → wpseo-dismissible-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{wpseo-dismissible-1401.css → wpseo-dismissible-1402.css}
RENAMED
File without changes
|
css/dist/{yoast-components-1401-rtl.css → yoast-components-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{yoast-components-1401.css → yoast-components-1402.css}
RENAMED
File without changes
|
css/dist/{yoast-extensions-1401-rtl.css → yoast-extensions-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{yoast-extensions-1401.css → yoast-extensions-1402.css}
RENAMED
File without changes
|
css/dist/{yst_plugin_tools-1401-rtl.css → yst_plugin_tools-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{yst_plugin_tools-1401.css → yst_plugin_tools-1402.css}
RENAMED
File without changes
|
css/dist/{yst_seo_score-1401-rtl.css → yst_seo_score-1402-rtl.css}
RENAMED
File without changes
|
css/dist/{yst_seo_score-1401.css → yst_seo_score-1402.css}
RENAMED
File without changes
|
{src/backwards-compatibility → deprecated/frontend}/breadcrumbs.php
RENAMED
@@ -5,8 +5,6 @@
|
|
5 |
* @package Yoast\YoastSEO\Backwards_Compatibility
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
9 |
-
use Yoast\WP\SEO\Initializers\Initializer_Interface;
|
10 |
use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
|
11 |
use Yoast\WP\SEO\Presenters\Breadcrumbs_Presenter;
|
12 |
use Yoast\WP\SEO\Surfaces\Helpers_Surface;
|
@@ -16,9 +14,7 @@ use Yoast\WP\SEO\Surfaces\Helpers_Surface;
|
|
16 |
*
|
17 |
* @codeCoverageIgnore Because of deprecation.
|
18 |
*/
|
19 |
-
class WPSEO_Breadcrumbs
|
20 |
-
|
21 |
-
use No_Conditionals;
|
22 |
|
23 |
/**
|
24 |
* Instance of this class.
|
@@ -64,26 +60,11 @@ class WPSEO_Breadcrumbs implements Initializer_Interface {
|
|
64 |
|
65 |
/**
|
66 |
* WPSEO_Breadcrumbs constructor.
|
67 |
-
*
|
68 |
-
* @param Meta_Tags_Context_Memoizer $context_memoizer The context memoizer.
|
69 |
-
* @param Helpers_Surface $helpers The helpers surface.
|
70 |
-
* @param WPSEO_Replace_Vars $replace_vars The replace vars helper.
|
71 |
-
*/
|
72 |
-
public function __construct(
|
73 |
-
Meta_Tags_Context_Memoizer $context_memoizer,
|
74 |
-
Helpers_Surface $helpers,
|
75 |
-
WPSEO_Replace_Vars $replace_vars
|
76 |
-
) {
|
77 |
-
$this->context_memoizer = $context_memoizer;
|
78 |
-
$this->helpers = $helpers;
|
79 |
-
$this->replace_vars = $replace_vars;
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* We use an initializer so the static functions will work right as our plugin is loaded just as they normally would.
|
84 |
*/
|
85 |
-
public function
|
86 |
-
|
|
|
|
|
87 |
}
|
88 |
|
89 |
/**
|
@@ -99,7 +80,7 @@ class WPSEO_Breadcrumbs implements Initializer_Interface {
|
|
99 |
// Remember the last used before/after for use in case the object goes __toString().
|
100 |
self::$before = $before;
|
101 |
self::$after = $after;
|
102 |
-
$output = $before . self
|
103 |
|
104 |
if ( $display === true ) {
|
105 |
echo $output;
|
@@ -122,9 +103,13 @@ class WPSEO_Breadcrumbs implements Initializer_Interface {
|
|
122 |
/**
|
123 |
* Retrieves an instance of the class.
|
124 |
*
|
125 |
-
* @return
|
126 |
*/
|
127 |
public static function get_instance() {
|
|
|
|
|
|
|
|
|
128 |
return self::$instance;
|
129 |
}
|
130 |
|
5 |
* @package Yoast\YoastSEO\Backwards_Compatibility
|
6 |
*/
|
7 |
|
|
|
|
|
8 |
use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
|
9 |
use Yoast\WP\SEO\Presenters\Breadcrumbs_Presenter;
|
10 |
use Yoast\WP\SEO\Surfaces\Helpers_Surface;
|
14 |
*
|
15 |
* @codeCoverageIgnore Because of deprecation.
|
16 |
*/
|
17 |
+
class WPSEO_Breadcrumbs {
|
|
|
|
|
18 |
|
19 |
/**
|
20 |
* Instance of this class.
|
60 |
|
61 |
/**
|
62 |
* WPSEO_Breadcrumbs constructor.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
*/
|
64 |
+
public function __construct() {
|
65 |
+
$this->context_memoizer = YoastSEO()->classes->get( Meta_Tags_Context_Memoizer::class );
|
66 |
+
$this->helpers = YoastSEO()->classes->get( Helpers_Surface::class );
|
67 |
+
$this->replace_vars = YoastSEO()->classes->get( WPSEO_Replace_Vars::class );
|
68 |
}
|
69 |
|
70 |
/**
|
80 |
// Remember the last used before/after for use in case the object goes __toString().
|
81 |
self::$before = $before;
|
82 |
self::$after = $after;
|
83 |
+
$output = $before . self::get_instance()->render() . $after;
|
84 |
|
85 |
if ( $display === true ) {
|
86 |
echo $output;
|
103 |
/**
|
104 |
* Retrieves an instance of the class.
|
105 |
*
|
106 |
+
* @return static The instance.
|
107 |
*/
|
108 |
public static function get_instance() {
|
109 |
+
if ( is_null( self::$instance ) ) {
|
110 |
+
self::$instance = new self();
|
111 |
+
}
|
112 |
+
|
113 |
return self::$instance;
|
114 |
}
|
115 |
|
{src/backwards-compatibility → deprecated/frontend}/frontend.php
RENAMED
@@ -5,20 +5,20 @@
|
|
5 |
* @package Yoast\YoastSEO\Backwards_Compatibility
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\SEO\Initializers\Initializer_Interface;
|
9 |
use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
|
10 |
use Yoast\WP\SEO\Presenters\Canonical_Presenter;
|
11 |
use Yoast\WP\SEO\Presenters\Meta_Description_Presenter;
|
12 |
use Yoast\WP\SEO\Presenters\Rel_Next_Presenter;
|
13 |
use Yoast\WP\SEO\Presenters\Rel_Prev_Presenter;
|
14 |
use Yoast\WP\SEO\Presenters\Robots_Presenter;
|
|
|
15 |
|
16 |
/**
|
17 |
* Class WPSEO_Frontend
|
18 |
*
|
19 |
* @codeCoverageIgnore Because of deprecation.
|
20 |
*/
|
21 |
-
class WPSEO_Frontend
|
22 |
/**
|
23 |
* Instance of this class.
|
24 |
*
|
@@ -41,31 +41,19 @@ class WPSEO_Frontend implements Initializer_Interface {
|
|
41 |
private $replace_vars;
|
42 |
|
43 |
/**
|
44 |
-
*
|
|
|
|
|
45 |
*/
|
46 |
-
|
47 |
-
self::$instance = $this;
|
48 |
-
}
|
49 |
|
50 |
/**
|
51 |
-
*
|
52 |
*/
|
53 |
-
public
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
/**
|
58 |
-
* WPSEO_Breadcrumbs constructor.
|
59 |
-
*
|
60 |
-
* @param Meta_Tags_Context_Memoizer $context_memoizer The context memoizer.
|
61 |
-
* @param \WPSEO_Replace_Vars $replace_vars The replace vars helper.
|
62 |
-
*/
|
63 |
-
public function __construct(
|
64 |
-
Meta_Tags_Context_Memoizer $context_memoizer,
|
65 |
-
WPSEO_Replace_Vars $replace_vars
|
66 |
-
) {
|
67 |
-
$this->context_memoizer = $context_memoizer;
|
68 |
-
$this->replace_vars = $replace_vars;
|
69 |
}
|
70 |
|
71 |
/**
|
@@ -101,6 +89,10 @@ class WPSEO_Frontend implements Initializer_Interface {
|
|
101 |
* @return static The instance.
|
102 |
*/
|
103 |
public static function get_instance() {
|
|
|
|
|
|
|
|
|
104 |
return self::$instance;
|
105 |
}
|
106 |
|
@@ -121,9 +113,11 @@ class WPSEO_Frontend implements Initializer_Interface {
|
|
121 |
return $context->presentation->canonical;
|
122 |
}
|
123 |
|
124 |
-
$
|
125 |
-
$
|
126 |
-
|
|
|
|
|
127 |
}
|
128 |
|
129 |
/**
|
@@ -148,6 +142,8 @@ class WPSEO_Frontend implements Initializer_Interface {
|
|
148 |
$context = $this->context_memoizer->for_current_page();
|
149 |
$presenter = new Robots_Presenter();
|
150 |
$presenter->presentation = $context->presentation;
|
|
|
|
|
151 |
echo $presenter->present();
|
152 |
}
|
153 |
|
@@ -230,10 +226,14 @@ class WPSEO_Frontend implements Initializer_Interface {
|
|
230 |
|
231 |
$rel_prev_presenter = new Rel_Prev_Presenter();
|
232 |
$rel_prev_presenter->presentation = $context->presentation;
|
|
|
|
|
233 |
echo $rel_prev_presenter->present();
|
234 |
|
235 |
$rel_next_presenter = new Rel_Next_Presenter();
|
236 |
$rel_next_presenter->presentation = $context->presentation;
|
|
|
|
|
237 |
echo $rel_next_presenter->present();
|
238 |
}
|
239 |
|
@@ -255,6 +255,8 @@ class WPSEO_Frontend implements Initializer_Interface {
|
|
255 |
|
256 |
$presenter = new Meta_Description_Presenter();
|
257 |
$presenter->presentation = $context->presentation;
|
|
|
|
|
258 |
$presenter->present();
|
259 |
}
|
260 |
}
|
5 |
* @package Yoast\YoastSEO\Backwards_Compatibility
|
6 |
*/
|
7 |
|
|
|
8 |
use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
|
9 |
use Yoast\WP\SEO\Presenters\Canonical_Presenter;
|
10 |
use Yoast\WP\SEO\Presenters\Meta_Description_Presenter;
|
11 |
use Yoast\WP\SEO\Presenters\Rel_Next_Presenter;
|
12 |
use Yoast\WP\SEO\Presenters\Rel_Prev_Presenter;
|
13 |
use Yoast\WP\SEO\Presenters\Robots_Presenter;
|
14 |
+
use Yoast\WP\SEO\Surfaces\Helpers_Surface;
|
15 |
|
16 |
/**
|
17 |
* Class WPSEO_Frontend
|
18 |
*
|
19 |
* @codeCoverageIgnore Because of deprecation.
|
20 |
*/
|
21 |
+
class WPSEO_Frontend {
|
22 |
/**
|
23 |
* Instance of this class.
|
24 |
*
|
41 |
private $replace_vars;
|
42 |
|
43 |
/**
|
44 |
+
* The helpers surface.
|
45 |
+
*
|
46 |
+
* @var Helpers_Surface
|
47 |
*/
|
48 |
+
private $helpers;
|
|
|
|
|
49 |
|
50 |
/**
|
51 |
+
* WPSEO_Frontend constructor.
|
52 |
*/
|
53 |
+
public function __construct() {
|
54 |
+
$this->context_memoizer = YoastSEO()->classes->get( Meta_Tags_Context_Memoizer::class );
|
55 |
+
$this->replace_vars = YoastSEO()->classes->get( WPSEO_Replace_Vars::class );
|
56 |
+
$this->helpers = YoastSEO()->classes->get( Helpers_Surface::class );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
}
|
58 |
|
59 |
/**
|
89 |
* @return static The instance.
|
90 |
*/
|
91 |
public static function get_instance() {
|
92 |
+
if ( is_null( self::$instance ) ) {
|
93 |
+
self::$instance = new self();
|
94 |
+
}
|
95 |
+
|
96 |
return self::$instance;
|
97 |
}
|
98 |
|
113 |
return $context->presentation->canonical;
|
114 |
}
|
115 |
|
116 |
+
$presenter = new Canonical_Presenter();
|
117 |
+
$presenter->presentation = $context->presentation;
|
118 |
+
$presenter->helpers = $this->helpers;
|
119 |
+
$presenter->replace_vars = $this->replace_vars;
|
120 |
+
echo $presenter->present();
|
121 |
}
|
122 |
|
123 |
/**
|
142 |
$context = $this->context_memoizer->for_current_page();
|
143 |
$presenter = new Robots_Presenter();
|
144 |
$presenter->presentation = $context->presentation;
|
145 |
+
$presenter->helpers = $this->helpers;
|
146 |
+
$presenter->replace_vars = $this->replace_vars;
|
147 |
echo $presenter->present();
|
148 |
}
|
149 |
|
226 |
|
227 |
$rel_prev_presenter = new Rel_Prev_Presenter();
|
228 |
$rel_prev_presenter->presentation = $context->presentation;
|
229 |
+
$rel_prev_presenter->helpers = $this->helpers;
|
230 |
+
$rel_prev_presenter->replace_vars = $this->replace_vars;
|
231 |
echo $rel_prev_presenter->present();
|
232 |
|
233 |
$rel_next_presenter = new Rel_Next_Presenter();
|
234 |
$rel_next_presenter->presentation = $context->presentation;
|
235 |
+
$rel_next_presenter->helpers = $this->helpers;
|
236 |
+
$rel_next_presenter->replace_vars = $this->replace_vars;
|
237 |
echo $rel_next_presenter->present();
|
238 |
}
|
239 |
|
255 |
|
256 |
$presenter = new Meta_Description_Presenter();
|
257 |
$presenter->presentation = $context->presentation;
|
258 |
+
$presenter->helpers = $this->helpers;
|
259 |
+
$presenter->replace_vars = $this->replace_vars;
|
260 |
$presenter->present();
|
261 |
}
|
262 |
}
|
js/dist/{analysis-1401.js → analysis-1402.js}
RENAMED
File without changes
|
js/dist/{babel-polyfill-1401.js → babel-polyfill-1402.js}
RENAMED
File without changes
|
js/dist/{commons-1401.js → commons-1402.js}
RENAMED
File without changes
|
js/dist/{components-1401.js → components-1402.js}
RENAMED
File without changes
|
js/dist/{configuration-wizard-1401.js → configuration-wizard-1402.js}
RENAMED
File without changes
|
js/dist/{help-scout-beacon-1401.js → help-scout-beacon-1402.js}
RENAMED
File without changes
|
js/dist/{jed-1401.js → jed-1402.js}
RENAMED
File without changes
|
js/dist/{redux-1401.js → redux-1402.js}
RENAMED
File without changes
|
js/dist/{search-appearance-1401.js → search-appearance-1402.js}
RENAMED
File without changes
|
js/dist/{styled-components-1401.js → styled-components-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-admin-1401.js → wp-seo-admin-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-admin-global-1401.js → wp-seo-admin-global-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-admin-gsc-1401.js → wp-seo-admin-gsc-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-admin-media-1401.js → wp-seo-admin-media-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-analysis-worker-1401.js → wp-seo-analysis-worker-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-api-1401.js → wp-seo-api-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-bulk-editor-1401.js → wp-seo-bulk-editor-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-dashboard-widget-1401.js → wp-seo-dashboard-widget-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-edit-page-1401.js → wp-seo-edit-page-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-featured-image-1401.js → wp-seo-featured-image-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-filter-explanation-1401.js → wp-seo-filter-explanation-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-indexation-1401.js → wp-seo-indexation-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-metabox-1401.js → wp-seo-metabox-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-metabox-category-1401.js → wp-seo-metabox-category-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-modal-1401.js → wp-seo-modal-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-network-admin-1401.js → wp-seo-network-admin-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-post-scraper-1401.js → wp-seo-post-scraper-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-quick-edit-handler-1401.js → wp-seo-quick-edit-handler-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-recalculate-1401.js → wp-seo-recalculate-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-reindex-links-1401.js → wp-seo-reindex-links-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-replacevar-plugin-1401.js → wp-seo-replacevar-plugin-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-shortcode-plugin-1401.js → wp-seo-shortcode-plugin-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-structured-data-blocks-1401.js → wp-seo-structured-data-blocks-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-term-scraper-1401.js → wp-seo-term-scraper-1402.js}
RENAMED
File without changes
|
js/dist/{wp-seo-used-keywords-assessment-1401.js → wp-seo-used-keywords-assessment-1402.js}
RENAMED
File without changes
|
languages/wordpress-seojs-de_DE.json
CHANGED
@@ -1 +1 @@
|
|
1 |
-
{"domain":"wordpress-seo","locale_data":{"wordpress-seo":{"":{"domain":"wordpress-seo","plural-forms":"nplurals=2; plural=n != 1;","lang":"de"},"Google preview":["Google-Vorschau"],"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.":[],"Schema":["Schema"],"Truly optimize your site for a local audience with our %s plugin! Optimized address details, opening hours, store locator and pickup option!":["Optimiere deine Website für ein lokales Publikum mit unserem %s-Plugin! Optimierte Adressdaten, Öffnungszeiten, Filialfinder und Abhol-Option!"],"Serving local customers?":["Betreuung lokaler Kunden?"],"Get the %s plugin now":["Hol dir jetzt das %s-Plugin"],"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.":["Du kannst die Angaben zu sozialen Profilen, den Namen und die Beschreibung dieses Benutzers, die in den Metadaten sichtbar sind, auf dessen %1$s Profilseite bearbeiten."],"Select a user...":["Wähle einen Benutzer…"],"Name:":["Name:"],"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":["Du hast den Benutzer %1$s als die Person ausgewählt, den diese Website repräsentiert. Die Daten aus dem Benutzerprofil dieses Benutzers werden jetzt in den Suchergebnissen verwendet. %2$sAktualisiere dieses Benutzerprofil, um sicherzustellen, dass die Angaben korrekt sind.%3$s"],"Error: Please select a user below to make your site's meta data complete.":["Fehler: Bitte unten einen Benutzer auswählen, um die Metadaten deiner Website zu komplettieren."],"New step added":["Neuer Schritt hinzugefügt"],"New question added":["Neue Frage hinzugefügt"],"Did you know %s also analyzes the different word forms of your keyphrase, like plurals and past tenses?":["Wusstest du schon, dass %s auch Plural- oder Zeitformen deiner Keyphrase analysiert?"],"Help on choosing the perfect focus keyphrase":["Hilfe bei der Auswahl des perfekten Fokus-Schlüsselworts"],"Would you like to add a related keyphrase?":["Möchtest du eine verwandte Keyphrase hinzufügen?"],"Go %s!":["Start %s!"],"Rank better with synonyms & related keyphrases":["Ranke besser mit Synonymen & verwandten Keyphrasen."],"Add related keyphrase":["Ähnliches Keyword hinzufügen"],"Get %s":["Erhalte %s"],"Focus keyphrase":["Fokus-Keyphrase"],"Learn more about the readability analysis":["Lerne mehr über die Lesbarkeitsanalyse"],"Describe the duration of the instruction:":["Beschreibe die Dauer der Anleitung:"],"Optional. Customize how you want to describe the duration of the instruction":["Optional. Passe an, wie du die Dauer der Anleitung beschreiben möchtest. "],"%s, %s and %s":["%s, %s und %s"],"%s and %s":["%s und %s"],"%d minute":["%d Minute","%d Minuten"],"%d hour":["%d Stunde","%d Stunden"],"%d day":["%d Tag","%d Tage"],"Enter a step title":["Schritt-Titel eingeben"],"Optional. This can give you better control over the styling of the steps.":["Optional. Dies kann dir eine bessere Kontrolle über das Styling der Schritte geben."],"CSS class(es) to apply to the steps":["CSS-Klasse(n), die auf die Schritte angewendet werden sollen"],"minutes":["Minuten"],"hours":["Stunden"],"days":["Tage"],"Create a How-to guide in an SEO-friendly way. You can only use one How-to block per post.":["Erstelle eine Anleitung auf SEO-freundliche Weise. Du kannst nur einen How-to-Absatz pro Beitrag verwenden."],"List your Frequently Asked Questions in an SEO-friendly way. You can only use one FAQ block per post.":["Liste deine häufig gestellten Fragen SEO-freundlich auf. Du kannst nur einen FAQ-Absatz pro Bericht verwenden."],"Copy error":["Fehler kopieren"],"An error occurred loading the %s primary taxonomy picker.":["Beim Laden des primären Taxonomie-Pickers %s ist ein Fehler aufgetreten."],"Time needed:":["Benötigte Zeit:"],"Move question down":["Frage nach unten verschieben"],"Move question up":["Frage nach oben verschieben"],"Insert question":["Frage hinzufügen"],"Delete question":["Frage löschen"],"Enter the answer to the question":["Antwort auf die Frage eingeben"],"Enter a question":["Gib eine Frage ein"],"Add question":["Frage hinzufügen"],"Frequently Asked Questions":["Häufig gestellte Fragen (FAQ)"],"Great news: you can, with %s!":["Tolle Neuigkeiten: Du kannst es, mit %s!"],"Select the primary %s":["Wähle die primären %s"],"Mark as cornerstone content":["Als Cornerstone-Inhalt markieren"],"Move step down":["Schritt nach unten verschieben"],"Move step up":["Schritt nach oben verschieben"],"Insert step":["Schritt einfügen"],"Delete step":["Schritt löschen"],"Add image":["Bild hinzufügen"],"Enter a step description":["Gib eine Beschreibung für den Schritt ein"],"Enter a description":["Gib eine Beschreibung ein"],"Unordered list":["Unsortierte Liste"],"Showing step items as an ordered list.":["Schritt-Elemente als geordnete Liste anzeigen."],"Showing step items as an unordered list":["Schritt-Elemente als ungeordnete Liste anzeigen"],"Add step":["Schritt hinzufügen"],"Delete total time":["Gesamtzeit löschen"],"Add total time":["Gesamtzeit hinzufügen"],"How to":["Anleitung"],"How-to":["Anleitung"],"Analysis results":["Analyse-Ergebnisse"],"Enter a focus keyphrase to calculate the SEO score":["Gib ein Fokus-Keyword ein, um den SEO-Wert zu berechnen"],"Learn more about Cornerstone Content.":["Erfahre mehr über Cornerstone-Inhalte."],"Cornerstone content should be the most important and extensive articles on your site.":["Cornerstone-Inhalte sollten die wichtigsten und umfassendsten Artikel deiner Seite sein."],"Add synonyms":["Synonyme hinzufügen"],"Would you like to add keyphrase synonyms?":["Möchtest du Keyphrase-Synonyme hinzufügen?"],"Current year":["Aktuelles Jahr"],"Page":["Seite"],"Tagline":["Untertitel"],"Modify your meta description by editing it right here":["Bearbeite direkt hier deine Meta-Beschreibung "],"ID":["ID"],"Separator":["Trennzeichen"],"Search phrase":["Suchwort"],"Term description":["Begriffsbeschreibung"],"Tag description":["Schlagwortbeschreibung"],"Category description":["Kategoriebeschreibung"],"Primary category":["Primäre Kategorie"],"Category":["Kategorie"],"Excerpt only":["Nur Auszug"],"Excerpt":["Textauszug"],"Site title":["Titel der Website"],"Parent title":["Titel der übergeordneten Seite"],"Date":["Datum"],"24/7 email support":["24/7 E-Mail-Support"],"SEO analysis":["SEO Analyse"],"Other benefits of %s for you:":["Andere Vorteile von %s für dich:"],"Cornerstone content":["Cornerstone-Inhalt"],"Superfast internal linking suggestions":["Superschnelle Vorschläge zur internen Verlinkung"],"Great news: you can, with %1$s!":["Großartige Neuigkeit: Du kannst es, mit %1$s!"],"1 year free support and updates included!":["1 Jahr kostenfreie Updates und Upgrades inbegriffen!"],"%1$sSocial media preview%2$s: Facebook & Twitter":["%1$sSocial Media Vorschau%2$s: Facebook & Twitter"],"%1$sNo more dead links%2$s: easy redirect manager":["%1$sKeine verwaisten Links mehr%2$s: Einfacher Redirect-Manager"],"No ads!":["Keine Werbung!"],"Please provide a meta description by editing the snippet below.":["Bitte lege eine Meta-Beschreibung fest, indem du den Code-Schnipsel bearbeitest."],"The name of the person":["Der Name der Person"],"Readability analysis":["Lesbarkeits-Analyse"],"Open":["Offen"],"Title":["Titel"],"Close":["Schließen"],"FAQ":["FAQ"],"Settings":["Einstellungen"]}}}
|
1 |
+
{"domain":"wordpress-seo","locale_data":{"wordpress-seo":{"":{"domain":"wordpress-seo","plural-forms":"nplurals=2; plural=n != 1;","lang":"de"},"Google preview":["Google-Vorschau"],"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.":["Wenn du auf OK klickst, öffnen wir unseren HelpScout-Beacon, in dem du Antworten auf deine Fragen finden kannst. Dieses Beacon lädt unsere Supportdaten und setzt möglicherweise Cookies."],"Schema":["Schema"],"Truly optimize your site for a local audience with our %s plugin! Optimized address details, opening hours, store locator and pickup option!":["Optimiere deine Website für ein lokales Publikum mit unserem %s-Plugin! Optimierte Adressdaten, Öffnungszeiten, Filialfinder und Abhol-Option!"],"Serving local customers?":["Betreuung lokaler Kunden?"],"Get the %s plugin now":["Hol dir jetzt das %s-Plugin"],"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.":["Du kannst die Angaben zu sozialen Profilen, den Namen und die Beschreibung dieses Benutzers, die in den Metadaten sichtbar sind, auf dessen %1$s Profilseite bearbeiten."],"Select a user...":["Wähle einen Benutzer…"],"Name:":["Name:"],"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":["Du hast den Benutzer %1$s als die Person ausgewählt, den diese Website repräsentiert. Die Daten aus dem Benutzerprofil dieses Benutzers werden jetzt in den Suchergebnissen verwendet. %2$sAktualisiere dieses Benutzerprofil, um sicherzustellen, dass die Angaben korrekt sind.%3$s"],"Error: Please select a user below to make your site's meta data complete.":["Fehler: Bitte unten einen Benutzer auswählen, um die Metadaten deiner Website zu komplettieren."],"New step added":["Neuer Schritt hinzugefügt"],"New question added":["Neue Frage hinzugefügt"],"Did you know %s also analyzes the different word forms of your keyphrase, like plurals and past tenses?":["Wusstest du schon, dass %s auch Plural- oder Zeitformen deiner Keyphrase analysiert?"],"Help on choosing the perfect focus keyphrase":["Hilfe bei der Auswahl des perfekten Fokus-Schlüsselworts"],"Would you like to add a related keyphrase?":["Möchtest du eine verwandte Keyphrase hinzufügen?"],"Go %s!":["Start %s!"],"Rank better with synonyms & related keyphrases":["Ranke besser mit Synonymen & verwandten Keyphrasen."],"Add related keyphrase":["Ähnliches Keyword hinzufügen"],"Get %s":["Erhalte %s"],"Focus keyphrase":["Fokus-Keyphrase"],"Learn more about the readability analysis":["Lerne mehr über die Lesbarkeitsanalyse"],"Describe the duration of the instruction:":["Beschreibe die Dauer der Anleitung:"],"Optional. Customize how you want to describe the duration of the instruction":["Optional. Passe an, wie du die Dauer der Anleitung beschreiben möchtest. "],"%s, %s and %s":["%s, %s und %s"],"%s and %s":["%s und %s"],"%d minute":["%d Minute","%d Minuten"],"%d hour":["%d Stunde","%d Stunden"],"%d day":["%d Tag","%d Tage"],"Enter a step title":["Schritt-Titel eingeben"],"Optional. This can give you better control over the styling of the steps.":["Optional. Dies kann dir eine bessere Kontrolle über das Styling der Schritte geben."],"CSS class(es) to apply to the steps":["CSS-Klasse(n), die auf die Schritte angewendet werden sollen"],"minutes":["Minuten"],"hours":["Stunden"],"days":["Tage"],"Create a How-to guide in an SEO-friendly way. You can only use one How-to block per post.":["Erstelle eine Anleitung auf SEO-freundliche Weise. Du kannst nur einen How-to-Absatz pro Beitrag verwenden."],"List your Frequently Asked Questions in an SEO-friendly way. You can only use one FAQ block per post.":["Liste deine häufig gestellten Fragen SEO-freundlich auf. Du kannst nur einen FAQ-Absatz pro Bericht verwenden."],"Copy error":["Fehler kopieren"],"An error occurred loading the %s primary taxonomy picker.":["Beim Laden des primären Taxonomie-Pickers %s ist ein Fehler aufgetreten."],"Time needed:":["Benötigte Zeit:"],"Move question down":["Frage nach unten verschieben"],"Move question up":["Frage nach oben verschieben"],"Insert question":["Frage hinzufügen"],"Delete question":["Frage löschen"],"Enter the answer to the question":["Antwort auf die Frage eingeben"],"Enter a question":["Gib eine Frage ein"],"Add question":["Frage hinzufügen"],"Frequently Asked Questions":["Häufig gestellte Fragen (FAQ)"],"Great news: you can, with %s!":["Tolle Neuigkeiten: Du kannst es, mit %s!"],"Select the primary %s":["Wähle die primären %s"],"Mark as cornerstone content":["Als Cornerstone-Inhalt markieren"],"Move step down":["Schritt nach unten verschieben"],"Move step up":["Schritt nach oben verschieben"],"Insert step":["Schritt einfügen"],"Delete step":["Schritt löschen"],"Add image":["Bild hinzufügen"],"Enter a step description":["Gib eine Beschreibung für den Schritt ein"],"Enter a description":["Gib eine Beschreibung ein"],"Unordered list":["Unsortierte Liste"],"Showing step items as an ordered list.":["Schritt-Elemente als geordnete Liste anzeigen."],"Showing step items as an unordered list":["Schritt-Elemente als ungeordnete Liste anzeigen"],"Add step":["Schritt hinzufügen"],"Delete total time":["Gesamtzeit löschen"],"Add total time":["Gesamtzeit hinzufügen"],"How to":["Anleitung"],"How-to":["Anleitung"],"Analysis results":["Analyse-Ergebnisse"],"Enter a focus keyphrase to calculate the SEO score":["Gib ein Fokus-Keyword ein, um den SEO-Wert zu berechnen"],"Learn more about Cornerstone Content.":["Erfahre mehr über Cornerstone-Inhalte."],"Cornerstone content should be the most important and extensive articles on your site.":["Cornerstone-Inhalte sollten die wichtigsten und umfassendsten Artikel deiner Seite sein."],"Add synonyms":["Synonyme hinzufügen"],"Would you like to add keyphrase synonyms?":["Möchtest du Keyphrase-Synonyme hinzufügen?"],"Current year":["Aktuelles Jahr"],"Page":["Seite"],"Tagline":["Untertitel"],"Modify your meta description by editing it right here":["Bearbeite direkt hier deine Meta-Beschreibung "],"ID":["ID"],"Separator":["Trennzeichen"],"Search phrase":["Suchwort"],"Term description":["Begriffsbeschreibung"],"Tag description":["Schlagwortbeschreibung"],"Category description":["Kategoriebeschreibung"],"Primary category":["Primäre Kategorie"],"Category":["Kategorie"],"Excerpt only":["Nur Auszug"],"Excerpt":["Textauszug"],"Site title":["Titel der Website"],"Parent title":["Titel der übergeordneten Seite"],"Date":["Datum"],"24/7 email support":["24/7 E-Mail-Support"],"SEO analysis":["SEO Analyse"],"Other benefits of %s for you:":["Andere Vorteile von %s für dich:"],"Cornerstone content":["Cornerstone-Inhalt"],"Superfast internal linking suggestions":["Superschnelle Vorschläge zur internen Verlinkung"],"Great news: you can, with %1$s!":["Großartige Neuigkeit: Du kannst es, mit %1$s!"],"1 year free support and updates included!":["1 Jahr kostenfreie Updates und Upgrades inbegriffen!"],"%1$sSocial media preview%2$s: Facebook & Twitter":["%1$sSocial Media Vorschau%2$s: Facebook & Twitter"],"%1$sNo more dead links%2$s: easy redirect manager":["%1$sKeine verwaisten Links mehr%2$s: Einfacher Redirect-Manager"],"No ads!":["Keine Werbung!"],"Please provide a meta description by editing the snippet below.":["Bitte lege eine Meta-Beschreibung fest, indem du den Code-Schnipsel bearbeitest."],"The name of the person":["Der Name der Person"],"Readability analysis":["Lesbarkeits-Analyse"],"Open":["Offen"],"Title":["Titel"],"Close":["Schließen"],"FAQ":["FAQ"],"Settings":["Einstellungen"]}}}
|
languages/yoast-components-de_DE.json
CHANGED
@@ -1 +1 @@
|
|
1 |
-
{"domain":"yoast-components","locale_data":{"yoast-components":{"":{"domain":"yoast-components","plural-forms":"nplurals=2; plural=n != 1;","lang":"de"},"Preview as:":["Vorschau als:"],"Mobile result":[],"Desktop result":[],"Dismiss this alert":["Hinweis ausblenden"],"The following words and word combinations occur the most in the content. These give an indication of what your content focuses on. If the words differ a lot from your topic, you might want to rewrite your content accordingly. ":["Die folgenden Wörter und Wort-Kombinationen kommen im Inhalt am häufigsten vor. Diese geben einen Hinweis darauf, worauf sich dein Inhalt konzentriert. Wenn sich die Wörter stark von deinem Thema unterscheiden, möchtest du vielleicht deinen Inhalt entsprechend umschreiben. "],"Once you add a bit more copy, we'll give you a list of words that occur the most in the content. These give an indication of what your content focuses on.":["Hast du deiner Seite einmal etwas mehr Inhalt hinzugefügt, werden wir dir eine Liste mit Wörtern anzeigen, die am meisten im Inhalt vorkommen. Dies kann eine gute Hilfestellung sein, um herauszufinden, worauf sich dein Inhalt konzentriert."],"%d occurrences":["%d Vorkommen"],"We could not find any relevant articles on your website that you could link to from your post.":["Wir konnten keine relevanten Beiträge auf deiner Website finden, auf die du von deinem Beitrag aus verlinken könntet."],"The image you selected is too small for Facebook":["Das ausgewählte Bild ist zu klein für Facebook."],"The given image url cannot be loaded":["Die angegebene URL zum Bild konnte nicht geladen werden."],"This is a list of related content to which you could link in your post. {{a}}Read our article about site structure{{/a}} to learn more about how internal linking can help improve your SEO.":["Dies ist eine Liste von verwandtem Inhalt auf den du in deinem Beitrag verweisen kannst. {{a}}Lies unseren Artikel über Seitenstruktur{{/a}}, um mehr darüber zu lernen, wie interne Verlinkungen deinen SEO Score verbessern können."],"Are you trying to use multiple keyphrases? You should add them separately below.":["Versuchst du, mehrere Keywords zu verwenden? Du solltest sie unten einzeln hinzufügen."],"Mark as cornerstone content":["Als Cornerstone-Inhalt markieren"],"image preview":["Bildvorschau"],"Copied!":["Kopiert!"],"Not supported!":["Nicht unterstützt!"],"Read {{a}}our article about site structure{{/a}} to learn more about how internal linking can help improve your SEO.":["Lies {{a}}unseren Artikel über Seitenstruktur{{/a}}, um mehr darüber zu erfahren, wie interne Verlinkungen deinen SEO Score verbessern können."],"Once you add a bit more copy, we'll give you a list of related content here to which you could link in your post.":["Hast du deiner Seite einmal etwas mehr Inhalt hinzugefügt, werden wir dir eine Liste mit verwandten Inhalten anzeigen, welche du in deinem Beitrag verlinken kannst."],"Consider linking to these {{a}}cornerstone articles:{{/a}}":["Überlege, zu diesen {{a}}Cornerstone-Artikeln{{/a}} zu verlinken. "],"Consider linking to these articles:":["Überlege, auf diese Artikel zu verlinken "],"Copy link":["Link kopieren"],"Copy link to suggested article: %s":["Link zum vorgeschlagenen Artikel kopieren: %s"],"Read our %1$sultimate guide to keyword research%2$s to learn more about keyword research and keyword strategy.":["Lies unser %1$sultimatives Handbuch zur Keyword-Recherche%2$s, um mehr über Keyword-Recherche und Keyword-Strategie zu erfahren."],"Once you add a bit more copy, we'll give you a list of words and word combinations that occur the most in the content. These give an indication of what your content focuses on.":["Hast du deiner Seite einmal etwas mehr Inhalt hinzugefügt, werden wir dir eine Liste mit Wörtern und Wort-Kombinationen anzeigen, die am meisten im Inhalt vorkommen. Dies kann eine gute Hilfestellung sein, um herauszufinden, worauf sich dein Inhalt konzentriert."],"The following words occur the most in the content. These give an indication of what your content focuses on. If the words differ a lot from your topic, you might want to rewrite your content accordingly. ":["Die folgenden Wörter kommen im Inhalt am häufigsten vor. Diese geben einen Hinweis darauf, worauf sich dein Inhalt konzentriert. Wenn sich die Wörter stark von deinem Thema unterscheiden, möchtest du vielleicht deinen Inhalt entsprechend umschreiben. "],"Prominent words":["Prominente Wörter "],"Something went wrong. Please reload the page.":["Das hat nicht funktioniert. Bitte lade die Seite neu."],"Modify your meta description by editing it right here":["Bearbeite direkt hier deine Meta-Beschreibung "],"Url preview":["URL-Vorschau"],"Please provide a meta description by editing the snippet below. If you don’t, Google will try to find a relevant part of your post to show in the search results.":["Bitte bearbeite das Codeschnipsel und richte eine Meta-Beschreibung ein. Wenn du dies nicht tust, wird Google selbständig versuchen, einen relevanten Teil deines Beitrags in den Suchergebnissen anzuzeigen."],"Insert snippet variable":["Codeschnipsel-Variable einsetzen"],"Dismiss this notice":["Ignoriere diese Nachricht"],"No results":["Keine Ergebnisse"],"%d result found, use up and down arrow keys to navigate":["%d Ergebnis gefunden, mit den Pfeiltasten nach oben und unten navigieren","%d Ergebnisse gefunden, mit den Pfeiltasten nach oben und unten navigieren"],"Your site language is set to %s. If this is not correct, contact your site administrator.":["Die Sprache deiner Website ist auf %s eingestellt. Wenn dies nicht korrekt ist, wende dich an deinen Website-Administrator."],"On":["An"],"Off":["Aus"],"Good results":["Gute Ergebnisse"],"Remove highlight from the text":["Text-Markierung entfernen"],"Your site language is set to %s. ":["Die Sprache deiner Website ist auf %s eingestellt."],"Highlight this result in the text":["Markiere dieses Ergebnis im Text"],"Considerations":["Überlegungen"],"Errors":["Fehler"],"Change language":["Sprache ändern"],"(Opens in a new browser tab)":["(Öffnet in einem neuen Browser Tab)"],"Scroll to see the preview content.":["Scrolle, um die Vorschau zu sehen."],"Step %1$d: %2$s":["Schritt %1$d: %2$s"],"Close snippet editor":["Ausschnitt-Editor schließen"],"Slug":["Permalink"],"Marks are disabled in current view":["Markierungen sind in der aktuellen Ansicht deaktiviert."],"Choose an image":["Wähle ein Bild"],"Remove the image":["Bild entfernen"],"MailChimp signup failed:":["MailChimp-Registrierung fehlgeschlagen:"],"Sign Up!":["Anmelden"],"Edit snippet":["Code-Schnipsel bearbeiten"],"SEO title preview":["SEO-Titel Vorschau"],"Meta description preview":["Meta Description Vorschau"],"A problem occurred when saving the current step, {{link}}please file a bug report{{/link}} describing what step you are on and which changes you want to make (if any).":["Beim Speichern des aktuellen Schritts ist ein Problem aufgetreten. {{link}}Bitte erfasse einen Fehlerbericht{{/link}}, der beschreibt in welchen Schritt du warst und welche Änderungen du vorgenommen hast (falls Änderungen gemacht wurden)."],"Close the Wizard":["Schließe den Assistenten "],"%s installation wizard":["%s Installationsassistent"],"SEO title":["SEO Titel"],"Improvements":["Verbesserungen"],"Problems":["Probleme"],"Email":["E-Mail"],"Previous":["Zurück"],"Next":["Weiter"],"Close":["Schließen"],"Meta description":["Meta-Beschreibung"]}}}
|
1 |
+
{"domain":"yoast-components","locale_data":{"yoast-components":{"":{"domain":"yoast-components","plural-forms":"nplurals=2; plural=n != 1;","lang":"de"},"Preview as:":["Vorschau als:"],"Mobile result":["Ergebnis für die mobilen Geräte"],"Desktop result":["Ergebnis für den Desktop"],"Dismiss this alert":["Hinweis ausblenden"],"The following words and word combinations occur the most in the content. These give an indication of what your content focuses on. If the words differ a lot from your topic, you might want to rewrite your content accordingly. ":["Die folgenden Wörter und Wort-Kombinationen kommen im Inhalt am häufigsten vor. Diese geben einen Hinweis darauf, worauf sich dein Inhalt konzentriert. Wenn sich die Wörter stark von deinem Thema unterscheiden, möchtest du vielleicht deinen Inhalt entsprechend umschreiben. "],"Once you add a bit more copy, we'll give you a list of words that occur the most in the content. These give an indication of what your content focuses on.":["Hast du deiner Seite einmal etwas mehr Inhalt hinzugefügt, werden wir dir eine Liste mit Wörtern anzeigen, die am meisten im Inhalt vorkommen. Dies kann eine gute Hilfestellung sein, um herauszufinden, worauf sich dein Inhalt konzentriert."],"%d occurrences":["%d Vorkommen"],"We could not find any relevant articles on your website that you could link to from your post.":["Wir konnten keine relevanten Beiträge auf deiner Website finden, auf die du von deinem Beitrag aus verlinken könntet."],"The image you selected is too small for Facebook":["Das ausgewählte Bild ist zu klein für Facebook."],"The given image url cannot be loaded":["Die angegebene URL zum Bild konnte nicht geladen werden."],"This is a list of related content to which you could link in your post. {{a}}Read our article about site structure{{/a}} to learn more about how internal linking can help improve your SEO.":["Dies ist eine Liste von verwandtem Inhalt auf den du in deinem Beitrag verweisen kannst. {{a}}Lies unseren Artikel über Seitenstruktur{{/a}}, um mehr darüber zu lernen, wie interne Verlinkungen deinen SEO Score verbessern können."],"Are you trying to use multiple keyphrases? You should add them separately below.":["Versuchst du, mehrere Keywords zu verwenden? Du solltest sie unten einzeln hinzufügen."],"Mark as cornerstone content":["Als Cornerstone-Inhalt markieren"],"image preview":["Bildvorschau"],"Copied!":["Kopiert!"],"Not supported!":["Nicht unterstützt!"],"Read {{a}}our article about site structure{{/a}} to learn more about how internal linking can help improve your SEO.":["Lies {{a}}unseren Artikel über Seitenstruktur{{/a}}, um mehr darüber zu erfahren, wie interne Verlinkungen deinen SEO Score verbessern können."],"Once you add a bit more copy, we'll give you a list of related content here to which you could link in your post.":["Hast du deiner Seite einmal etwas mehr Inhalt hinzugefügt, werden wir dir eine Liste mit verwandten Inhalten anzeigen, welche du in deinem Beitrag verlinken kannst."],"Consider linking to these {{a}}cornerstone articles:{{/a}}":["Überlege, zu diesen {{a}}Cornerstone-Artikeln{{/a}} zu verlinken. "],"Consider linking to these articles:":["Überlege, auf diese Artikel zu verlinken "],"Copy link":["Link kopieren"],"Copy link to suggested article: %s":["Link zum vorgeschlagenen Artikel kopieren: %s"],"Read our %1$sultimate guide to keyword research%2$s to learn more about keyword research and keyword strategy.":["Lies unser %1$sultimatives Handbuch zur Keyword-Recherche%2$s, um mehr über Keyword-Recherche und Keyword-Strategie zu erfahren."],"Once you add a bit more copy, we'll give you a list of words and word combinations that occur the most in the content. These give an indication of what your content focuses on.":["Hast du deiner Seite einmal etwas mehr Inhalt hinzugefügt, werden wir dir eine Liste mit Wörtern und Wort-Kombinationen anzeigen, die am meisten im Inhalt vorkommen. Dies kann eine gute Hilfestellung sein, um herauszufinden, worauf sich dein Inhalt konzentriert."],"The following words occur the most in the content. These give an indication of what your content focuses on. If the words differ a lot from your topic, you might want to rewrite your content accordingly. ":["Die folgenden Wörter kommen im Inhalt am häufigsten vor. Diese geben einen Hinweis darauf, worauf sich dein Inhalt konzentriert. Wenn sich die Wörter stark von deinem Thema unterscheiden, möchtest du vielleicht deinen Inhalt entsprechend umschreiben. "],"Prominent words":["Prominente Wörter "],"Something went wrong. Please reload the page.":["Das hat nicht funktioniert. Bitte lade die Seite neu."],"Modify your meta description by editing it right here":["Bearbeite direkt hier deine Meta-Beschreibung "],"Url preview":["URL-Vorschau"],"Please provide a meta description by editing the snippet below. If you don’t, Google will try to find a relevant part of your post to show in the search results.":["Bitte bearbeite das Codeschnipsel und richte eine Meta-Beschreibung ein. Wenn du dies nicht tust, wird Google selbständig versuchen, einen relevanten Teil deines Beitrags in den Suchergebnissen anzuzeigen."],"Insert snippet variable":["Codeschnipsel-Variable einsetzen"],"Dismiss this notice":["Ignoriere diese Nachricht"],"No results":["Keine Ergebnisse"],"%d result found, use up and down arrow keys to navigate":["%d Ergebnis gefunden, mit den Pfeiltasten nach oben und unten navigieren","%d Ergebnisse gefunden, mit den Pfeiltasten nach oben und unten navigieren"],"Your site language is set to %s. If this is not correct, contact your site administrator.":["Die Sprache deiner Website ist auf %s eingestellt. Wenn dies nicht korrekt ist, wende dich an deinen Website-Administrator."],"On":["An"],"Off":["Aus"],"Good results":["Gute Ergebnisse"],"Remove highlight from the text":["Text-Markierung entfernen"],"Your site language is set to %s. ":["Die Sprache deiner Website ist auf %s eingestellt."],"Highlight this result in the text":["Markiere dieses Ergebnis im Text"],"Considerations":["Überlegungen"],"Errors":["Fehler"],"Change language":["Sprache ändern"],"(Opens in a new browser tab)":["(Öffnet in einem neuen Browser Tab)"],"Scroll to see the preview content.":["Scrolle, um die Vorschau zu sehen."],"Step %1$d: %2$s":["Schritt %1$d: %2$s"],"Close snippet editor":["Ausschnitt-Editor schließen"],"Slug":["Permalink"],"Marks are disabled in current view":["Markierungen sind in der aktuellen Ansicht deaktiviert."],"Choose an image":["Wähle ein Bild"],"Remove the image":["Bild entfernen"],"MailChimp signup failed:":["MailChimp-Registrierung fehlgeschlagen:"],"Sign Up!":["Anmelden"],"Edit snippet":["Code-Schnipsel bearbeiten"],"SEO title preview":["SEO-Titel Vorschau"],"Meta description preview":["Meta Description Vorschau"],"A problem occurred when saving the current step, {{link}}please file a bug report{{/link}} describing what step you are on and which changes you want to make (if any).":["Beim Speichern des aktuellen Schritts ist ein Problem aufgetreten. {{link}}Bitte erfasse einen Fehlerbericht{{/link}}, der beschreibt in welchen Schritt du warst und welche Änderungen du vorgenommen hast (falls Änderungen gemacht wurden)."],"Close the Wizard":["Schließe den Assistenten "],"%s installation wizard":["%s Installationsassistent"],"SEO title":["SEO Titel"],"Improvements":["Verbesserungen"],"Problems":["Probleme"],"Email":["E-Mail"],"Previous":["Zurück"],"Next":["Weiter"],"Close":["Schließen"],"Meta description":["Meta-Beschreibung"]}}}
|
src/orm/yoast-model.php → lib/model.php
RENAMED
@@ -1,13 +1,11 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* Yoast
|
4 |
*
|
5 |
-
* @package Yoast\
|
6 |
*/
|
7 |
|
8 |
-
namespace Yoast\WP\
|
9 |
-
|
10 |
-
use Yoast\WP\SEO\Exceptions\Missing_Method;
|
11 |
|
12 |
/**
|
13 |
* Make Model compatible with WordPress.
|
@@ -18,18 +16,8 @@ use Yoast\WP\SEO\Exceptions\Missing_Method;
|
|
18 |
* class Widget extends Model {
|
19 |
* }
|
20 |
*
|
21 |
-
* The methods documented below are magic methods that conform to PSR-1.
|
22 |
-
* This documentation exposes these methods to doc generators and IDEs.
|
23 |
-
*
|
24 |
-
* @link http://www.php-fig.org/psr/psr-1/
|
25 |
-
*
|
26 |
-
* @method void setOrm($orm)
|
27 |
-
* @method $this setExpr($property, $value = null)
|
28 |
-
* @method bool isDirty($property)
|
29 |
-
* @method bool isNew()
|
30 |
-
* @method Array asArray()
|
31 |
*/
|
32 |
-
class
|
33 |
|
34 |
/**
|
35 |
* Default ID column for all models. Can be overridden by adding
|
@@ -57,13 +45,6 @@ class Yoast_Model {
|
|
57 |
*/
|
58 |
public static $auto_prefix_models = '\Yoast\WP\SEO\Models\\';
|
59 |
|
60 |
-
/**
|
61 |
-
* Set a logger to use for all models.
|
62 |
-
*
|
63 |
-
* @var \YoastSEO_Vendor\Psr\Log\LoggerInterface $logger
|
64 |
-
*/
|
65 |
-
public static $logger;
|
66 |
-
|
67 |
/**
|
68 |
* Set true to to ignore namespace information when computing table names
|
69 |
* from class names.
|
@@ -78,7 +59,7 @@ class Yoast_Model {
|
|
78 |
/**
|
79 |
* The ORM instance used by this model instance to communicate with the database.
|
80 |
*
|
81 |
-
* @var
|
82 |
*/
|
83 |
public $orm;
|
84 |
|
@@ -116,7 +97,7 @@ class Yoast_Model {
|
|
116 |
* @param string $class_name Type of Model to load.
|
117 |
* @param bool $yoast_prefix Optional. True to prefix the table name with the Yoast prefix.
|
118 |
*
|
119 |
-
* @return
|
120 |
*/
|
121 |
public static function of_type( $class_name, $yoast_prefix = true ) {
|
122 |
// Prepend namespace to the class name.
|
@@ -133,7 +114,7 @@ class Yoast_Model {
|
|
133 |
*
|
134 |
* @param string $class_name Type of Model to load.
|
135 |
*
|
136 |
-
* @return
|
137 |
*/
|
138 |
public static function of_wp_type( $class_name ) {
|
139 |
return static::of_type( $class_name, false );
|
@@ -316,18 +297,14 @@ class Yoast_Model {
|
|
316 |
* responsible for returning instances of the correct class when
|
317 |
* its find_one or find_many methods are called.
|
318 |
*
|
319 |
-
* @param string
|
320 |
-
* @param null|string $connection_name The name of the connection.
|
321 |
*
|
322 |
-
* @return
|
323 |
*/
|
324 |
-
public static function factory( $class_name
|
325 |
$class_name = static::$auto_prefix_models . $class_name;
|
326 |
$table_name = static::get_table_name_for_class( $class_name );
|
327 |
-
|
328 |
-
$connection_name = static::get_static_property( $class_name, '_connection_name', ORMWrapper::DEFAULT_CONNECTION );
|
329 |
-
}
|
330 |
-
$wrapper = ORMWrapper::for_table( $table_name, $connection_name );
|
331 |
$wrapper->set_class_name( $class_name );
|
332 |
$wrapper->use_id_column( static::get_id_column_name( $class_name ) );
|
333 |
|
@@ -343,12 +320,11 @@ class Yoast_Model {
|
|
343 |
* @param string $associated_class_name The associated class name.
|
344 |
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
345 |
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
346 |
-
* @param null|string $connection_name The name of the connection.
|
347 |
*
|
348 |
-
* @return
|
349 |
* @throws \Exception When ID of current model has a null value.
|
350 |
*/
|
351 |
-
protected function has_one_or_many( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null
|
352 |
$base_table_name = static::get_table_name_for_class( \get_class( $this ) );
|
353 |
$foreign_key_name = static::build_foreign_key_name( $foreign_key_name, $base_table_name );
|
354 |
|
@@ -365,7 +341,7 @@ class Yoast_Model {
|
|
365 |
$where_value = $this->{$foreign_key_name_in_current_models_table};
|
366 |
}
|
367 |
|
368 |
-
return static::factory( $associated_class_name
|
369 |
}
|
370 |
|
371 |
/**
|
@@ -375,13 +351,12 @@ class Yoast_Model {
|
|
375 |
* @param string $associated_class_name The associated class name.
|
376 |
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
377 |
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
378 |
-
* @param null|string $connection_name The name of the connection.
|
379 |
*
|
380 |
-
* @return
|
381 |
* @throws \Exception When ID of current model has a null value.
|
382 |
*/
|
383 |
-
protected function has_one( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null
|
384 |
-
return $this->has_one_or_many( $associated_class_name, $foreign_key_name, $foreign_key_name_in_current_models_table
|
385 |
}
|
386 |
|
387 |
/**
|
@@ -391,15 +366,14 @@ class Yoast_Model {
|
|
391 |
* @param string $associated_class_name The associated class name.
|
392 |
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
393 |
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
394 |
-
* @param null|string $connection_name The name of the connection.
|
395 |
*
|
396 |
-
* @return
|
397 |
* @throws \Exception When ID has a null value.
|
398 |
*/
|
399 |
-
protected function has_many( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null
|
400 |
$this->set_table_name( $associated_class_name );
|
401 |
|
402 |
-
return $this->has_one_or_many( $associated_class_name, $foreign_key_name, $foreign_key_name_in_current_models_table
|
403 |
}
|
404 |
|
405 |
/**
|
@@ -409,11 +383,10 @@ class Yoast_Model {
|
|
409 |
* @param string $associated_class_name The associated class name.
|
410 |
* @param null|string $foreign_key_name The foreign key in the current models table.
|
411 |
* @param null|string $foreign_key_name_in_associated_models_table The foreign key in the associated table.
|
412 |
-
* @param null|string $connection_name The name of the connection.
|
413 |
*
|
414 |
* @return $this|null Instance of the foreign model.
|
415 |
*/
|
416 |
-
protected function belongs_to( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_associated_models_table = null
|
417 |
$this->set_table_name( $associated_class_name );
|
418 |
|
419 |
$associated_table_name = static::get_table_name_for_class( static::$auto_prefix_models . $associated_class_name );
|
@@ -426,11 +399,11 @@ class Yoast_Model {
|
|
426 |
*
|
427 |
* NOTE: primary_key is a placeholder for the actual primary key column's name in $associated_table_name.
|
428 |
*/
|
429 |
-
return static::factory( $associated_class_name
|
430 |
}
|
431 |
|
432 |
// Comparison: "{$associated_table_name}.{$foreign_key_name_in_associated_models_table} = {$associated_object_id}".
|
433 |
-
return static::factory( $associated_class_name
|
434 |
}
|
435 |
|
436 |
/**
|
@@ -443,11 +416,10 @@ class Yoast_Model {
|
|
443 |
* @param null|string $key_to_associated_table The key to the associated table.
|
444 |
* @param null|string $key_in_base_table The key in the current models table.
|
445 |
* @param null|string $key_in_associated_table The key in the associated table.
|
446 |
-
* @param null|string $connection_name The name of the connection.
|
447 |
*
|
448 |
-
* @return
|
449 |
*/
|
450 |
-
protected function has_many_through( $associated_class_name, $join_class_name = null, $key_to_base_table = null, $key_to_associated_table = null, $key_in_base_table = null, $key_in_associated_table = null
|
451 |
$base_class_name = \get_class( $this );
|
452 |
|
453 |
/*
|
@@ -491,7 +463,7 @@ class Yoast_Model {
|
|
491 |
ON {$associated_table_name}.{$associated_table_id_column} = {$join_table_name}.{$key_to_associated_table}
|
492 |
WHERE {$join_table_name}.{$key_to_base_table} = {$this->$base_table_id_column} ;"
|
493 |
*/
|
494 |
-
return static::factory( $associated_class_name
|
495 |
->select( "{$associated_table_name}.*" )
|
496 |
->join(
|
497 |
$join_table_name,
|
@@ -507,7 +479,7 @@ class Yoast_Model {
|
|
507 |
/**
|
508 |
* Set the wrapped ORM instance associated with this Model instance.
|
509 |
*
|
510 |
-
* @param
|
511 |
*
|
512 |
* @return void
|
513 |
*/
|
@@ -696,7 +668,7 @@ class Yoast_Model {
|
|
696 |
}
|
697 |
|
698 |
/**
|
699 |
-
* Calls static methods directly on the
|
700 |
*
|
701 |
* @param string $method The method to call.
|
702 |
* @param array $arguments The arguments to use.
|
@@ -712,28 +684,4 @@ class Yoast_Model {
|
|
712 |
|
713 |
return \call_user_func_array( [ $model, $method ], $arguments );
|
714 |
}
|
715 |
-
|
716 |
-
/**
|
717 |
-
* Magic method to capture calls to undefined class methods.
|
718 |
-
* In this case we are attempting to convert camel case formatted
|
719 |
-
* methods into underscore formatted methods.
|
720 |
-
*
|
721 |
-
* This allows us to call methods using camel case and remain
|
722 |
-
* backwards compatible.
|
723 |
-
*
|
724 |
-
* @param string $name The method to call.
|
725 |
-
* @param array $arguments The arguments to use.
|
726 |
-
*
|
727 |
-
* @throws \Yoast\WP\SEO\Exceptions\Missing_Method When the method does not exist.
|
728 |
-
*
|
729 |
-
* @return bool|\Yoast\WP\SEO\ORMWrapper Result of the call.
|
730 |
-
*/
|
731 |
-
public function __call( $name, $arguments ) {
|
732 |
-
$method = \strtolower( \preg_replace( '/([a-z])([A-Z])/', '$1_$2', $name ) );
|
733 |
-
if ( ! \method_exists( $this, $method ) ) {
|
734 |
-
throw Missing_Method::for_class( \get_class( $this ), $name );
|
735 |
-
}
|
736 |
-
|
737 |
-
return \call_user_func_array( [ $this, $method ], $arguments );
|
738 |
-
}
|
739 |
}
|
1 |
<?php
|
2 |
/**
|
3 |
+
* Yoast model class.
|
4 |
*
|
5 |
+
* @package Yoast\WP\Lib
|
6 |
*/
|
7 |
|
8 |
+
namespace Yoast\WP\Lib;
|
|
|
|
|
9 |
|
10 |
/**
|
11 |
* Make Model compatible with WordPress.
|
16 |
* class Widget extends Model {
|
17 |
* }
|
18 |
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
*/
|
20 |
+
class Model {
|
21 |
|
22 |
/**
|
23 |
* Default ID column for all models. Can be overridden by adding
|
45 |
*/
|
46 |
public static $auto_prefix_models = '\Yoast\WP\SEO\Models\\';
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
/**
|
49 |
* Set true to to ignore namespace information when computing table names
|
50 |
* from class names.
|
59 |
/**
|
60 |
* The ORM instance used by this model instance to communicate with the database.
|
61 |
*
|
62 |
+
* @var ORM $orm
|
63 |
*/
|
64 |
public $orm;
|
65 |
|
97 |
* @param string $class_name Type of Model to load.
|
98 |
* @param bool $yoast_prefix Optional. True to prefix the table name with the Yoast prefix.
|
99 |
*
|
100 |
+
* @return ORM Wrapper to use.
|
101 |
*/
|
102 |
public static function of_type( $class_name, $yoast_prefix = true ) {
|
103 |
// Prepend namespace to the class name.
|
114 |
*
|
115 |
* @param string $class_name Type of Model to load.
|
116 |
*
|
117 |
+
* @return ORM
|
118 |
*/
|
119 |
public static function of_wp_type( $class_name ) {
|
120 |
return static::of_type( $class_name, false );
|
297 |
* responsible for returning instances of the correct class when
|
298 |
* its find_one or find_many methods are called.
|
299 |
*
|
300 |
+
* @param string $class_name The target class name.
|
|
|
301 |
*
|
302 |
+
* @return ORM Instance of the ORM wrapper.
|
303 |
*/
|
304 |
+
public static function factory( $class_name ) {
|
305 |
$class_name = static::$auto_prefix_models . $class_name;
|
306 |
$table_name = static::get_table_name_for_class( $class_name );
|
307 |
+
$wrapper = ORM::for_table( $table_name );
|
|
|
|
|
|
|
308 |
$wrapper->set_class_name( $class_name );
|
309 |
$wrapper->use_id_column( static::get_id_column_name( $class_name ) );
|
310 |
|
320 |
* @param string $associated_class_name The associated class name.
|
321 |
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
322 |
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
|
|
323 |
*
|
324 |
+
* @return ORM
|
325 |
* @throws \Exception When ID of current model has a null value.
|
326 |
*/
|
327 |
+
protected function has_one_or_many( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null ) {
|
328 |
$base_table_name = static::get_table_name_for_class( \get_class( $this ) );
|
329 |
$foreign_key_name = static::build_foreign_key_name( $foreign_key_name, $base_table_name );
|
330 |
|
341 |
$where_value = $this->{$foreign_key_name_in_current_models_table};
|
342 |
}
|
343 |
|
344 |
+
return static::factory( $associated_class_name )->where( $foreign_key_name, $where_value );
|
345 |
}
|
346 |
|
347 |
/**
|
351 |
* @param string $associated_class_name The associated class name.
|
352 |
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
353 |
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
|
|
354 |
*
|
355 |
+
* @return ORM Instance of the ORM.
|
356 |
* @throws \Exception When ID of current model has a null value.
|
357 |
*/
|
358 |
+
protected function has_one( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null ) {
|
359 |
+
return $this->has_one_or_many( $associated_class_name, $foreign_key_name, $foreign_key_name_in_current_models_table );
|
360 |
}
|
361 |
|
362 |
/**
|
366 |
* @param string $associated_class_name The associated class name.
|
367 |
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
368 |
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
|
|
369 |
*
|
370 |
+
* @return ORM Instance of the ORM.
|
371 |
* @throws \Exception When ID has a null value.
|
372 |
*/
|
373 |
+
protected function has_many( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null ) {
|
374 |
$this->set_table_name( $associated_class_name );
|
375 |
|
376 |
+
return $this->has_one_or_many( $associated_class_name, $foreign_key_name, $foreign_key_name_in_current_models_table );
|
377 |
}
|
378 |
|
379 |
/**
|
383 |
* @param string $associated_class_name The associated class name.
|
384 |
* @param null|string $foreign_key_name The foreign key in the current models table.
|
385 |
* @param null|string $foreign_key_name_in_associated_models_table The foreign key in the associated table.
|
|
|
386 |
*
|
387 |
* @return $this|null Instance of the foreign model.
|
388 |
*/
|
389 |
+
protected function belongs_to( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_associated_models_table = null ) {
|
390 |
$this->set_table_name( $associated_class_name );
|
391 |
|
392 |
$associated_table_name = static::get_table_name_for_class( static::$auto_prefix_models . $associated_class_name );
|
399 |
*
|
400 |
* NOTE: primary_key is a placeholder for the actual primary key column's name in $associated_table_name.
|
401 |
*/
|
402 |
+
return static::factory( $associated_class_name )->where_id_is( $associated_object_id );
|
403 |
}
|
404 |
|
405 |
// Comparison: "{$associated_table_name}.{$foreign_key_name_in_associated_models_table} = {$associated_object_id}".
|
406 |
+
return static::factory( $associated_class_name )->where( $foreign_key_name_in_associated_models_table, $associated_object_id );
|
407 |
}
|
408 |
|
409 |
/**
|
416 |
* @param null|string $key_to_associated_table The key to the associated table.
|
417 |
* @param null|string $key_in_base_table The key in the current models table.
|
418 |
* @param null|string $key_in_associated_table The key in the associated table.
|
|
|
419 |
*
|
420 |
+
* @return ORM Instance of the ORM.
|
421 |
*/
|
422 |
+
protected function has_many_through( $associated_class_name, $join_class_name = null, $key_to_base_table = null, $key_to_associated_table = null, $key_in_base_table = null, $key_in_associated_table = null ) {
|
423 |
$base_class_name = \get_class( $this );
|
424 |
|
425 |
/*
|
463 |
ON {$associated_table_name}.{$associated_table_id_column} = {$join_table_name}.{$key_to_associated_table}
|
464 |
WHERE {$join_table_name}.{$key_to_base_table} = {$this->$base_table_id_column} ;"
|
465 |
*/
|
466 |
+
return static::factory( $associated_class_name )
|
467 |
->select( "{$associated_table_name}.*" )
|
468 |
->join(
|
469 |
$join_table_name,
|
479 |
/**
|
480 |
* Set the wrapped ORM instance associated with this Model instance.
|
481 |
*
|
482 |
+
* @param ORM $orm The ORM instance to set.
|
483 |
*
|
484 |
* @return void
|
485 |
*/
|
668 |
}
|
669 |
|
670 |
/**
|
671 |
+
* Calls static methods directly on the ORM
|
672 |
*
|
673 |
* @param string $method The method to call.
|
674 |
* @param array $arguments The arguments to use.
|
684 |
|
685 |
return \call_user_func_array( [ $model, $method ], $arguments );
|
686 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
687 |
}
|
lib/orm.php
ADDED
@@ -0,0 +1,2342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Yoast ORM class.
|
4 |
+
*
|
5 |
+
* @package Yoast\WP\Lib
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Yoast\WP\Lib;
|
9 |
+
|
10 |
+
use wpdb;
|
11 |
+
|
12 |
+
/**
|
13 |
+
*
|
14 |
+
* Based on Idiorm
|
15 |
+
*
|
16 |
+
* http://github.com/j4mie/idiorm/
|
17 |
+
*
|
18 |
+
* A single-class super-simple database abstraction layer for PHP.
|
19 |
+
* Provides (nearly) zero-configuration object-relational mapping
|
20 |
+
* and a fluent interface for building basic, commonly-used queries.
|
21 |
+
*
|
22 |
+
* BSD Licensed.
|
23 |
+
*
|
24 |
+
* Copyright (c) 2010, Jamie Matthews
|
25 |
+
* All rights reserved.
|
26 |
+
*
|
27 |
+
* Redistribution and use in source and binary forms, with or without
|
28 |
+
* modification, are permitted provided that the following conditions are met:
|
29 |
+
*
|
30 |
+
* * Redistributions of source code must retain the above copyright notice, this
|
31 |
+
* list of conditions and the following disclaimer.
|
32 |
+
*
|
33 |
+
* * Redistributions in binary form must reproduce the above copyright notice,
|
34 |
+
* this list of conditions and the following disclaimer in the documentation
|
35 |
+
* and/or other materials provided with the distribution.
|
36 |
+
*
|
37 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
38 |
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
39 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
40 |
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
41 |
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
42 |
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
43 |
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
44 |
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
45 |
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
46 |
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
47 |
+
*
|
48 |
+
*
|
49 |
+
* The methods documented below are magic methods that conform to PSR-1.
|
50 |
+
* This documentation exposes these methods to doc generators and IDEs.
|
51 |
+
*
|
52 |
+
* @see http://www.php-fig.org/psr/psr-1/
|
53 |
+
*/
|
54 |
+
class ORM implements \ArrayAccess {
|
55 |
+
|
56 |
+
// ----------------------- //
|
57 |
+
// --- CLASS CONSTANTS --- //
|
58 |
+
// ----------------------- //
|
59 |
+
// WHERE and HAVING condition array keys
|
60 |
+
const CONDITION_FRAGMENT = 0;
|
61 |
+
const CONDITION_VALUES = 1;
|
62 |
+
// --------------------------- //
|
63 |
+
// --- INSTANCE PROPERTIES --- //
|
64 |
+
// --------------------------- //
|
65 |
+
/**
|
66 |
+
* The wrapped find_one and find_many classes will return an instance or
|
67 |
+
* instances of this class.
|
68 |
+
*
|
69 |
+
* @var string
|
70 |
+
*/
|
71 |
+
protected $class_name;
|
72 |
+
/**
|
73 |
+
* The name of the table the current ORM instance is associated with.
|
74 |
+
*
|
75 |
+
* @var string
|
76 |
+
*/
|
77 |
+
protected $_table_name;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Alias for the table to be used in SELECT queries
|
81 |
+
*
|
82 |
+
* @var string
|
83 |
+
*/
|
84 |
+
protected $_table_alias = null;
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Values to be bound to the query
|
88 |
+
*
|
89 |
+
* @var array
|
90 |
+
*/
|
91 |
+
protected $_values = [];
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Columns to select in the result
|
95 |
+
*
|
96 |
+
* @var array
|
97 |
+
*/
|
98 |
+
protected $_result_columns = [ '*' ];
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Are we using the default result column or have these been manually changed?
|
102 |
+
*
|
103 |
+
* @var boolean
|
104 |
+
*/
|
105 |
+
protected $_using_default_result_columns = true;
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Join sources
|
109 |
+
*
|
110 |
+
* @var array
|
111 |
+
*/
|
112 |
+
protected $_join_sources = [];
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Should the query include a DISTINCT keyword?
|
116 |
+
*
|
117 |
+
* @var boolean
|
118 |
+
*/
|
119 |
+
protected $_distinct = false;
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Is this a raw query?
|
123 |
+
*
|
124 |
+
* @var boolean
|
125 |
+
*/
|
126 |
+
protected $_is_raw_query = false;
|
127 |
+
|
128 |
+
/**
|
129 |
+
* The raw query
|
130 |
+
*
|
131 |
+
* @var string
|
132 |
+
*/
|
133 |
+
protected $_raw_query = '';
|
134 |
+
|
135 |
+
/**
|
136 |
+
* The raw query parameters
|
137 |
+
*
|
138 |
+
* @var array
|
139 |
+
*/
|
140 |
+
protected $_raw_parameters = [];
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Array of WHERE clauses
|
144 |
+
*
|
145 |
+
* @var array
|
146 |
+
*/
|
147 |
+
protected $_where_conditions = [];
|
148 |
+
|
149 |
+
/**
|
150 |
+
* LIMIT
|
151 |
+
*
|
152 |
+
* @var int
|
153 |
+
*/
|
154 |
+
protected $_limit = null;
|
155 |
+
|
156 |
+
/**
|
157 |
+
* OFFSET
|
158 |
+
*
|
159 |
+
* @var int
|
160 |
+
*/
|
161 |
+
protected $_offset = null;
|
162 |
+
|
163 |
+
/**
|
164 |
+
* ORDER BY
|
165 |
+
*
|
166 |
+
* @var array
|
167 |
+
*/
|
168 |
+
protected $_order_by = [];
|
169 |
+
|
170 |
+
/**
|
171 |
+
* GROUP BY
|
172 |
+
*
|
173 |
+
* @var array
|
174 |
+
*/
|
175 |
+
protected $_group_by = [];
|
176 |
+
|
177 |
+
/**
|
178 |
+
* HAVING
|
179 |
+
*
|
180 |
+
* @var array
|
181 |
+
*/
|
182 |
+
protected $_having_conditions = [];
|
183 |
+
|
184 |
+
/**
|
185 |
+
* The data for a hydrated instance of the class
|
186 |
+
*
|
187 |
+
* @var array
|
188 |
+
*/
|
189 |
+
protected $_data = [];
|
190 |
+
|
191 |
+
/**
|
192 |
+
* lifetime of the object
|
193 |
+
*
|
194 |
+
* @var array
|
195 |
+
*/
|
196 |
+
protected $_dirty_fields = [];
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Fields that are to be inserted in the DB raw
|
200 |
+
*
|
201 |
+
* @var array
|
202 |
+
*/
|
203 |
+
protected $_expr_fields = [];
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Is this a new object (has create() been called)?
|
207 |
+
*
|
208 |
+
* @var boolean
|
209 |
+
*/
|
210 |
+
protected $_is_new = false;
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Name of the column to use as the primary key for
|
214 |
+
* this instance only. Overrides the config settings.
|
215 |
+
*
|
216 |
+
* @var string
|
217 |
+
*/
|
218 |
+
protected $_instance_id_column = null;
|
219 |
+
// ---------------------- //
|
220 |
+
// --- STATIC METHODS --- //
|
221 |
+
// ---------------------- //
|
222 |
+
/**
|
223 |
+
* Factory method, return an instance of this class bound to the supplied
|
224 |
+
* table name.
|
225 |
+
*
|
226 |
+
* A repeat of content in parent::for_table, so that created class is
|
227 |
+
* ORMWrapper, not ORM.
|
228 |
+
*
|
229 |
+
* @param string $table_name Table name. The table to create instance for.
|
230 |
+
*
|
231 |
+
* @return ORM Instance of the ORM wrapper.
|
232 |
+
*/
|
233 |
+
public static function for_table( $table_name ) {
|
234 |
+
return new static( $table_name, [] );
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Executes a raw query as a wrapper for wpdb::query.
|
239 |
+
* Useful for queries that can't be accomplished through Idiorm,
|
240 |
+
* particularly those using engine-specific features.
|
241 |
+
*
|
242 |
+
* @param string $query The raw SQL query
|
243 |
+
* @param array $parameters Optional bound parameters
|
244 |
+
*
|
245 |
+
* @return bool Success
|
246 |
+
* @example raw_execute('SELECT `name`, AVG(`order`) FROM `customer` GROUP BY `name` HAVING AVG(`order`) > 10')
|
247 |
+
*
|
248 |
+
* @example raw_execute('INSERT OR REPLACE INTO `widget` (`id`, `name`) SELECT `id`, `name` FROM `other_table`')
|
249 |
+
*/
|
250 |
+
public static function raw_execute( $query, $parameters = [] ) {
|
251 |
+
return self::_execute( $query, $parameters );
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Internal helper method for executing statements.
|
256 |
+
*
|
257 |
+
* @param string $query The query.
|
258 |
+
* @param array $parameters An array of parameters to be bound in to the query.
|
259 |
+
*
|
260 |
+
* @return bool|int Response of wpdb::query
|
261 |
+
*/
|
262 |
+
protected static function _execute( $query, $parameters = [] ) {
|
263 |
+
/**
|
264 |
+
* @var wpdb wpdb
|
265 |
+
*/
|
266 |
+
global $wpdb;
|
267 |
+
|
268 |
+
$query = $wpdb->prepare( $query, $parameters );
|
269 |
+
|
270 |
+
return $wpdb->query( $query );
|
271 |
+
}
|
272 |
+
|
273 |
+
// ------------------------ //
|
274 |
+
// --- INSTANCE METHODS --- //
|
275 |
+
// ------------------------ //
|
276 |
+
/**
|
277 |
+
* "Private" constructor; shouldn't be called directly.
|
278 |
+
* Use the ORM::for_table factory method instead.
|
279 |
+
*
|
280 |
+
* @param string $table_name Table name.
|
281 |
+
* @param array $data Data to populate table.
|
282 |
+
*/
|
283 |
+
protected function __construct( $table_name, $data = [] ) {
|
284 |
+
$this->_table_name = $table_name;
|
285 |
+
$this->_data = $data;
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Set the name of the class which the wrapped methods should return
|
290 |
+
* instances of.
|
291 |
+
*
|
292 |
+
* @param string $class_name The classname to set.
|
293 |
+
*
|
294 |
+
* @return void
|
295 |
+
*/
|
296 |
+
public function set_class_name( $class_name ) {
|
297 |
+
$this->class_name = $class_name;
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Create a new, empty instance of the class. Used
|
302 |
+
* to add a new row to your database. May optionally
|
303 |
+
* be passed an associative array of data to populate
|
304 |
+
* the instance. If so, all fields will be flagged as
|
305 |
+
* dirty so all will be saved to the database when
|
306 |
+
* save() is called.
|
307 |
+
*
|
308 |
+
* @param array|null $data Data to populate table.
|
309 |
+
*
|
310 |
+
* @return bool|Model|ORM
|
311 |
+
*/
|
312 |
+
public function create( $data = null ) {
|
313 |
+
$this->_is_new = true;
|
314 |
+
if ( ! \is_null( $data ) ) {
|
315 |
+
$this->hydrate( $data )->force_all_dirty();
|
316 |
+
}
|
317 |
+
|
318 |
+
return $this->create_model_instance( $this );
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Specify the ID column to use for this instance or array of instances only.
|
323 |
+
* This overrides the id_column and id_column_overrides settings.
|
324 |
+
*
|
325 |
+
* This is mostly useful for libraries built on top of Idiorm, and will
|
326 |
+
* not normally be used in manually built queries. If you don't know why
|
327 |
+
* you would want to use this, you should probably just ignore it.
|
328 |
+
*
|
329 |
+
* @param string $id_column The ID column.
|
330 |
+
*
|
331 |
+
* @return ORM
|
332 |
+
*/
|
333 |
+
public function use_id_column( $id_column ) {
|
334 |
+
$this->_instance_id_column = $id_column;
|
335 |
+
|
336 |
+
return $this;
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Create an ORM instance from the given row (an associative
|
341 |
+
* array of data fetched from the database)
|
342 |
+
*
|
343 |
+
* @param array $row A row from the database.
|
344 |
+
*
|
345 |
+
* @return bool|Model
|
346 |
+
*/
|
347 |
+
protected function _create_instance_from_row( $row ) {
|
348 |
+
$instance = self::for_table( $this->_table_name );
|
349 |
+
$instance->use_id_column( $this->_instance_id_column );
|
350 |
+
$instance->hydrate( $row );
|
351 |
+
|
352 |
+
return $this->create_model_instance( $instance );
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* Tell the ORM that you are expecting a single result
|
357 |
+
* back from your query, and execute it. Will return
|
358 |
+
* a single instance of the ORM class, or false if no
|
359 |
+
* rows were returned.
|
360 |
+
* As a shortcut, you may supply an ID as a parameter
|
361 |
+
* to this method. This will perform a primary key
|
362 |
+
* lookup on the table.
|
363 |
+
*
|
364 |
+
* @param null|int $id An (optional) ID.
|
365 |
+
*
|
366 |
+
* @return bool|Model
|
367 |
+
*/
|
368 |
+
public function find_one( $id = null ) {
|
369 |
+
if ( ! \is_null( $id ) ) {
|
370 |
+
$this->where_id_is( $id );
|
371 |
+
}
|
372 |
+
$this->limit( 1 );
|
373 |
+
$rows = $this->_run();
|
374 |
+
if ( empty( $rows ) ) {
|
375 |
+
return false;
|
376 |
+
}
|
377 |
+
|
378 |
+
return $this->_create_instance_from_row( $rows[0] );
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Tell the ORM that you are expecting multiple results
|
383 |
+
* from your query, and execute it. Will return an array
|
384 |
+
* of instances of the ORM class, or an empty array if
|
385 |
+
* no rows were returned.
|
386 |
+
*
|
387 |
+
* @return array
|
388 |
+
*/
|
389 |
+
public function find_many() {
|
390 |
+
$rows = $this->_run();
|
391 |
+
|
392 |
+
if ( $rows === false ) {
|
393 |
+
return [];
|
394 |
+
}
|
395 |
+
|
396 |
+
return \array_map( [ $this, '_create_instance_from_row' ], $rows );
|
397 |
+
}
|
398 |
+
|
399 |
+
/**
|
400 |
+
* Method to create an instance of the model class associated with this
|
401 |
+
* wrapper and populate it with the supplied Idiorm instance.
|
402 |
+
*
|
403 |
+
* @param ORM $orm The ORM used by model.
|
404 |
+
*
|
405 |
+
* @return bool|Model Instance of the model class.
|
406 |
+
*/
|
407 |
+
protected function create_model_instance( $orm ) {
|
408 |
+
if ( $orm === false ) {
|
409 |
+
return false;
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* An instance of Model is being made.
|
414 |
+
*
|
415 |
+
* @var Model $model
|
416 |
+
*/
|
417 |
+
$model = new $this->class_name();
|
418 |
+
$model->set_orm( $orm );
|
419 |
+
|
420 |
+
return $model;
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Tell the ORM that you are expecting multiple results
|
425 |
+
* from your query, and execute it. Will return an array,
|
426 |
+
* or an empty array if no rows were returned.
|
427 |
+
*
|
428 |
+
* @return array The query results.
|
429 |
+
*/
|
430 |
+
public function find_array() {
|
431 |
+
return $this->_run();
|
432 |
+
}
|
433 |
+
|
434 |
+
/**
|
435 |
+
* Tell the ORM that you wish to execute a COUNT query.
|
436 |
+
*
|
437 |
+
* @param string $column The table column.
|
438 |
+
*
|
439 |
+
* @return float|int An integer representing the number of rows returned.
|
440 |
+
*/
|
441 |
+
public function count( $column = '*' ) {
|
442 |
+
return $this->_call_aggregate_db_function( __FUNCTION__, $column );
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* Tell the ORM that you wish to execute a MAX query.
|
447 |
+
*
|
448 |
+
* @param string $column The table column.
|
449 |
+
*
|
450 |
+
* @return float|int The max value of the chosen column.
|
451 |
+
*/
|
452 |
+
public function max( $column ) {
|
453 |
+
return $this->_call_aggregate_db_function( __FUNCTION__, $column );
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Tell the ORM that you wish to execute a MIN query.
|
458 |
+
*
|
459 |
+
* @param string $column The table column.
|
460 |
+
*
|
461 |
+
* @return float|int The min value of the chosen column.
|
462 |
+
*/
|
463 |
+
public function min( $column ) {
|
464 |
+
return $this->_call_aggregate_db_function( __FUNCTION__, $column );
|
465 |
+
}
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Tell the ORM that you wish to execute a AVG query.
|
469 |
+
*
|
470 |
+
* @param string $column The table column.
|
471 |
+
*
|
472 |
+
* @return float|int The average value of the chosen column.
|
473 |
+
*/
|
474 |
+
public function avg( $column ) {
|
475 |
+
return $this->_call_aggregate_db_function( __FUNCTION__, $column );
|
476 |
+
}
|
477 |
+
|
478 |
+
/**
|
479 |
+
* Tell the ORM that you wish to execute a SUM query.
|
480 |
+
*
|
481 |
+
* @param string $column The table column.
|
482 |
+
*
|
483 |
+
* @return float|int The sum of the chosen column.
|
484 |
+
*/
|
485 |
+
public function sum( $column ) {
|
486 |
+
return $this->_call_aggregate_db_function( __FUNCTION__, $column );
|
487 |
+
}
|
488 |
+
|
489 |
+
/**
|
490 |
+
* Returns the select query as SQL.
|
491 |
+
*
|
492 |
+
* @return string The select query in SQL.
|
493 |
+
*/
|
494 |
+
public function get_sql() {
|
495 |
+
return $this->_build_select();
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Returns the update query as SQL.
|
500 |
+
*
|
501 |
+
* @return string The update query in SQL.
|
502 |
+
*/
|
503 |
+
public function get_update_sql() {
|
504 |
+
return $this->_build_update();
|
505 |
+
}
|
506 |
+
|
507 |
+
/**
|
508 |
+
* Execute an aggregate query on the current connection.
|
509 |
+
*
|
510 |
+
* @param string $sql_function The aggregate function to call eg. MIN, COUNT, etc
|
511 |
+
* @param string $column The column to execute the aggregate query against
|
512 |
+
*
|
513 |
+
* @return int
|
514 |
+
*/
|
515 |
+
protected function _call_aggregate_db_function( $sql_function, $column ) {
|
516 |
+
$alias = \strtolower( $sql_function );
|
517 |
+
$sql_function = \strtoupper( $sql_function );
|
518 |
+
if ( '*' != $column ) {
|
519 |
+
$column = $this->_quote_identifier( $column );
|
520 |
+
}
|
521 |
+
$result_columns = $this->_result_columns;
|
522 |
+
$this->_result_columns = [];
|
523 |
+
$this->select_expr( "{$sql_function}({$column})", $alias );
|
524 |
+
$result = $this->find_one();
|
525 |
+
$this->_result_columns = $result_columns;
|
526 |
+
$return_value = 0;
|
527 |
+
if ( $result !== false && isset( $result->{$alias} ) ) {
|
528 |
+
if ( ! \is_numeric( $result->{$alias} ) ) {
|
529 |
+
$return_value = $result->{$alias};
|
530 |
+
} elseif ( (int) $result->{$alias} == (float) $result->{$alias} ) {
|
531 |
+
$return_value = (int) $result->{$alias};
|
532 |
+
} else {
|
533 |
+
$return_value = (float) $result->{$alias};
|
534 |
+
}
|
535 |
+
}
|
536 |
+
|
537 |
+
return $return_value;
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* This method can be called to hydrate (populate) this
|
542 |
+
* instance of the class from an associative array of data.
|
543 |
+
* This will usually be called only from inside the class,
|
544 |
+
* but it's public in case you need to call it directly.
|
545 |
+
*
|
546 |
+
* @param array $data Data to populate table.
|
547 |
+
*
|
548 |
+
* @return ORM
|
549 |
+
*/
|
550 |
+
public function hydrate( $data = [] ) {
|
551 |
+
$this->_data = $data;
|
552 |
+
|
553 |
+
return $this;
|
554 |
+
}
|
555 |
+
|
556 |
+
/**
|
557 |
+
* Force the ORM to flag all the fields in the $data array
|
558 |
+
* as "dirty" and therefore update them when save() is called.
|
559 |
+
*
|
560 |
+
* @return ORM
|
561 |
+
*/
|
562 |
+
public function force_all_dirty() {
|
563 |
+
$this->_dirty_fields = $this->_data;
|
564 |
+
|
565 |
+
return $this;
|
566 |
+
}
|
567 |
+
|
568 |
+
/**
|
569 |
+
* Perform a raw query. The query can contain placeholders in
|
570 |
+
* either named or question mark style. If placeholders are
|
571 |
+
* used, the parameters should be an array of values which will
|
572 |
+
* be bound to the placeholders in the query. If this method
|
573 |
+
* is called, all other query building methods will be ignored.
|
574 |
+
*
|
575 |
+
* @param array $query The query.
|
576 |
+
* @param array $parameters
|
577 |
+
*
|
578 |
+
* @return ORM
|
579 |
+
*/
|
580 |
+
public function raw_query( $query, $parameters = [] ) {
|
581 |
+
$this->_is_raw_query = true;
|
582 |
+
$this->_raw_query = $query;
|
583 |
+
$this->_raw_parameters = $parameters;
|
584 |
+
|
585 |
+
return $this;
|
586 |
+
}
|
587 |
+
|
588 |
+
/**
|
589 |
+
* Add an alias for the main table to be used in SELECT queries
|
590 |
+
*
|
591 |
+
* @param string $alias
|
592 |
+
*
|
593 |
+
* @return ORM
|
594 |
+
*/
|
595 |
+
public function table_alias( $alias ) {
|
596 |
+
$this->_table_alias = $alias;
|
597 |
+
|
598 |
+
return $this;
|
599 |
+
}
|
600 |
+
|
601 |
+
/**
|
602 |
+
* Internal method to add an unquoted expression to the set
|
603 |
+
* of columns returned by the SELECT query. The second optional
|
604 |
+
* argument is the alias to return the expression as.
|
605 |
+
*
|
606 |
+
* @param string $expr
|
607 |
+
* @param null|string $alias
|
608 |
+
*
|
609 |
+
* @return ORM
|
610 |
+
*/
|
611 |
+
protected function _add_result_column( $expr, $alias = null ) {
|
612 |
+
if ( ! \is_null( $alias ) ) {
|
613 |
+
$expr .= ' AS ' . $this->_quote_identifier( $alias );
|
614 |
+
}
|
615 |
+
if ( $this->_using_default_result_columns ) {
|
616 |
+
$this->_result_columns = [ $expr ];
|
617 |
+
$this->_using_default_result_columns = false;
|
618 |
+
} else {
|
619 |
+
$this->_result_columns[] = $expr;
|
620 |
+
}
|
621 |
+
|
622 |
+
return $this;
|
623 |
+
}
|
624 |
+
|
625 |
+
/**
|
626 |
+
* Counts the number of columns that belong to the primary
|
627 |
+
* key and their value is null.
|
628 |
+
*
|
629 |
+
* @return int
|
630 |
+
*
|
631 |
+
* @throws \Exception
|
632 |
+
*/
|
633 |
+
public function count_null_id_columns() {
|
634 |
+
if ( \is_array( $this->_get_id_column_name() ) ) {
|
635 |
+
return \count( \array_filter( $this->id(), 'is_null' ) );
|
636 |
+
} else {
|
637 |
+
return \is_null( $this->id() ) ? 1 : 0;
|
638 |
+
}
|
639 |
+
}
|
640 |
+
|
641 |
+
/**
|
642 |
+
* Add a column to the list of columns returned by the SELECT
|
643 |
+
* query. This defaults to '*'. The second optional argument is
|
644 |
+
* the alias to return the column as.
|
645 |
+
*
|
646 |
+
* @param string $column
|
647 |
+
* @param null|string $alias
|
648 |
+
*
|
649 |
+
* @return ORM
|
650 |
+
*/
|
651 |
+
public function select( $column, $alias = null ) {
|
652 |
+
$column = $this->_quote_identifier( $column );
|
653 |
+
|
654 |
+
return $this->_add_result_column( $column, $alias );
|
655 |
+
}
|
656 |
+
|
657 |
+
/**
|
658 |
+
* Add an unquoted expression to the list of columns returned
|
659 |
+
* by the SELECT query. The second optional argument is
|
660 |
+
* the alias to return the column as.
|
661 |
+
*
|
662 |
+
* @param string $expr
|
663 |
+
* @param null|string $alias
|
664 |
+
*
|
665 |
+
* @return ORM
|
666 |
+
*/
|
667 |
+
public function select_expr( $expr, $alias = null ) {
|
668 |
+
return $this->_add_result_column( $expr, $alias );
|
669 |
+
}
|
670 |
+
|
671 |
+
/**
|
672 |
+
* Add columns to the list of columns returned by the SELECT
|
673 |
+
* query. This defaults to '*'. Many columns can be supplied
|
674 |
+
* as either an array or as a list of parameters to the method.
|
675 |
+
*
|
676 |
+
* Note that the alias must not be numeric - if you want a
|
677 |
+
* numeric alias then prepend it with some alpha chars. eg. a1
|
678 |
+
*
|
679 |
+
* @example select_many(array('column', 'column2', 'column3'), 'column4', 'column5');
|
680 |
+
* @example select_many(array('alias' => 'column', 'column2', 'alias2' => 'column3'), 'column4', 'column5');
|
681 |
+
* @example select_many('column', 'column2', 'column3');
|
682 |
+
*
|
683 |
+
* @return ORM
|
684 |
+
*/
|
685 |
+
public function select_many() {
|
686 |
+
$columns = \func_get_args();
|
687 |
+
if ( ! empty( $columns ) ) {
|
688 |
+
$columns = $this->_normalise_select_many_columns( $columns );
|
689 |
+
foreach ( $columns as $alias => $column ) {
|
690 |
+
if ( \is_numeric( $alias ) ) {
|
691 |
+
$alias = null;
|
692 |
+
}
|
693 |
+
$this->select( $column, $alias );
|
694 |
+
}
|
695 |
+
}
|
696 |
+
|
697 |
+
return $this;
|
698 |
+
}
|
699 |
+
|
700 |
+
/**
|
701 |
+
* Add an unquoted expression to the list of columns returned
|
702 |
+
* by the SELECT query. Many columns can be supplied as either
|
703 |
+
* an array or as a list of parameters to the method.
|
704 |
+
*
|
705 |
+
* Note that the alias must not be numeric - if you want a
|
706 |
+
* numeric alias then prepend it with some alpha chars. eg. a1
|
707 |
+
*
|
708 |
+
* @return ORM
|
709 |
+
* @example select_many_expr(array('column', 'column2', 'column3'), 'column4', 'column5')
|
710 |
+
* @example select_many_expr(array('alias' => 'column', 'column2', 'alias2' => 'column3'), 'column4', 'column5')
|
711 |
+
*
|
712 |
+
* @example select_many_expr('column', 'column2', 'column3')
|
713 |
+
*/
|
714 |
+
public function select_many_expr() {
|
715 |
+
$columns = \func_get_args();
|
716 |
+
if ( ! empty( $columns ) ) {
|
717 |
+
$columns = $this->_normalise_select_many_columns( $columns );
|
718 |
+
foreach ( $columns as $alias => $column ) {
|
719 |
+
if ( \is_numeric( $alias ) ) {
|
720 |
+
$alias = null;
|
721 |
+
}
|
722 |
+
$this->select_expr( $column, $alias );
|
723 |
+
}
|
724 |
+
}
|
725 |
+
|
726 |
+
return $this;
|
727 |
+
}
|
728 |
+
|
729 |
+
/**
|
730 |
+
* Take a column specification for the select many methods and convert it
|
731 |
+
* into a normalised array of columns and aliases.
|
732 |
+
*
|
733 |
+
* It is designed to turn the following styles into a normalised array:
|
734 |
+
*
|
735 |
+
* array(array('alias' => 'column', 'column2', 'alias2' => 'column3'), 'column4', 'column5'))
|
736 |
+
*
|
737 |
+
* @param array $columns
|
738 |
+
*
|
739 |
+
* @return array
|
740 |
+
*/
|
741 |
+
protected function _normalise_select_many_columns( $columns ) {
|
742 |
+
$return = [];
|
743 |
+
foreach ( $columns as $column ) {
|
744 |
+
if ( \is_array( $column ) ) {
|
745 |
+
foreach ( $column as $key => $value ) {
|
746 |
+
if ( ! \is_numeric( $key ) ) {
|
747 |
+
$return[ $key ] = $value;
|
748 |
+
} else {
|
749 |
+
$return[] = $value;
|
750 |
+
}
|
751 |
+
}
|
752 |
+
} else {
|
753 |
+
$return[] = $column;
|
754 |
+
}
|
755 |
+
}
|
756 |
+
|
757 |
+
return $return;
|
758 |
+
}
|
759 |
+
|
760 |
+
/**
|
761 |
+
* Add a DISTINCT keyword before the list of columns in the SELECT query
|
762 |
+
*
|
763 |
+
* @return ORM
|
764 |
+
*/
|
765 |
+
public function distinct() {
|
766 |
+
$this->_distinct = true;
|
767 |
+
|
768 |
+
return $this;
|
769 |
+
}
|
770 |
+
|
771 |
+
/**
|
772 |
+
* Internal method to add a JOIN source to the query.
|
773 |
+
*
|
774 |
+
* The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this
|
775 |
+
* will be prepended to JOIN.
|
776 |
+
*
|
777 |
+
* The table should be the name of the table to join to.
|
778 |
+
*
|
779 |
+
* The constraint may be either a string or an array with three elements. If it
|
780 |
+
* is a string, it will be compiled into the query as-is, with no escaping. The
|
781 |
+
* recommended way to supply the constraint is as an array with three elements:
|
782 |
+
*
|
783 |
+
* first_column, operator, second_column
|
784 |
+
*
|
785 |
+
* Example: array('user.id', '=', 'profile.user_id')
|
786 |
+
*
|
787 |
+
* will compile to
|
788 |
+
*
|
789 |
+
* ON `user`.`id` = `profile`.`user_id`
|
790 |
+
*
|
791 |
+
* The final (optional) argument specifies an alias for the joined table.
|
792 |
+
*
|
793 |
+
* @param string $join_operator
|
794 |
+
* @param string $table
|
795 |
+
* @param string $constraint
|
796 |
+
* @param null $table_alias
|
797 |
+
*
|
798 |
+
* @return ORM
|
799 |
+
*/
|
800 |
+
protected function _add_join_source( $join_operator, $table, $constraint, $table_alias = null ) {
|
801 |
+
$join_operator = \trim( "{$join_operator} JOIN" );
|
802 |
+
$table = $this->_quote_identifier( $table );
|
803 |
+
// Add table alias if present
|
804 |
+
if ( ! \is_null( $table_alias ) ) {
|
805 |
+
$table_alias = $this->_quote_identifier( $table_alias );
|
806 |
+
$table .= " {$table_alias}";
|
807 |
+
}
|
808 |
+
// Build the constraint
|
809 |
+
if ( \is_array( $constraint ) ) {
|
810 |
+
list( $first_column, $operator, $second_column ) = $constraint;
|
811 |
+
$first_column = $this->_quote_identifier( $first_column );
|
812 |
+
$second_column = $this->_quote_identifier( $second_column );
|
813 |
+
$constraint = "{$first_column} {$operator} {$second_column}";
|
814 |
+
}
|
815 |
+
$this->_join_sources[] = "{$join_operator} {$table} ON {$constraint}";
|
816 |
+
|
817 |
+
return $this;
|
818 |
+
}
|
819 |
+
|
820 |
+
/**
|
821 |
+
* Add a RAW JOIN source to the query
|
822 |
+
*
|
823 |
+
* @param string $table
|
824 |
+
* @param string $constraint
|
825 |
+
* @param string $table_alias
|
826 |
+
* @param array $parameters
|
827 |
+
*
|
828 |
+
* @return ORM
|
829 |
+
*/
|
830 |
+
public function raw_join( $table, $constraint, $table_alias, $parameters = [] ) {
|
831 |
+
// Add table alias if present
|
832 |
+
if ( ! \is_null( $table_alias ) ) {
|
833 |
+
$table_alias = $this->_quote_identifier( $table_alias );
|
834 |
+
$table .= " {$table_alias}";
|
835 |
+
}
|
836 |
+
$this->_values = \array_merge( $this->_values, $parameters );
|
837 |
+
// Build the constraint
|
838 |
+
if ( \is_array( $constraint ) ) {
|
839 |
+
list( $first_column, $operator, $second_column ) = $constraint;
|
840 |
+
$first_column = $this->_quote_identifier( $first_column );
|
841 |
+
$second_column = $this->_quote_identifier( $second_column );
|
842 |
+
$constraint = "{$first_column} {$operator} {$second_column}";
|
843 |
+
}
|
844 |
+
$this->_join_sources[] = "{$table} ON {$constraint}";
|
845 |
+
|
846 |
+
return $this;
|
847 |
+
}
|
848 |
+
|
849 |
+
/**
|
850 |
+
* Add a simple JOIN source to the query
|
851 |
+
*
|
852 |
+
* @param string $table
|
853 |
+
* @param string $constraint
|
854 |
+
* @param null $table_alias
|
855 |
+
*
|
856 |
+
* @return ORM
|
857 |
+
*/
|
858 |
+
public function join( $table, $constraint, $table_alias = null ) {
|
859 |
+
return $this->_add_join_source( '', $table, $constraint, $table_alias );
|
860 |
+
}
|
861 |
+
|
862 |
+
/**
|
863 |
+
* Add an INNER JOIN souce to the query
|
864 |
+
*
|
865 |
+
* @param string $table
|
866 |
+
* @param string $constraint
|
867 |
+
* @param null $table_alias
|
868 |
+
*
|
869 |
+
* @return ORM
|
870 |
+
*/
|
871 |
+
public function inner_join( $table, $constraint, $table_alias = null ) {
|
872 |
+
return $this->_add_join_source( 'INNER', $table, $constraint, $table_alias );
|
873 |
+
}
|
874 |
+
|
875 |
+
/**
|
876 |
+
* Add a LEFT OUTER JOIN souce to the query
|
877 |
+
*
|
878 |
+
* @param string $table
|
879 |
+
* @param string $constraint
|
880 |
+
* @param null $table_alias
|
881 |
+
*
|
882 |
+
* @return ORM
|
883 |
+
*/
|
884 |
+
public function left_outer_join( $table, $constraint, $table_alias = null ) {
|
885 |
+
return $this->_add_join_source( 'LEFT OUTER', $table, $constraint, $table_alias );
|
886 |
+
}
|
887 |
+
|
888 |
+
/**
|
889 |
+
* Add an RIGHT OUTER JOIN souce to the query
|
890 |
+
*
|
891 |
+
* @param string $table
|
892 |
+
* @param string $constraint
|
893 |
+
* @param null $table_alias
|
894 |
+
*
|
895 |
+
* @return ORM
|
896 |
+
*/
|
897 |
+
public function right_outer_join( $table, $constraint, $table_alias = null ) {
|
898 |
+
return $this->_add_join_source( 'RIGHT OUTER', $table, $constraint, $table_alias );
|
899 |
+
}
|
900 |
+
|
901 |
+
/**
|
902 |
+
* Add an FULL OUTER JOIN souce to the query
|
903 |
+
*
|
904 |
+
* @param string $table
|
905 |
+
* @param string $constraint
|
906 |
+
* @param null $table_alias
|
907 |
+
*
|
908 |
+
* @return ORM
|
909 |
+
*/
|
910 |
+
public function full_outer_join( $table, $constraint, $table_alias = null ) {
|
911 |
+
return $this->_add_join_source( 'FULL OUTER', $table, $constraint, $table_alias );
|
912 |
+
}
|
913 |
+
|
914 |
+
/**
|
915 |
+
* Internal method to add a HAVING condition to the query
|
916 |
+
*
|
917 |
+
* @param string $fragment
|
918 |
+
* @param array $values
|
919 |
+
*
|
920 |
+
* @return ORM
|
921 |
+
*/
|
922 |
+
protected function _add_having( $fragment, $values = [] ) {
|
923 |
+
return $this->_add_condition( 'having', $fragment, $values );
|
924 |
+
}
|
925 |
+
|
926 |
+
/**
|
927 |
+
* Internal method to add a HAVING condition to the query
|
928 |
+
*
|
929 |
+
* @param string $column_name The table column.
|
930 |
+
* @param string $separator
|
931 |
+
* @param $value
|
932 |
+
*
|
933 |
+
* @return ORM
|
934 |
+
*/
|
935 |
+
protected function _add_simple_having( $column_name, $separator, $value ) {
|
936 |
+
return $this->_add_simple_condition( 'having', $column_name, $separator, $value );
|
937 |
+
}
|
938 |
+
|
939 |
+
/**
|
940 |
+
* Internal method to add a HAVING clause with multiple values (like IN and NOT IN)
|
941 |
+
*
|
942 |
+
* @param string|array $column_name The table column.
|
943 |
+
* @param string $separator
|
944 |
+
* @param $values
|
945 |
+
*
|
946 |
+
* @return ORM
|
947 |
+
*/
|
948 |
+
public function _add_having_placeholder( $column_name, $separator, $values ) {
|
949 |
+
if ( ! \is_array( $column_name ) ) {
|
950 |
+
$data = [ $column_name => $values ];
|
951 |
+
} else {
|
952 |
+
$data = $column_name;
|
953 |
+
}
|
954 |
+
$result = $this;
|
955 |
+
foreach ( $data as $key => $val ) {
|
956 |
+
$column = $result->_quote_identifier( $key );
|
957 |
+
$placeholders = $result->_create_placeholders( $val );
|
958 |
+
$result = $result->_add_having( "{$column} {$separator} ({$placeholders})", $val );
|
959 |
+
}
|
960 |
+
|
961 |
+
return $result;
|
962 |
+
}
|
963 |
+
|
964 |
+
/**
|
965 |
+
* Internal method to add a HAVING clause with no parameters(like IS NULL and IS NOT NULL)
|
966 |
+
*
|
967 |
+
* @param string $column_name
|
968 |
+
* @param $operator
|
969 |
+
*
|
970 |
+
* @return ORM
|
971 |
+
*/
|
972 |
+
public function _add_having_no_value( $column_name, $operator ) {
|
973 |
+
$conditions = \is_array( $column_name ) ? $column_name : [ $column_name ];
|
974 |
+
$result = $this;
|
975 |
+
foreach ( $conditions as $column ) {
|
976 |
+
$column = $this->_quote_identifier( $column );
|
977 |
+
$result = $result->_add_having( "{$column} {$operator}" );
|
978 |
+
}
|
979 |
+
|
980 |
+
return $result;
|
981 |
+
}
|
982 |
+
|
983 |
+
/**
|
984 |
+
* Internal method to add a WHERE condition to the query
|
985 |
+
*
|
986 |
+
* @param string $fragment
|
987 |
+
* @param array $values
|
988 |
+
*
|
989 |
+
* @return ORM
|
990 |
+
*/
|
991 |
+
protected function _add_where( $fragment, $values = [] ) {
|
992 |
+
return $this->_add_condition( 'where', $fragment, $values );
|
993 |
+
}
|
994 |
+
|
995 |
+
/**
|
996 |
+
* Internal method to add a WHERE condition to the query
|
997 |
+
*
|
998 |
+
* @param string|array $column_name The table column
|
999 |
+
* @param string $separator
|
1000 |
+
* @param $value
|
1001 |
+
*
|
1002 |
+
* @return ORM
|
1003 |
+
*/
|
1004 |
+
protected function _add_simple_where( $column_name, $separator, $value ) {
|
1005 |
+
return $this->_add_simple_condition( 'where', $column_name, $separator, $value );
|
1006 |
+
}
|
1007 |
+
|
1008 |
+
/**
|
1009 |
+
* Add a WHERE clause with multiple values (like IN and NOT IN)
|
1010 |
+
*
|
1011 |
+
* @param string|array $column_name The table column
|
1012 |
+
* @param string $separator
|
1013 |
+
* @param $values
|
1014 |
+
*
|
1015 |
+
* @return ORM
|
1016 |
+
*/
|
1017 |
+
public function _add_where_placeholder( $column_name, $separator, $values ) {
|
1018 |
+
if ( ! \is_array( $column_name ) ) {
|
1019 |
+
$data = [ $column_name => $values ];
|
1020 |
+
} else {
|
1021 |
+
$data = $column_name;
|
1022 |
+
}
|
1023 |
+
$result = $this;
|
1024 |
+
foreach ( $data as $key => $val ) {
|
1025 |
+
$column = $result->_quote_identifier( $key );
|
1026 |
+
$placeholders = $result->_create_placeholders( $val );
|
1027 |
+
$result = $result->_add_where( "{$column} {$separator} ({$placeholders})", $val );
|
1028 |
+
}
|
1029 |
+
|
1030 |
+
return $result;
|
1031 |
+
}
|
1032 |
+
|
1033 |
+
/**
|
1034 |
+
* Add a WHERE clause with no parameters(like IS NULL and IS NOT NULL)
|
1035 |
+
*
|
1036 |
+
* @param string $column_name
|
1037 |
+
* @param $operator
|
1038 |
+
*
|
1039 |
+
* @return ORM
|
1040 |
+
*/
|
1041 |
+
public function _add_where_no_value( $column_name, $operator ) {
|
1042 |
+
$conditions = \is_array( $column_name ) ? $column_name : [ $column_name ];
|
1043 |
+
$result = $this;
|
1044 |
+
foreach ( $conditions as $column ) {
|
1045 |
+
$column = $this->_quote_identifier( $column );
|
1046 |
+
$result = $result->_add_where( "{$column} {$operator}" );
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
return $result;
|
1050 |
+
}
|
1051 |
+
|
1052 |
+
/**
|
1053 |
+
* Internal method to add a HAVING or WHERE condition to the query
|
1054 |
+
*
|
1055 |
+
* @param $type
|
1056 |
+
* @param string $fragment
|
1057 |
+
* @param array $values
|
1058 |
+
*
|
1059 |
+
* @return ORM
|
1060 |
+
*/
|
1061 |
+
protected function _add_condition( $type, $fragment, $values = [] ) {
|
1062 |
+
$conditions_class_property_name = "_{$type}_conditions";
|
1063 |
+
if ( ! \is_array( $values ) ) {
|
1064 |
+
$values = [ $values ];
|
1065 |
+
}
|
1066 |
+
\array_push( $this->{$conditions_class_property_name}, [
|
1067 |
+
self::CONDITION_FRAGMENT => $fragment,
|
1068 |
+
self::CONDITION_VALUES => $values,
|
1069 |
+
] );
|
1070 |
+
|
1071 |
+
return $this;
|
1072 |
+
}
|
1073 |
+
|
1074 |
+
/**
|
1075 |
+
* Helper method to compile a simple COLUMN SEPARATOR VALUE
|
1076 |
+
* style HAVING or WHERE condition into a string and value ready to
|
1077 |
+
* be passed to the _add_condition method. Avoids duplication
|
1078 |
+
* of the call to _quote_identifier
|
1079 |
+
*
|
1080 |
+
* If column_name is an associative array, it will add a condition for each column
|
1081 |
+
*
|
1082 |
+
* @param $type
|
1083 |
+
* @param string|array $column_name The table column
|
1084 |
+
* @param string $separator
|
1085 |
+
* @param $value
|
1086 |
+
*
|
1087 |
+
* @return ORM
|
1088 |
+
*/
|
1089 |
+
protected function _add_simple_condition( $type, $column_name, $separator, $value ) {
|
1090 |
+
$multiple = \is_array( $column_name ) ? $column_name : [ $column_name => $value ];
|
1091 |
+
$result = $this;
|
1092 |
+
foreach ( $multiple as $key => $val ) {
|
1093 |
+
// Add the table name in case of ambiguous columns
|
1094 |
+
if ( \count( $result->_join_sources ) > 0 && \strpos( $key, '.' ) === false ) {
|
1095 |
+
$table = $result->_table_name;
|
1096 |
+
if ( ! \is_null( $result->_table_alias ) ) {
|
1097 |
+
$table = $result->_table_alias;
|
1098 |
+
}
|
1099 |
+
$key = "{$table}.{$key}";
|
1100 |
+
}
|
1101 |
+
$key = $result->_quote_identifier( $key );
|
1102 |
+
$placeholder = '%s';
|
1103 |
+
$result = $result->_add_condition( $type, "{$key} {$separator} {$placeholder}", $val );
|
1104 |
+
}
|
1105 |
+
|
1106 |
+
return $result;
|
1107 |
+
}
|
1108 |
+
|
1109 |
+
/**
|
1110 |
+
* Return a string containing the given number of question marks,
|
1111 |
+
* separated by commas. Eg "?, ?, ?"
|
1112 |
+
*
|
1113 |
+
* @param array $fields Fields to create placeholder for.
|
1114 |
+
*
|
1115 |
+
* @return string
|
1116 |
+
*/
|
1117 |
+
protected function _create_placeholders( $fields ) {
|
1118 |
+
if ( ! empty( $fields ) ) {
|
1119 |
+
$db_fields = [];
|
1120 |
+
foreach ( $fields as $key => $value ) {
|
1121 |
+
// Process expression fields directly into the query
|
1122 |
+
if ( \array_key_exists( $key, $this->_expr_fields ) ) {
|
1123 |
+
$db_fields[] = $value;
|
1124 |
+
} else {
|
1125 |
+
$db_fields[] = '%s';
|
1126 |
+
}
|
1127 |
+
}
|
1128 |
+
|
1129 |
+
return \implode( ', ', $db_fields );
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
return '';
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
/**
|
1136 |
+
* Helper method that filters a column/value array returning only those
|
1137 |
+
* columns that belong to a compound primary key.
|
1138 |
+
*
|
1139 |
+
* If the key contains a column that does not exist in the given array,
|
1140 |
+
* a null value will be returned for it.
|
1141 |
+
*
|
1142 |
+
* @param $value
|
1143 |
+
*
|
1144 |
+
* @return array
|
1145 |
+
*/
|
1146 |
+
protected function _get_compound_id_column_values( $value ) {
|
1147 |
+
$filtered = [];
|
1148 |
+
foreach ( $this->_get_id_column_name() as $key ) {
|
1149 |
+
$filtered[ $key ] = isset( $value[ $key ] ) ? $value[ $key ] : null;
|
1150 |
+
}
|
1151 |
+
|
1152 |
+
return $filtered;
|
1153 |
+
}
|
1154 |
+
|
1155 |
+
/**
|
1156 |
+
* Helper method that filters an array containing compound column/value
|
1157 |
+
* arrays.
|
1158 |
+
*
|
1159 |
+
* @param $values
|
1160 |
+
*
|
1161 |
+
* @return array
|
1162 |
+
*/
|
1163 |
+
protected function _get_compound_id_column_values_array( $values ) {
|
1164 |
+
$filtered = [];
|
1165 |
+
foreach ( $values as $value ) {
|
1166 |
+
$filtered[] = $this->_get_compound_id_column_values( $value );
|
1167 |
+
}
|
1168 |
+
|
1169 |
+
return $filtered;
|
1170 |
+
}
|
1171 |
+
|
1172 |
+
/**
|
1173 |
+
* Add a WHERE column = value clause to your query. Each time
|
1174 |
+
* this is called in the chain, an additional WHERE will be
|
1175 |
+
* added, and these will be ANDed together when the final query
|
1176 |
+
* is built.
|
1177 |
+
*
|
1178 |
+
* If you use an array in $column_name, a new clause will be
|
1179 |
+
* added for each element. In this case, $value is ignored.
|
1180 |
+
*
|
1181 |
+
* @param string|array $column_name The table column
|
1182 |
+
* @param null $value
|
1183 |
+
*
|
1184 |
+
* @return ORM
|
1185 |
+
*/
|
1186 |
+
public function where( $column_name, $value = null ) {
|
1187 |
+
return $this->where_equal( $column_name, $value );
|
1188 |
+
}
|
1189 |
+
|
1190 |
+
/**
|
1191 |
+
* More explicitly named version of for the where() method.
|
1192 |
+
* Can be used if preferred.
|
1193 |
+
*
|
1194 |
+
* @param string|array $column_name The table column
|
1195 |
+
* @param null $value
|
1196 |
+
*
|
1197 |
+
* @return ORM
|
1198 |
+
*/
|
1199 |
+
public function where_equal( $column_name, $value = null ) {
|
1200 |
+
return $this->_add_simple_where( $column_name, '=', $value );
|
1201 |
+
}
|
1202 |
+
|
1203 |
+
/**
|
1204 |
+
* Add a WHERE column != value clause to your query.
|
1205 |
+
*
|
1206 |
+
* @param string|array $column_name The table column
|
1207 |
+
* @param null $value
|
1208 |
+
*
|
1209 |
+
* @return ORM
|
1210 |
+
*/
|
1211 |
+
public function where_not_equal( $column_name, $value = null ) {
|
1212 |
+
return $this->_add_simple_where( $column_name, '!=', $value );
|
1213 |
+
}
|
1214 |
+
|
1215 |
+
/**
|
1216 |
+
* Special method to query the table by its primary key
|
1217 |
+
*
|
1218 |
+
* If primary key is compound, only the columns that
|
1219 |
+
* belong to they key will be used for the query
|
1220 |
+
*
|
1221 |
+
* @param $id
|
1222 |
+
*
|
1223 |
+
* @return ORM
|
1224 |
+
*/
|
1225 |
+
public function where_id_is( $id ) {
|
1226 |
+
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 );
|
1227 |
+
}
|
1228 |
+
|
1229 |
+
/**
|
1230 |
+
* Allows adding a WHERE clause that matches any of the conditions
|
1231 |
+
* specified in the array. Each element in the associative array will
|
1232 |
+
* be a different condition, where the key will be the column name.
|
1233 |
+
*
|
1234 |
+
* By default, an equal operator will be used against all columns, but
|
1235 |
+
* it can be overriden for any or every column using the second parameter.
|
1236 |
+
*
|
1237 |
+
* Each condition will be ORed together when added to the final query.
|
1238 |
+
*
|
1239 |
+
* @param $values
|
1240 |
+
* @param string $operator
|
1241 |
+
*
|
1242 |
+
* @return ORM
|
1243 |
+
*/
|
1244 |
+
public function where_any_is( $values, $operator = '=' ) {
|
1245 |
+
$data = [];
|
1246 |
+
$query = [ '((' ];
|
1247 |
+
$first = true;
|
1248 |
+
foreach ( $values as $value ) {
|
1249 |
+
if ( $first ) {
|
1250 |
+
$first = false;
|
1251 |
+
} else {
|
1252 |
+
$query[] = ') OR (';
|
1253 |
+
}
|
1254 |
+
$firstsub = true;
|
1255 |
+
foreach ( $value as $key => $item ) {
|
1256 |
+
$op = \is_string( $operator ) ? $operator : ( isset( $operator[ $key ] ) ? $operator[ $key ] : '=' );
|
1257 |
+
if ( $firstsub ) {
|
1258 |
+
$firstsub = false;
|
1259 |
+
} else {
|
1260 |
+
$query[] = 'AND';
|
1261 |
+
}
|
1262 |
+
$query[] = $this->_quote_identifier( $key );
|
1263 |
+
$data[] = $item;
|
1264 |
+
$query[] = $op . '%s';
|
1265 |
+
}
|
1266 |
+
}
|
1267 |
+
$query[] = '))';
|
1268 |
+
|
1269 |
+
return $this->where_raw( \join( $query, ' ' ), $data );
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
/**
|
1273 |
+
* Similar to where_id_is() but allowing multiple primary keys.
|
1274 |
+
*
|
1275 |
+
* If primary key is compound, only the columns that
|
1276 |
+
* belong to they key will be used for the query
|
1277 |
+
*
|
1278 |
+
* @param $ids
|
1279 |
+
*
|
1280 |
+
* @return ORM
|
1281 |
+
*/
|
1282 |
+
public function where_id_in( $ids ) {
|
1283 |
+
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 );
|
1284 |
+
}
|
1285 |
+
|
1286 |
+
/**
|
1287 |
+
* Add a WHERE ... LIKE clause to your query.
|
1288 |
+
*
|
1289 |
+
* @param string|array $column_name The table column
|
1290 |
+
* @param null $value
|
1291 |
+
*
|
1292 |
+
* @return ORM
|
1293 |
+
*/
|
1294 |
+
public function where_like( $column_name, $value = null ) {
|
1295 |
+
return $this->_add_simple_where( $column_name, 'LIKE', $value );
|
1296 |
+
}
|
1297 |
+
|
1298 |
+
/**
|
1299 |
+
* Add where WHERE ... NOT LIKE clause to your query.
|
1300 |
+
*
|
1301 |
+
* @param string|array $column_name The table column
|
1302 |
+
* @param null $value
|
1303 |
+
*
|
1304 |
+
* @return ORM
|
1305 |
+
*/
|
1306 |
+
public function where_not_like( $column_name, $value = null ) {
|
1307 |
+
return $this->_add_simple_where( $column_name, 'NOT LIKE', $value );
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
/**
|
1311 |
+
* Add a WHERE ... > clause to your query
|
1312 |
+
*
|
1313 |
+
* @param string|array $column_name The table column
|
1314 |
+
* @param null $value
|
1315 |
+
*
|
1316 |
+
* @return ORM
|
1317 |
+
*/
|
1318 |
+
public function where_gt( $column_name, $value = null ) {
|
1319 |
+
return $this->_add_simple_where( $column_name, '>', $value );
|
1320 |
+
}
|
1321 |
+
|
1322 |
+
/**
|
1323 |
+
* Add a WHERE ... < clause to your query
|
1324 |
+
*
|
1325 |
+
* @param string|array $column_name The table column
|
1326 |
+
* @param null $value
|
1327 |
+
*
|
1328 |
+
* @return ORM
|
1329 |
+
*/
|
1330 |
+
public function where_lt( $column_name, $value = null ) {
|
1331 |
+
return $this->_add_simple_where( $column_name, '<', $value );
|
1332 |
+
}
|
1333 |
+
|
1334 |
+
/**
|
1335 |
+
* Add a WHERE ... >= clause to your query
|
1336 |
+
*
|
1337 |
+
* @param string|array $column_name The table column
|
1338 |
+
* @param null $value
|
1339 |
+
*
|
1340 |
+
* @return ORM
|
1341 |
+
*/
|
1342 |
+
public function where_gte( $column_name, $value = null ) {
|
1343 |
+
return $this->_add_simple_where( $column_name, '>=', $value );
|
1344 |
+
}
|
1345 |
+
|
1346 |
+
/**
|
1347 |
+
* Add a WHERE ... <= clause to your query
|
1348 |
+
*
|
1349 |
+
* @param string|array $column_name The table column
|
1350 |
+
* @param null $value
|
1351 |
+
*
|
1352 |
+
* @return ORM
|
1353 |
+
*/
|
1354 |
+
public function where_lte( $column_name, $value = null ) {
|
1355 |
+
return $this->_add_simple_where( $column_name, '<=', $value );
|
1356 |
+
}
|
1357 |
+
|
1358 |
+
/**
|
1359 |
+
* Add a WHERE ... IN clause to your query
|
1360 |
+
*
|
1361 |
+
* @param string|array $column_name The table column
|
1362 |
+
* @param $values
|
1363 |
+
*
|
1364 |
+
* @return ORM
|
1365 |
+
*/
|
1366 |
+
public function where_in( $column_name, $values ) {
|
1367 |
+
return $this->_add_where_placeholder( $column_name, 'IN', $values );
|
1368 |
+
}
|
1369 |
+
|
1370 |
+
/**
|
1371 |
+
* Add a WHERE ... NOT IN clause to your query
|
1372 |
+
*
|
1373 |
+
* @param string|array $column_name The table column
|
1374 |
+
* @param $values
|
1375 |
+
*
|
1376 |
+
* @return ORM
|
1377 |
+
*/
|
1378 |
+
public function where_not_in( $column_name, $values ) {
|
1379 |
+
return $this->_add_where_placeholder( $column_name, 'NOT IN', $values );
|
1380 |
+
}
|
1381 |
+
|
1382 |
+
/**
|
1383 |
+
* Add a WHERE column IS NULL clause to your query
|
1384 |
+
*
|
1385 |
+
* @param string|array $column_name The table column
|
1386 |
+
*
|
1387 |
+
* @return ORM
|
1388 |
+
*/
|
1389 |
+
public function where_null( $column_name ) {
|
1390 |
+
return $this->_add_where_no_value( $column_name, 'IS NULL' );
|
1391 |
+
}
|
1392 |
+
|
1393 |
+
/**
|
1394 |
+
* Add a WHERE column IS NOT NULL clause to your query
|
1395 |
+
*
|
1396 |
+
* @param string|array $column_name The table column
|
1397 |
+
*
|
1398 |
+
* @return ORM
|
1399 |
+
*/
|
1400 |
+
public function where_not_null( $column_name ) {
|
1401 |
+
return $this->_add_where_no_value( $column_name, 'IS NOT NULL' );
|
1402 |
+
}
|
1403 |
+
|
1404 |
+
/**
|
1405 |
+
* Add a raw WHERE clause to the query. The clause should
|
1406 |
+
* contain question mark placeholders, which will be bound
|
1407 |
+
* to the parameters supplied in the second argument.
|
1408 |
+
*
|
1409 |
+
* @param $clause
|
1410 |
+
* @param array $parameters
|
1411 |
+
*
|
1412 |
+
* @return ORM
|
1413 |
+
*/
|
1414 |
+
public function where_raw( $clause, $parameters = [] ) {
|
1415 |
+
return $this->_add_where( $clause, $parameters );
|
1416 |
+
}
|
1417 |
+
|
1418 |
+
/**
|
1419 |
+
* Add a LIMIT to the query
|
1420 |
+
*
|
1421 |
+
* @param $limit
|
1422 |
+
*
|
1423 |
+
* @return ORM
|
1424 |
+
*/
|
1425 |
+
public function limit( $limit ) {
|
1426 |
+
$this->_limit = $limit;
|
1427 |
+
|
1428 |
+
return $this;
|
1429 |
+
}
|
1430 |
+
|
1431 |
+
/**
|
1432 |
+
* Add an OFFSET to the query
|
1433 |
+
*
|
1434 |
+
* @param $offset
|
1435 |
+
*
|
1436 |
+
* @return ORM
|
1437 |
+
*/
|
1438 |
+
public function offset( $offset ) {
|
1439 |
+
$this->_offset = $offset;
|
1440 |
+
|
1441 |
+
return $this;
|
1442 |
+
}
|
1443 |
+
|
1444 |
+
/**
|
1445 |
+
* Add an ORDER BY clause to the query
|
1446 |
+
*
|
1447 |
+
* @param string $column_name
|
1448 |
+
* @param $ordering
|
1449 |
+
*
|
1450 |
+
* @return ORM
|
1451 |
+
*/
|
1452 |
+
protected function _add_order_by( $column_name, $ordering ) {
|
1453 |
+
$column_name = $this->_quote_identifier( $column_name );
|
1454 |
+
$this->_order_by[] = "{$column_name} {$ordering}";
|
1455 |
+
|
1456 |
+
return $this;
|
1457 |
+
}
|
1458 |
+
|
1459 |
+
/**
|
1460 |
+
* Add an ORDER BY column DESC clause
|
1461 |
+
*
|
1462 |
+
* @param string|array $column_name The table column
|
1463 |
+
*
|
1464 |
+
* @return ORM
|
1465 |
+
*/
|
1466 |
+
public function order_by_desc( $column_name ) {
|
1467 |
+
return $this->_add_order_by( $column_name, 'DESC' );
|
1468 |
+
}
|
1469 |
+
|
1470 |
+
/**
|
1471 |
+
* Add an ORDER BY column ASC clause
|
1472 |
+
*
|
1473 |
+
* @param string|array $column_name The table column
|
1474 |
+
*
|
1475 |
+
* @return ORM
|
1476 |
+
*/
|
1477 |
+
public function order_by_asc( $column_name ) {
|
1478 |
+
return $this->_add_order_by( $column_name, 'ASC' );
|
1479 |
+
}
|
1480 |
+
|
1481 |
+
/**
|
1482 |
+
* Add an unquoted expression as an ORDER BY clause
|
1483 |
+
*
|
1484 |
+
* @param $clause
|
1485 |
+
*
|
1486 |
+
* @return ORM
|
1487 |
+
*/
|
1488 |
+
public function order_by_expr( $clause ) {
|
1489 |
+
$this->_order_by[] = $clause;
|
1490 |
+
|
1491 |
+
return $this;
|
1492 |
+
}
|
1493 |
+
|
1494 |
+
/**
|
1495 |
+
* Add a column to the list of columns to GROUP BY
|
1496 |
+
*
|
1497 |
+
* @param string|array $column_name The table column
|
1498 |
+
*
|
1499 |
+
* @return ORM
|
1500 |
+
*/
|
1501 |
+
public function group_by( $column_name ) {
|
1502 |
+
$column_name = $this->_quote_identifier( $column_name );
|
1503 |
+
$this->_group_by[] = $column_name;
|
1504 |
+
|
1505 |
+
return $this;
|
1506 |
+
}
|
1507 |
+
|
1508 |
+
/**
|
1509 |
+
* Add an unquoted expression to the list of columns to GROUP BY
|
1510 |
+
*
|
1511 |
+
* @param string $expr
|
1512 |
+
*
|
1513 |
+
* @return ORM
|
1514 |
+
*/
|
1515 |
+
public function group_by_expr( $expr ) {
|
1516 |
+
$this->_group_by[] = $expr;
|
1517 |
+
|
1518 |
+
return $this;
|
1519 |
+
}
|
1520 |
+
|
1521 |
+
/**
|
1522 |
+
* Add a HAVING column = value clause to your query. Each time
|
1523 |
+
* this is called in the chain, an additional HAVING will be
|
1524 |
+
* added, and these will be ANDed together when the final query
|
1525 |
+
* is built.
|
1526 |
+
*
|
1527 |
+
* If you use an array in $column_name, a new clause will be
|
1528 |
+
* added for each element. In this case, $value is ignored.
|
1529 |
+
*
|
1530 |
+
* @param string|array $column_name The table column
|
1531 |
+
* @param null $value
|
1532 |
+
*
|
1533 |
+
* @return ORM
|
1534 |
+
*/
|
1535 |
+
public function having( $column_name, $value = null ) {
|
1536 |
+
return $this->having_equal( $column_name, $value );
|
1537 |
+
}
|
1538 |
+
|
1539 |
+
/**
|
1540 |
+
* More explicitly named version of for the having() method.
|
1541 |
+
* Can be used if preferred.
|
1542 |
+
*
|
1543 |
+
* @param string|array $column_name The table column
|
1544 |
+
* @param null $value
|
1545 |
+
*
|
1546 |
+
* @return ORM
|
1547 |
+
*/
|
1548 |
+
public function having_equal( $column_name, $value = null ) {
|
1549 |
+
return $this->_add_simple_having( $column_name, '=', $value );
|
1550 |
+
}
|
1551 |
+
|
1552 |
+
/**
|
1553 |
+
* Add a HAVING column != value clause to your query.
|
1554 |
+
*
|
1555 |
+
* @param string|array $column_name The table column
|
1556 |
+
* @param null $value
|
1557 |
+
*
|
1558 |
+
* @return ORM
|
1559 |
+
*/
|
1560 |
+
public function having_not_equal( $column_name, $value = null ) {
|
1561 |
+
return $this->_add_simple_having( $column_name, '!=', $value );
|
1562 |
+
}
|
1563 |
+
|
1564 |
+
/**
|
1565 |
+
* Special method to query the table by its primary key.
|
1566 |
+
*
|
1567 |
+
* If primary key is compound, only the columns that
|
1568 |
+
* belong to they key will be used for the query
|
1569 |
+
*
|
1570 |
+
* @param $id
|
1571 |
+
*
|
1572 |
+
* @return ORM
|
1573 |
+
*/
|
1574 |
+
public function having_id_is( $id ) {
|
1575 |
+
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 );
|
1576 |
+
}
|
1577 |
+
|
1578 |
+
/**
|
1579 |
+
* Add a HAVING ... LIKE clause to your query.
|
1580 |
+
*
|
1581 |
+
* @param string|array $column_name The table column
|
1582 |
+
* @param null $value
|
1583 |
+
*
|
1584 |
+
* @return ORM
|
1585 |
+
*/
|
1586 |
+
public function having_like( $column_name, $value = null ) {
|
1587 |
+
return $this->_add_simple_having( $column_name, 'LIKE', $value );
|
1588 |
+
}
|
1589 |
+
|
1590 |
+
/**
|
1591 |
+
* Add where HAVING ... NOT LIKE clause to your query.
|
1592 |
+
*
|
1593 |
+
* @param string|array $column_name The table column
|
1594 |
+
* @param null $value
|
1595 |
+
*
|
1596 |
+
* @return ORM
|
1597 |
+
*/
|
1598 |
+
public function having_not_like( $column_name, $value = null ) {
|
1599 |
+
return $this->_add_simple_having( $column_name, 'NOT LIKE', $value );
|
1600 |
+
}
|
1601 |
+
|
1602 |
+
/**
|
1603 |
+
* Add a HAVING ... > clause to your query
|
1604 |
+
*
|
1605 |
+
* @param string|array $column_name The table column
|
1606 |
+
* @param null $value
|
1607 |
+
*
|
1608 |
+
* @return ORM
|
1609 |
+
*/
|
1610 |
+
public function having_gt( $column_name, $value = null ) {
|
1611 |
+
return $this->_add_simple_having( $column_name, '>', $value );
|
1612 |
+
}
|
1613 |
+
|
1614 |
+
/**
|
1615 |
+
* Add a HAVING ... < clause to your query
|
1616 |
+
*
|
1617 |
+
* @param string|array $column_name The table column
|
1618 |
+
* @param null $value
|
1619 |
+
*
|
1620 |
+
* @return ORM
|
1621 |
+
*/
|
1622 |
+
public function having_lt( $column_name, $value = null ) {
|
1623 |
+
return $this->_add_simple_having( $column_name, '<', $value );
|
1624 |
+
}
|
1625 |
+
|
1626 |
+
/**
|
1627 |
+
* Add a HAVING ... >= clause to your query
|
1628 |
+
*
|
1629 |
+
* @param string|array $column_name The table column
|
1630 |
+
* @param null $value
|
1631 |
+
*
|
1632 |
+
* @return ORM
|
1633 |
+
*/
|
1634 |
+
public function having_gte( $column_name, $value = null ) {
|
1635 |
+
return $this->_add_simple_having( $column_name, '>=', $value );
|
1636 |
+
}
|
1637 |
+
|
1638 |
+
/**
|
1639 |
+
* Add a HAVING ... <= clause to your query
|
1640 |
+
*
|
1641 |
+
* @param string|array $column_name The table column
|
1642 |
+
* @param null $value
|
1643 |
+
*
|
1644 |
+
* @return ORM
|
1645 |
+
*/
|
1646 |
+
public function having_lte( $column_name, $value = null ) {
|
1647 |
+
return $this->_add_simple_having( $column_name, '<=', $value );
|
1648 |
+
}
|
1649 |
+
|
1650 |
+
/**
|
1651 |
+
* Add a HAVING ... IN clause to your query
|
1652 |
+
*
|
1653 |
+
* @param string|array $column_name The table column
|
1654 |
+
* @param null $values
|
1655 |
+
*
|
1656 |
+
* @return ORM
|
1657 |
+
*/
|
1658 |
+
public function having_in( $column_name, $values = null ) {
|
1659 |
+
return $this->_add_having_placeholder( $column_name, 'IN', $values );
|
1660 |
+
}
|
1661 |
+
|
1662 |
+
/**
|
1663 |
+
* Add a HAVING ... NOT IN clause to your query
|
1664 |
+
*
|
1665 |
+
* @param string|array $column_name The table column
|
1666 |
+
* @param null $values
|
1667 |
+
*
|
1668 |
+
* @return ORM
|
1669 |
+
*/
|
1670 |
+
public function having_not_in( $column_name, $values = null ) {
|
1671 |
+
return $this->_add_having_placeholder( $column_name, 'NOT IN', $values );
|
1672 |
+
}
|
1673 |
+
|
1674 |
+
/**
|
1675 |
+
* Add a HAVING column IS NULL clause to your query
|
1676 |
+
*
|
1677 |
+
* @param string|array $column_name The table column
|
1678 |
+
*
|
1679 |
+
* @return ORM
|
1680 |
+
*/
|
1681 |
+
public function having_null( $column_name ) {
|
1682 |
+
return $this->_add_having_no_value( $column_name, 'IS NULL' );
|
1683 |
+
}
|
1684 |
+
|
1685 |
+
/**
|
1686 |
+
* Add a HAVING column IS NOT NULL clause to your query
|
1687 |
+
*
|
1688 |
+
* @param string|array $column_name The table column
|
1689 |
+
*
|
1690 |
+
* @return ORM
|
1691 |
+
*/
|
1692 |
+
public function having_not_null( $column_name ) {
|
1693 |
+
return $this->_add_having_no_value( $column_name, 'IS NOT NULL' );
|
1694 |
+
}
|
1695 |
+
|
1696 |
+
/**
|
1697 |
+
* Add a raw HAVING clause to the query. The clause should
|
1698 |
+
* contain question mark placeholders, which will be bound
|
1699 |
+
* to the parameters supplied in the second argument.
|
1700 |
+
*
|
1701 |
+
* @param $clause
|
1702 |
+
* @param array $parameters
|
1703 |
+
*
|
1704 |
+
* @return ORM
|
1705 |
+
*/
|
1706 |
+
public function having_raw( $clause, $parameters = [] ) {
|
1707 |
+
return $this->_add_having( $clause, $parameters );
|
1708 |
+
}
|
1709 |
+
|
1710 |
+
/**
|
1711 |
+
* Build a SELECT statement based on the clauses that have
|
1712 |
+
* been passed to this instance by chaining method calls.
|
1713 |
+
*
|
1714 |
+
* @return string
|
1715 |
+
*/
|
1716 |
+
protected function _build_select() {
|
1717 |
+
// If the query is raw, just set the $this->_values to be
|
1718 |
+
// the raw query parameters and return the raw query
|
1719 |
+
if ( $this->_is_raw_query ) {
|
1720 |
+
$this->_values = $this->_raw_parameters;
|
1721 |
+
|
1722 |
+
return $this->_raw_query;
|
1723 |
+
}
|
1724 |
+
// Build and return the full SELECT statement by concatenating
|
1725 |
+
// the results of calling each separate builder method.
|
1726 |
+
return $this->_join_if_not_empty( ' ', [
|
1727 |
+
$this->_build_select_start(),
|
1728 |
+
$this->_build_join(),
|
1729 |
+
$this->_build_where(),
|
1730 |
+
$this->_build_group_by(),
|
1731 |
+
$this->_build_having(),
|
1732 |
+
$this->_build_order_by(),
|
1733 |
+
$this->_build_limit(),
|
1734 |
+
$this->_build_offset(),
|
1735 |
+
] );
|
1736 |
+
}
|
1737 |
+
|
1738 |
+
/**
|
1739 |
+
* Build the start of the SELECT statement
|
1740 |
+
*
|
1741 |
+
* @return string
|
1742 |
+
*/
|
1743 |
+
protected function _build_select_start() {
|
1744 |
+
$fragment = 'SELECT ';
|
1745 |
+
$result_columns = \join( ', ', $this->_result_columns );
|
1746 |
+
if ( $this->_distinct ) {
|
1747 |
+
$result_columns = 'DISTINCT ' . $result_columns;
|
1748 |
+
}
|
1749 |
+
$fragment .= "{$result_columns} FROM " . $this->_quote_identifier( $this->_table_name );
|
1750 |
+
if ( ! \is_null( $this->_table_alias ) ) {
|
1751 |
+
$fragment .= ' ' . $this->_quote_identifier( $this->_table_alias );
|
1752 |
+
}
|
1753 |
+
|
1754 |
+
return $fragment;
|
1755 |
+
}
|
1756 |
+
|
1757 |
+
/**
|
1758 |
+
* Build the JOIN sources
|
1759 |
+
*
|
1760 |
+
* @return string
|
1761 |
+
*/
|
1762 |
+
protected function _build_join() {
|
1763 |
+
if ( \count( $this->_join_sources ) === 0 ) {
|
1764 |
+
return '';
|
1765 |
+
}
|
1766 |
+
|
1767 |
+
return \join( ' ', $this->_join_sources );
|
1768 |
+
}
|
1769 |
+
|
1770 |
+
/**
|
1771 |
+
* Build the WHERE clause(s)
|
1772 |
+
*
|
1773 |
+
* @return string
|
1774 |
+
*/
|
1775 |
+
protected function _build_where() {
|
1776 |
+
return $this->_build_conditions( 'where' );
|
1777 |
+
}
|
1778 |
+
|
1779 |
+
/**
|
1780 |
+
* Build the HAVING clause(s)
|
1781 |
+
*
|
1782 |
+
* @return string
|
1783 |
+
*/
|
1784 |
+
protected function _build_having() {
|
1785 |
+
return $this->_build_conditions( 'having' );
|
1786 |
+
}
|
1787 |
+
|
1788 |
+
/**
|
1789 |
+
* Build GROUP BY
|
1790 |
+
*
|
1791 |
+
* @return string
|
1792 |
+
*/
|
1793 |
+
protected function _build_group_by() {
|
1794 |
+
if ( \count( $this->_group_by ) === 0 ) {
|
1795 |
+
return '';
|
1796 |
+
}
|
1797 |
+
|
1798 |
+
return 'GROUP BY ' . \join( ', ', $this->_group_by );
|
1799 |
+
}
|
1800 |
+
|
1801 |
+
/**
|
1802 |
+
* Build a WHERE or HAVING clause
|
1803 |
+
*
|
1804 |
+
* @param string $type
|
1805 |
+
*
|
1806 |
+
* @return string
|
1807 |
+
*/
|
1808 |
+
protected function _build_conditions( $type ) {
|
1809 |
+
$conditions_class_property_name = "_{$type}_conditions";
|
1810 |
+
// If there are no clauses, return empty string
|
1811 |
+
if ( \count( $this->{$conditions_class_property_name} ) === 0 ) {
|
1812 |
+
return '';
|
1813 |
+
}
|
1814 |
+
$conditions = [];
|
1815 |
+
foreach ( $this->{$conditions_class_property_name} as $condition ) {
|
1816 |
+
$conditions[] = $condition[ self::CONDITION_FRAGMENT ];
|
1817 |
+
$this->_values = \array_merge( $this->_values, $condition[ self::CONDITION_VALUES ] );
|
1818 |
+
}
|
1819 |
+
|
1820 |
+
return \strtoupper( $type ) . ' ' . \join( ' AND ', $conditions );
|
1821 |
+
}
|
1822 |
+
|
1823 |
+
/**
|
1824 |
+
* Build ORDER BY
|
1825 |
+
*/
|
1826 |
+
protected function _build_order_by() {
|
1827 |
+
if ( \count( $this->_order_by ) === 0 ) {
|
1828 |
+
return '';
|
1829 |
+
}
|
1830 |
+
|
1831 |
+
return 'ORDER BY ' . \join( ', ', $this->_order_by );
|
1832 |
+
}
|
1833 |
+
|
1834 |
+
/**
|
1835 |
+
* Build LIMIT
|
1836 |
+
*/
|
1837 |
+
protected function _build_limit() {
|
1838 |
+
if ( ! \is_null( $this->_limit ) ) {
|
1839 |
+
return "LIMIT {$this->_limit}";
|
1840 |
+
}
|
1841 |
+
|
1842 |
+
return '';
|
1843 |
+
}
|
1844 |
+
|
1845 |
+
/**
|
1846 |
+
* Build OFFSET
|
1847 |
+
*/
|
1848 |
+
protected function _build_offset() {
|
1849 |
+
if ( ! \is_null( $this->_offset ) ) {
|
1850 |
+
return 'OFFSET ' . $this->_offset;
|
1851 |
+
}
|
1852 |
+
|
1853 |
+
return '';
|
1854 |
+
}
|
1855 |
+
|
1856 |
+
/**
|
1857 |
+
* Wrapper around PHP's join function which
|
1858 |
+
* only adds the pieces if they are not empty.
|
1859 |
+
*
|
1860 |
+
* @param $glue
|
1861 |
+
* @param $pieces
|
1862 |
+
*
|
1863 |
+
* @return string
|
1864 |
+
*/
|
1865 |
+
protected function _join_if_not_empty( $glue, $pieces ) {
|
1866 |
+
$filtered_pieces = [];
|
1867 |
+
foreach ( $pieces as $piece ) {
|
1868 |
+
if ( \is_string( $piece ) ) {
|
1869 |
+
$piece = \trim( $piece );
|
1870 |
+
}
|
1871 |
+
if ( ! empty( $piece ) ) {
|
1872 |
+
$filtered_pieces[] = $piece;
|
1873 |
+
}
|
1874 |
+
}
|
1875 |
+
|
1876 |
+
return \join( $glue, $filtered_pieces );
|
1877 |
+
}
|
1878 |
+
|
1879 |
+
/**
|
1880 |
+
* Quote a string that is used as an identifier
|
1881 |
+
* (table names, column names etc). This method can
|
1882 |
+
* also deal with dot-separated identifiers eg table.column
|
1883 |
+
*
|
1884 |
+
* @param $identifier
|
1885 |
+
*
|
1886 |
+
* @return string
|
1887 |
+
*/
|
1888 |
+
protected function _quote_one_identifier( $identifier ) {
|
1889 |
+
$parts = \explode( '.', $identifier );
|
1890 |
+
$parts = \array_map( [ $this, '_quote_identifier_part' ], $parts );
|
1891 |
+
|
1892 |
+
return \join( '.', $parts );
|
1893 |
+
}
|
1894 |
+
|
1895 |
+
/**
|
1896 |
+
* Quote a string that is used as an identifier
|
1897 |
+
* (table names, column names etc) or an array containing
|
1898 |
+
* multiple identifiers. This method can also deal with
|
1899 |
+
* dot-separated identifiers eg table.column
|
1900 |
+
*
|
1901 |
+
* @param $identifier
|
1902 |
+
*
|
1903 |
+
* @return string
|
1904 |
+
*/
|
1905 |
+
protected function _quote_identifier( $identifier ) {
|
1906 |
+
if ( \is_array( $identifier ) ) {
|
1907 |
+
$result = \array_map( [ $this, '_quote_one_identifier' ], $identifier );
|
1908 |
+
|
1909 |
+
return \join( ', ', $result );
|
1910 |
+
} else {
|
1911 |
+
return $this->_quote_one_identifier( $identifier );
|
1912 |
+
}
|
1913 |
+
}
|
1914 |
+
|
1915 |
+
/**
|
1916 |
+
* This method performs the actual quoting of a single
|
1917 |
+
* part of an identifier, using the identifier quote
|
1918 |
+
* character specified in the config (or autodetected).
|
1919 |
+
*
|
1920 |
+
* @param $part
|
1921 |
+
*
|
1922 |
+
* @return string
|
1923 |
+
*/
|
1924 |
+
protected function _quote_identifier_part( $part ) {
|
1925 |
+
if ( $part === '*' ) {
|
1926 |
+
return $part;
|
1927 |
+
}
|
1928 |
+
$quote_character = '`';
|
1929 |
+
|
1930 |
+
// double up any identifier quotes to escape them
|
1931 |
+
return $quote_character . \str_replace( $quote_character, $quote_character . $quote_character, $part ) . $quote_character;
|
1932 |
+
}
|
1933 |
+
|
1934 |
+
/**
|
1935 |
+
* Execute the SELECT query that has been built up by chaining methods
|
1936 |
+
* on this class. Return an array of rows as associative arrays.
|
1937 |
+
*
|
1938 |
+
* @return array|false The result rows. False if the query failed.
|
1939 |
+
*/
|
1940 |
+
protected function _run() {
|
1941 |
+
global $wpdb;
|
1942 |
+
|
1943 |
+
$query = $this->_build_select();
|
1944 |
+
$success = self::_execute( $query, $this->_values );
|
1945 |
+
|
1946 |
+
if ( $success === false ) {
|
1947 |
+
// If the query fails run the migrations and try again.
|
1948 |
+
// Action is intentionally undocumented and should not be used by third-parties.
|
1949 |
+
\do_action( '_yoast_run_migrations' );
|
1950 |
+
$success = self::_execute( $query, $this->_values );
|
1951 |
+
}
|
1952 |
+
|
1953 |
+
$this->_reset_idiorm_state();
|
1954 |
+
|
1955 |
+
if ( $success === false ) {
|
1956 |
+
return false;
|
1957 |
+
}
|
1958 |
+
|
1959 |
+
$rows = [];
|
1960 |
+
foreach ( $wpdb->last_result as $row ) {
|
1961 |
+
$rows[] = \get_object_vars( $row );
|
1962 |
+
}
|
1963 |
+
|
1964 |
+
return $rows;
|
1965 |
+
}
|
1966 |
+
|
1967 |
+
/**
|
1968 |
+
* Reset the Idiorm instance state
|
1969 |
+
*/
|
1970 |
+
private function _reset_idiorm_state() {
|
1971 |
+
$this->_values = [];
|
1972 |
+
$this->_result_columns = [ '*' ];
|
1973 |
+
$this->_using_default_result_columns = true;
|
1974 |
+
}
|
1975 |
+
|
1976 |
+
/**
|
1977 |
+
* Return the raw data wrapped by this ORM
|
1978 |
+
* instance as an associative array. Column
|
1979 |
+
* names may optionally be supplied as arguments,
|
1980 |
+
* if so, only those keys will be returned.
|
1981 |
+
*/
|
1982 |
+
public function as_array() {
|
1983 |
+
if ( \func_num_args() === 0 ) {
|
1984 |
+
return $this->_data;
|
1985 |
+
}
|
1986 |
+
$args = \func_get_args();
|
1987 |
+
|
1988 |
+
return \array_intersect_key( $this->_data, \array_flip( $args ) );
|
1989 |
+
}
|
1990 |
+
|
1991 |
+
/**
|
1992 |
+
* Return the value of a property of this object (database row)
|
1993 |
+
* or null if not present.
|
1994 |
+
*
|
1995 |
+
* If a column-names array is passed, it will return a associative array
|
1996 |
+
* with the value of each column or null if it is not present.
|
1997 |
+
*
|
1998 |
+
* @param $key
|
1999 |
+
*
|
2000 |
+
* @return array|mixed|null
|
2001 |
+
*/
|
2002 |
+
public function get( $key ) {
|
2003 |
+
if ( \is_array( $key ) ) {
|
2004 |
+
$result = [];
|
2005 |
+
foreach ( $key as $column ) {
|
2006 |
+
$result[ $column ] = isset( $this->_data[ $column ] ) ? $this->_data[ $column ] : null;
|
2007 |
+
}
|
2008 |
+
|
2009 |
+
return $result;
|
2010 |
+
} else {
|
2011 |
+
return isset( $this->_data[ $key ] ) ? $this->_data[ $key ] : null;
|
2012 |
+
}
|
2013 |
+
}
|
2014 |
+
|
2015 |
+
/**
|
2016 |
+
* Return the name of the column in the database table which contains
|
2017 |
+
* the primary key ID of the row.
|
2018 |
+
*/
|
2019 |
+
protected function _get_id_column_name() {
|
2020 |
+
if ( ! \is_null( $this->_instance_id_column ) ) {
|
2021 |
+
return $this->_instance_id_column;
|
2022 |
+
}
|
2023 |
+
|
2024 |
+
return 'id';
|
2025 |
+
}
|
2026 |
+
|
2027 |
+
/**
|
2028 |
+
* Get the primary key ID of this object.
|
2029 |
+
*
|
2030 |
+
* @param bool $disallow_null
|
2031 |
+
*
|
2032 |
+
* @return array|mixed|null
|
2033 |
+
* @throws \Exception
|
2034 |
+
*/
|
2035 |
+
public function id( $disallow_null = false ) {
|
2036 |
+
$id = $this->get( $this->_get_id_column_name() );
|
2037 |
+
if ( $disallow_null ) {
|
2038 |
+
if ( \is_array( $id ) ) {
|
2039 |
+
foreach ( $id as $id_part ) {
|
2040 |
+
if ( $id_part === null ) {
|
2041 |
+
throw new \Exception( 'Primary key ID contains null value(s)' );
|
2042 |
+
}
|
2043 |
+
}
|
2044 |
+
} else {
|
2045 |
+
if ( $id === null ) {
|
2046 |
+
throw new \Exception( 'Primary key ID missing from row or is null' );
|
2047 |
+
}
|
2048 |
+
}
|
2049 |
+
}
|
2050 |
+
|
2051 |
+
return $id;
|
2052 |
+
}
|
2053 |
+
|
2054 |
+
/**
|
2055 |
+
* Set a property to a particular value on this object.
|
2056 |
+
* To set multiple properties at once, pass an associative array
|
2057 |
+
* as the first parameter and leave out the second parameter.
|
2058 |
+
* Flags the properties as 'dirty' so they will be saved to the
|
2059 |
+
* database when save() is called.
|
2060 |
+
*
|
2061 |
+
* @param $key
|
2062 |
+
* @param null $value
|
2063 |
+
*
|
2064 |
+
* @return ORM
|
2065 |
+
*/
|
2066 |
+
public function set( $key, $value = null ) {
|
2067 |
+
return $this->_set_orm_property( $key, $value );
|
2068 |
+
}
|
2069 |
+
|
2070 |
+
/**
|
2071 |
+
* Set a property to a particular value on this object.
|
2072 |
+
* To set multiple properties at once, pass an associative array
|
2073 |
+
* as the first parameter and leave out the second parameter.
|
2074 |
+
* Flags the properties as 'dirty' so they will be saved to the
|
2075 |
+
* database when save() is called.
|
2076 |
+
*
|
2077 |
+
* @param string|array $key
|
2078 |
+
* @param string|null $value
|
2079 |
+
*
|
2080 |
+
* @return ORM
|
2081 |
+
*/
|
2082 |
+
public function set_expr( $key, $value = null ) {
|
2083 |
+
return $this->_set_orm_property( $key, $value, true );
|
2084 |
+
}
|
2085 |
+
|
2086 |
+
/**
|
2087 |
+
* Set a property on the ORM object.
|
2088 |
+
*
|
2089 |
+
* @param string|array $key
|
2090 |
+
* @param string|null $value
|
2091 |
+
* @param bool $expr
|
2092 |
+
*
|
2093 |
+
* @return ORM
|
2094 |
+
*/
|
2095 |
+
protected function _set_orm_property( $key, $value = null, $expr = false ) {
|
2096 |
+
if ( ! \is_array( $key ) ) {
|
2097 |
+
$key = [ $key => $value ];
|
2098 |
+
}
|
2099 |
+
foreach ( $key as $field => $value ) {
|
2100 |
+
$this->_data[ $field ] = $value;
|
2101 |
+
$this->_dirty_fields[ $field ] = $value;
|
2102 |
+
if ( false === $expr and isset( $this->_expr_fields[ $field ] ) ) {
|
2103 |
+
unset( $this->_expr_fields[ $field ] );
|
2104 |
+
} else {
|
2105 |
+
if ( true === $expr ) {
|
2106 |
+
$this->_expr_fields[ $field ] = true;
|
2107 |
+
}
|
2108 |
+
}
|
2109 |
+
}
|
2110 |
+
|
2111 |
+
return $this;
|
2112 |
+
}
|
2113 |
+
|
2114 |
+
/**
|
2115 |
+
* Check whether the given field has been changed since this
|
2116 |
+
* object was saved.
|
2117 |
+
*
|
2118 |
+
* @param $key
|
2119 |
+
*
|
2120 |
+
* @return bool
|
2121 |
+
*/
|
2122 |
+
public function is_dirty( $key ) {
|
2123 |
+
return \array_key_exists( $key, $this->_dirty_fields );
|
2124 |
+
}
|
2125 |
+
|
2126 |
+
/**
|
2127 |
+
* Check whether the model was the result of a call to create() or not
|
2128 |
+
*
|
2129 |
+
* @return bool
|
2130 |
+
*/
|
2131 |
+
public function is_new() {
|
2132 |
+
return $this->_is_new;
|
2133 |
+
}
|
2134 |
+
|
2135 |
+
/**
|
2136 |
+
* Save any fields which have been modified on this object
|
2137 |
+
* to the database.
|
2138 |
+
*/
|
2139 |
+
public function save() {
|
2140 |
+
global $wpdb;
|
2141 |
+
|
2142 |
+
// remove any expression fields as they are already baked into the query
|
2143 |
+
$values = \array_values( \array_diff_key( $this->_dirty_fields, $this->_expr_fields ) );
|
2144 |
+
if ( ! $this->_is_new ) {
|
2145 |
+
// UPDATE
|
2146 |
+
// If there are no dirty values, do nothing
|
2147 |
+
if ( empty( $values ) && empty( $this->_expr_fields ) ) {
|
2148 |
+
return true;
|
2149 |
+
}
|
2150 |
+
$query = $this->_build_update();
|
2151 |
+
$id = $this->id( true );
|
2152 |
+
if ( \is_array( $id ) ) {
|
2153 |
+
$values = \array_merge( $values, \array_values( $id ) );
|
2154 |
+
} else {
|
2155 |
+
$values[] = $id;
|
2156 |
+
}
|
2157 |
+
} else {
|
2158 |
+
// INSERT
|
2159 |
+
$query = $this->_build_insert();
|
2160 |
+
}
|
2161 |
+
$success = self::_execute( $query, $values );
|
2162 |
+
// If we've just inserted a new record, set the ID of this object
|
2163 |
+
if ( $this->_is_new ) {
|
2164 |
+
$this->_is_new = false;
|
2165 |
+
if ( $this->count_null_id_columns() != 0 ) {
|
2166 |
+
$column = $this->_get_id_column_name();
|
2167 |
+
// if the primary key is compound, assign the last inserted id
|
2168 |
+
// to the first column
|
2169 |
+
if ( \is_array( $column ) ) {
|
2170 |
+
$column = \reset( $column );
|
2171 |
+
}
|
2172 |
+
$this->_data[ $column ] = $wpdb->insert_id;
|
2173 |
+
}
|
2174 |
+
}
|
2175 |
+
$this->_dirty_fields = $this->_expr_fields = [];
|
2176 |
+
|
2177 |
+
return $success;
|
2178 |
+
}
|
2179 |
+
|
2180 |
+
/**
|
2181 |
+
* Add a WHERE clause for every column that belongs to the primary key
|
2182 |
+
*
|
2183 |
+
* @param array $query The query.
|
2184 |
+
*
|
2185 |
+
* @return void
|
2186 |
+
*/
|
2187 |
+
public function _add_id_column_conditions( &$query ) {
|
2188 |
+
$query[] = 'WHERE';
|
2189 |
+
$keys = \is_array( $this->_get_id_column_name() ) ? $this->_get_id_column_name() : [ $this->_get_id_column_name() ];
|
2190 |
+
$first = true;
|
2191 |
+
foreach ( $keys as $key ) {
|
2192 |
+
if ( $first ) {
|
2193 |
+
$first = false;
|
2194 |
+
} else {
|
2195 |
+
$query[] = 'AND';
|
2196 |
+
}
|
2197 |
+
$query[] = $this->_quote_identifier( $key );
|
2198 |
+
$query[] = '= %s';
|
2199 |
+
}
|
2200 |
+
}
|
2201 |
+
|
2202 |
+
/**
|
2203 |
+
* Build an UPDATE query
|
2204 |
+
*
|
2205 |
+
* @return string The update query.
|
2206 |
+
*/
|
2207 |
+
protected function _build_update() {
|
2208 |
+
$query = [];
|
2209 |
+
$query[] = "UPDATE {$this->_quote_identifier($this->_table_name)} SET";
|
2210 |
+
$field_list = [];
|
2211 |
+
foreach ( $this->_dirty_fields as $key => $value ) {
|
2212 |
+
if ( ! \array_key_exists( $key, $this->_expr_fields ) ) {
|
2213 |
+
$value = '%s';
|
2214 |
+
}
|
2215 |
+
$field_list[] = "{$this->_quote_identifier($key)} = {$value}";
|
2216 |
+
}
|
2217 |
+
$query[] = \join( ', ', $field_list );
|
2218 |
+
$this->_add_id_column_conditions( $query );
|
2219 |
+
|
2220 |
+
return \join( ' ', $query );
|
2221 |
+
}
|
2222 |
+
|
2223 |
+
/**
|
2224 |
+
* Build an INSERT query
|
2225 |
+
*
|
2226 |
+
* @return string The insert query.
|
2227 |
+
*/
|
2228 |
+
protected function _build_insert() {
|
2229 |
+
$query[] = 'INSERT INTO';
|
2230 |
+
$query[] = $this->_quote_identifier( $this->_table_name );
|
2231 |
+
$field_list = \array_map( [ $this, '_quote_identifier' ], \array_keys( $this->_dirty_fields ) );
|
2232 |
+
$query[] = '(' . \join( ', ', $field_list ) . ')';
|
2233 |
+
$query[] = 'VALUES';
|
2234 |
+
$placeholders = $this->_create_placeholders( $this->_dirty_fields );
|
2235 |
+
$query[] = "({$placeholders})";
|
2236 |
+
|
2237 |
+
return \join( ' ', $query );
|
2238 |
+
}
|
2239 |
+
|
2240 |
+
/**
|
2241 |
+
* Delete this record from the database
|
2242 |
+
*
|
2243 |
+
* @return string The delete query.
|
2244 |
+
*
|
2245 |
+
* @throws \Exception
|
2246 |
+
*/
|
2247 |
+
public function delete() {
|
2248 |
+
$query = [ 'DELETE FROM', $this->_quote_identifier( $this->_table_name ) ];
|
2249 |
+
$this->_add_id_column_conditions( $query );
|
2250 |
+
|
2251 |
+
return self::_execute( \join( ' ', $query ), \is_array( $this->id( true ) ) ? \array_values( $this->id( true ) ) : [ $this->id( true ) ] );
|
2252 |
+
}
|
2253 |
+
|
2254 |
+
/**
|
2255 |
+
* Delete many records from the database
|
2256 |
+
*/
|
2257 |
+
public function delete_many() {
|
2258 |
+
// Build and return the full DELETE statement by concatenating
|
2259 |
+
// the results of calling each separate builder method.
|
2260 |
+
$query = $this->_join_if_not_empty( ' ', [
|
2261 |
+
'DELETE FROM',
|
2262 |
+
$this->_quote_identifier( $this->_table_name ),
|
2263 |
+
$this->_build_where(),
|
2264 |
+
] );
|
2265 |
+
|
2266 |
+
return self::_execute( $query, $this->_values );
|
2267 |
+
}
|
2268 |
+
// --------------------- //
|
2269 |
+
// --- ArrayAccess --- //
|
2270 |
+
// --------------------- //
|
2271 |
+
/**
|
2272 |
+
* @param mixed $key
|
2273 |
+
*
|
2274 |
+
* @return bool
|
2275 |
+
*/
|
2276 |
+
public function offsetExists( $key ) {
|
2277 |
+
return \array_key_exists( $key, $this->_data );
|
2278 |
+
}
|
2279 |
+
|
2280 |
+
/**
|
2281 |
+
* @param mixed $key
|
2282 |
+
*
|
2283 |
+
* @return array|mixed|null
|
2284 |
+
*/
|
2285 |
+
public function offsetGet( $key ) {
|
2286 |
+
return $this->get( $key );
|
2287 |
+
}
|
2288 |
+
|
2289 |
+
/**
|
2290 |
+
* @param mixed $key
|
2291 |
+
* @param mixed $value
|
2292 |
+
*/
|
2293 |
+
public function offsetSet( $key, $value ) {
|
2294 |
+
if ( \is_null( $key ) ) {
|
2295 |
+
return;
|
2296 |
+
}
|
2297 |
+
$this->set( $key, $value );
|
2298 |
+
}
|
2299 |
+
|
2300 |
+
/**
|
2301 |
+
* @param mixed $key
|
2302 |
+
*/
|
2303 |
+
public function offsetUnset( $key ) {
|
2304 |
+
unset( $this->_data[ $key ] );
|
2305 |
+
unset( $this->_dirty_fields[ $key ] );
|
2306 |
+
}
|
2307 |
+
// --------------------- //
|
2308 |
+
// --- MAGIC METHODS --- //
|
2309 |
+
// --------------------- //
|
2310 |
+
/**
|
2311 |
+
* @param $key
|
2312 |
+
*
|
2313 |
+
* @return array|mixed|null
|
2314 |
+
*/
|
2315 |
+
public function __get( $key ) {
|
2316 |
+
return $this->offsetGet( $key );
|
2317 |
+
}
|
2318 |
+
|
2319 |
+
/**
|
2320 |
+
* @param $key
|
2321 |
+
* @param $value
|
2322 |
+
*/
|
2323 |
+
public function __set( $key, $value ) {
|
2324 |
+
$this->offsetSet( $key, $value );
|
2325 |
+
}
|
2326 |
+
|
2327 |
+
/**
|
2328 |
+
* @param $key
|
2329 |
+
*/
|
2330 |
+
public function __unset( $key ) {
|
2331 |
+
$this->offsetUnset( $key );
|
2332 |
+
}
|
2333 |
+
|
2334 |
+
/**
|
2335 |
+
* @param $key
|
2336 |
+
*
|
2337 |
+
* @return bool
|
2338 |
+
*/
|
2339 |
+
public function __isset( $key ) {
|
2340 |
+
return $this->offsetExists( $key );
|
2341 |
+
}
|
2342 |
+
}
|
lib/ruckusing-adapter.php
ADDED
@@ -0,0 +1,1084 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Yoast model class.
|
4 |
+
*
|
5 |
+
* @package Yoast\WP\Lib
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Yoast\WP\Lib;
|
9 |
+
|
10 |
+
use YoastSEO_Vendor\Ruckusing_Adapter_ColumnDefinition;
|
11 |
+
use YoastSEO_Vendor\Ruckusing_Adapter_Interface;
|
12 |
+
use YoastSEO_Vendor\Ruckusing_Adapter_MySQL_Base;
|
13 |
+
use YoastSEO_Vendor\Ruckusing_Adapter_MySQL_TableDefinition;
|
14 |
+
use YoastSEO_Vendor\Ruckusing_Exception;
|
15 |
+
use YoastSEO_Vendor\Ruckusing_Util_Naming;
|
16 |
+
|
17 |
+
use const YoastSEO_Vendor\MYSQL_MAX_IDENTIFIER_LENGTH;
|
18 |
+
use const YoastSEO_Vendor\SQL_ALTER;
|
19 |
+
use const YoastSEO_Vendor\SQL_CREATE;
|
20 |
+
use const YoastSEO_Vendor\SQL_DELETE;
|
21 |
+
use const YoastSEO_Vendor\SQL_DROP;
|
22 |
+
use const YoastSEO_Vendor\SQL_INSERT;
|
23 |
+
use const YoastSEO_Vendor\SQL_RENAME;
|
24 |
+
use const YoastSEO_Vendor\SQL_SELECT;
|
25 |
+
use const YoastSEO_Vendor\SQL_SET;
|
26 |
+
use const YoastSEO_Vendor\SQL_SHOW;
|
27 |
+
use const YoastSEO_Vendor\SQL_UNKNOWN_QUERY_TYPE;
|
28 |
+
use const YoastSEO_Vendor\SQL_UPDATE;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Ruckusing_Adapter
|
32 |
+
*/
|
33 |
+
class Ruckusing_Adapter extends Ruckusing_Adapter_MySQL_Base implements Ruckusing_Adapter_Interface {
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Name of adapter
|
37 |
+
*
|
38 |
+
* @var string
|
39 |
+
*/
|
40 |
+
private $_name = 'MySQL';
|
41 |
+
/**
|
42 |
+
* Tables
|
43 |
+
*
|
44 |
+
* @var array
|
45 |
+
*/
|
46 |
+
private $_tables = [];
|
47 |
+
/**
|
48 |
+
* Tables_loaded
|
49 |
+
*
|
50 |
+
* @var boolean
|
51 |
+
*/
|
52 |
+
private $_tables_loaded = false;
|
53 |
+
/**
|
54 |
+
* Version
|
55 |
+
*
|
56 |
+
* @var string
|
57 |
+
*/
|
58 |
+
private $_version = '1.0';
|
59 |
+
/**
|
60 |
+
* Indicate if is in transaction
|
61 |
+
*
|
62 |
+
* @var boolean
|
63 |
+
*/
|
64 |
+
private $_in_trx = false;
|
65 |
+
/**
|
66 |
+
* Creates an instance of Ruckusing_Adapter.
|
67 |
+
*
|
68 |
+
* @param array $config The configuration.
|
69 |
+
*
|
70 |
+
* @return Ruckusing_Adapter
|
71 |
+
*/
|
72 |
+
public function __construct( $config ) {
|
73 |
+
$this->set_dsn( $config );
|
74 |
+
}
|
75 |
+
/**
|
76 |
+
* Get the current db name
|
77 |
+
*
|
78 |
+
* @return string
|
79 |
+
*/
|
80 |
+
public function get_database_name() {
|
81 |
+
global $wpdb;
|
82 |
+
return $wpdb->dbname;
|
83 |
+
}
|
84 |
+
/**
|
85 |
+
* Check support for migrations
|
86 |
+
*
|
87 |
+
* @return boolean
|
88 |
+
*/
|
89 |
+
public function supports_migrations() {
|
90 |
+
return true;
|
91 |
+
}
|
92 |
+
/**
|
93 |
+
* Get the column native types
|
94 |
+
*
|
95 |
+
* @return array
|
96 |
+
*/
|
97 |
+
public function native_database_types() {
|
98 |
+
$types = [ 'primary_key' => [ 'name' => 'integer', 'limit' => 11, 'null' => false ], 'string' => [ 'name' => 'varchar', 'limit' => 255 ], 'text' => [ 'name' => 'text' ], 'tinytext' => [ 'name' => 'tinytext' ], 'mediumtext' => [ 'name' => 'mediumtext' ], 'integer' => [ 'name' => 'int', 'limit' => 11 ], 'tinyinteger' => [ 'name' => 'tinyint' ], 'smallinteger' => [ 'name' => 'smallint' ], 'mediuminteger' => [ 'name' => 'mediumint' ], 'biginteger' => [ 'name' => 'bigint' ], 'float' => [ 'name' => 'float' ], 'decimal' => [ 'name' => 'decimal', 'scale' => 0, 'precision' => 10 ], 'datetime' => [ 'name' => 'datetime' ], 'timestamp' => [ 'name' => 'timestamp' ], 'time' => [ 'name' => 'time' ], 'date' => [ 'name' => 'date' ], 'binary' => [ 'name' => 'blob' ], 'tinybinary' => [ 'name' => 'tinyblob' ], 'mediumbinary' => [ 'name' => 'mediumblob' ], 'longbinary' => [ 'name' => 'longblob' ], 'boolean' => [ 'name' => 'tinyint', 'limit' => 1 ], 'enum' => [ 'name' => 'enum', 'values' => [] ], 'uuid' => [ 'name' => 'char', 'limit' => 36 ], 'char' => [ 'name' => 'char' ] ];
|
99 |
+
return $types;
|
100 |
+
}
|
101 |
+
/**
|
102 |
+
* Create the schema table, if necessary
|
103 |
+
*/
|
104 |
+
public function create_schema_version_table() {
|
105 |
+
if ( ! $this->has_table( $this->get_schema_version_table_name() ) ) {
|
106 |
+
$t = $this->create_table( $this->get_schema_version_table_name(), [ 'id' => false ] );
|
107 |
+
$t->column( 'version', 'string' );
|
108 |
+
$t->finish();
|
109 |
+
$this->add_index( $this->get_schema_version_table_name(), 'version', [ 'unique' => true ] );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
/**
|
113 |
+
* Start Transaction
|
114 |
+
*/
|
115 |
+
public function start_transaction() {
|
116 |
+
if ( $this->inTransaction() === false ) {
|
117 |
+
$this->beginTransaction();
|
118 |
+
}
|
119 |
+
}
|
120 |
+
/**
|
121 |
+
* Commit Transaction
|
122 |
+
*/
|
123 |
+
public function commit_transaction() {
|
124 |
+
if ( $this->inTransaction() ) {
|
125 |
+
$this->commit();
|
126 |
+
}
|
127 |
+
}
|
128 |
+
/**
|
129 |
+
* Rollback Transaction
|
130 |
+
*/
|
131 |
+
public function rollback_transaction() {
|
132 |
+
if ( $this->inTransaction() ) {
|
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 |
+
*
|
148 |
+
* @param string $column_name The column name.
|
149 |
+
* @param string $type The type of the column.
|
150 |
+
* @param array $options Column options.
|
151 |
+
*
|
152 |
+
* @return string
|
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 |
+
*
|
162 |
+
* @param string $db The db name.
|
163 |
+
*
|
164 |
+
* @return boolean
|
165 |
+
*/
|
166 |
+
public function database_exists( $db ) {
|
167 |
+
$ddl = 'SHOW DATABASES';
|
168 |
+
$result = $this->select_all( $ddl );
|
169 |
+
if ( \count( $result ) == 0 ) {
|
170 |
+
return false;
|
171 |
+
}
|
172 |
+
foreach ( $result as $dbrow ) {
|
173 |
+
if ( $dbrow['Database'] == $db ) {
|
174 |
+
return true;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
return false;
|
178 |
+
}
|
179 |
+
/**
|
180 |
+
* Create a database
|
181 |
+
*
|
182 |
+
* @param string $db the db name
|
183 |
+
*
|
184 |
+
* @return boolean
|
185 |
+
*/
|
186 |
+
public function create_database( $db ) {
|
187 |
+
if ( $this->database_exists( $db ) ) {
|
188 |
+
return false;
|
189 |
+
}
|
190 |
+
$ddl = \sprintf( 'CREATE DATABASE %s', $this->identifier( $db ) );
|
191 |
+
$result = $this->query( $ddl );
|
192 |
+
return $result === true;
|
193 |
+
}
|
194 |
+
/**
|
195 |
+
* Drop a database
|
196 |
+
*
|
197 |
+
* @param string $db the db name
|
198 |
+
*
|
199 |
+
* @return boolean
|
200 |
+
*/
|
201 |
+
public function drop_database( $db ) {
|
202 |
+
if ( ! $this->database_exists( $db ) ) {
|
203 |
+
return false;
|
204 |
+
}
|
205 |
+
$ddl = \sprintf( 'DROP DATABASE IF EXISTS %s', $this->identifier( $db ) );
|
206 |
+
$result = $this->query( $ddl );
|
207 |
+
return $result === true;
|
208 |
+
}
|
209 |
+
/**
|
210 |
+
* Dump the complete schema of the DB. This is really just all of the
|
211 |
+
* CREATE TABLE statements for all of the tables in the DB.
|
212 |
+
* NOTE: this does NOT include any INSERT statements or the actual data
|
213 |
+
* (that is, this method is NOT a replacement for mysqldump)
|
214 |
+
*
|
215 |
+
* @param string $output_file the filepath to output to
|
216 |
+
*
|
217 |
+
* @return int|FALSE
|
218 |
+
*/
|
219 |
+
public function schema( $output_file ) {
|
220 |
+
$final = '';
|
221 |
+
$views = '';
|
222 |
+
$this->load_tables( true );
|
223 |
+
foreach ( $this->_tables as $tbl => $idx ) {
|
224 |
+
if ( $tbl == 'schema_info' ) {
|
225 |
+
continue;
|
226 |
+
}
|
227 |
+
$stmt = \sprintf( 'SHOW CREATE TABLE %s', $this->identifier( $tbl ) );
|
228 |
+
$result = $this->query( $stmt );
|
229 |
+
if ( \is_array( $result ) && \count( $result ) == 1 ) {
|
230 |
+
$row = $result[0];
|
231 |
+
if ( \count( $row ) == 2 ) {
|
232 |
+
if ( isset( $row['Create Table'] ) ) {
|
233 |
+
$final .= $row['Create Table'] . ";\n\n";
|
234 |
+
} elseif ( isset( $row['Create View'] ) ) {
|
235 |
+
$views .= $row['Create View'] . ";\n\n";
|
236 |
+
}
|
237 |
+
}
|
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 |
+
*
|
246 |
+
* @param string $tbl the table name
|
247 |
+
* @param boolean $reload_tables reload table or not
|
248 |
+
*
|
249 |
+
* @return boolean
|
250 |
+
*/
|
251 |
+
public function table_exists( $tbl, $reload_tables = false ) {
|
252 |
+
$this->load_tables( $reload_tables );
|
253 |
+
return \array_key_exists( $tbl, $this->_tables );
|
254 |
+
}
|
255 |
+
/**
|
256 |
+
* Wrapper to execute a query
|
257 |
+
*
|
258 |
+
* @param string $query query to run
|
259 |
+
*
|
260 |
+
* @return boolean
|
261 |
+
*/
|
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...
|
286 |
+
$res = $wpdb->query( $query );
|
287 |
+
if ( $this->isError( $res ) ) {
|
288 |
+
throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
|
289 |
+
}
|
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;
|
320 |
+
|
321 |
+
$query_type = $this->determine_query_type( $query );
|
322 |
+
if ( $query_type == SQL_SELECT || $query_type == SQL_SHOW ) {
|
323 |
+
$res = $wpdb->query( $query );
|
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 |
+
*
|
335 |
+
* @param string $query query to run
|
336 |
+
*
|
337 |
+
* @return array
|
338 |
+
*/
|
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.
|
345 |
+
*
|
346 |
+
* @param string $ddl query to run
|
347 |
+
*
|
348 |
+
* @return boolean
|
349 |
+
*/
|
350 |
+
public function execute_ddl( $ddl ) {
|
351 |
+
$result = $this->query( $ddl );
|
352 |
+
return true;
|
353 |
+
}
|
354 |
+
/**
|
355 |
+
* Drop table
|
356 |
+
*
|
357 |
+
* @param string $tbl the table name
|
358 |
+
*
|
359 |
+
* @return boolean
|
360 |
+
*/
|
361 |
+
public function drop_table( $tbl ) {
|
362 |
+
$ddl = \sprintf( 'DROP TABLE IF EXISTS %s', $this->identifier( $tbl ) );
|
363 |
+
$result = $this->query( $ddl );
|
364 |
+
return true;
|
365 |
+
}
|
366 |
+
/**
|
367 |
+
* Create table
|
368 |
+
*
|
369 |
+
* @param string $table_name the table name
|
370 |
+
* @param array $options the options
|
371 |
+
* @return bool|Ruckusing_Adapter_MySQL_TableDefinition
|
372 |
+
*/
|
373 |
+
public function create_table( $table_name, $options = [] ) {
|
374 |
+
return new Ruckusing_Adapter_MySQL_TableDefinition( $this, $table_name, $options );
|
375 |
+
}
|
376 |
+
/**
|
377 |
+
* Escape a string for mysql
|
378 |
+
*
|
379 |
+
* @param string $str the string
|
380 |
+
*
|
381 |
+
* @return string
|
382 |
+
*/
|
383 |
+
public function quote_string( $str ) {
|
384 |
+
global $wpdb;
|
385 |
+
return $wpdb->_escape( $str );
|
386 |
+
}
|
387 |
+
/**
|
388 |
+
* Quote a string
|
389 |
+
*
|
390 |
+
* @param string $str the string
|
391 |
+
*
|
392 |
+
* @return string
|
393 |
+
*/
|
394 |
+
public function identifier( $str ) {
|
395 |
+
return '`' . $str . '`';
|
396 |
+
}
|
397 |
+
/**
|
398 |
+
* Quote a string
|
399 |
+
*
|
400 |
+
* @param string $value the string
|
401 |
+
* @param string $column the column
|
402 |
+
*
|
403 |
+
* @return string
|
404 |
+
*/
|
405 |
+
public function quote( $value, $column = null ) {
|
406 |
+
return $this->quote_string( $value );
|
407 |
+
}
|
408 |
+
/**
|
409 |
+
* Rename a table
|
410 |
+
*
|
411 |
+
* @param string $name the current table name
|
412 |
+
* @param string $new_name the new table name
|
413 |
+
*
|
414 |
+
* @throws Ruckusing_Exception
|
415 |
+
* @return boolean
|
416 |
+
*/
|
417 |
+
public function rename_table( $name, $new_name ) {
|
418 |
+
if ( empty( $name ) ) {
|
419 |
+
throw new Ruckusing_Exception( 'Missing original column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
420 |
+
}
|
421 |
+
if ( empty( $new_name ) ) {
|
422 |
+
throw new Ruckusing_Exception( 'Missing new column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
423 |
+
}
|
424 |
+
$sql = \sprintf( 'RENAME TABLE %s TO %s', $this->identifier( $name ), $this->identifier( $new_name ) );
|
425 |
+
return $this->execute_ddl( $sql );
|
426 |
+
}
|
427 |
+
// create_table
|
428 |
+
/**
|
429 |
+
* Add a column
|
430 |
+
*
|
431 |
+
* @param string $table_name the table name
|
432 |
+
* @param string $column_name the column name
|
433 |
+
* @param string $type the column type
|
434 |
+
* @param array $options column options
|
435 |
+
*
|
436 |
+
* @throws Ruckusing_Exception
|
437 |
+
* @return boolean
|
438 |
+
*/
|
439 |
+
public function add_column( $table_name, $column_name, $type, $options = [] ) {
|
440 |
+
if ( empty( $table_name ) ) {
|
441 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
442 |
+
}
|
443 |
+
if ( empty( $column_name ) ) {
|
444 |
+
throw new Ruckusing_Exception( 'Missing column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
445 |
+
}
|
446 |
+
if ( empty( $type ) ) {
|
447 |
+
throw new Ruckusing_Exception( 'Missing type parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
448 |
+
}
|
449 |
+
// default types
|
450 |
+
if ( ! \array_key_exists( 'limit', $options ) ) {
|
451 |
+
$options['limit'] = null;
|
452 |
+
}
|
453 |
+
if ( ! \array_key_exists( 'precision', $options ) ) {
|
454 |
+
$options['precision'] = null;
|
455 |
+
}
|
456 |
+
if ( ! \array_key_exists( 'scale', $options ) ) {
|
457 |
+
$options['scale'] = null;
|
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 |
+
*
|
467 |
+
* @param string $table_name the table name
|
468 |
+
* @param string $column_name the column name
|
469 |
+
*
|
470 |
+
* @return boolean
|
471 |
+
*/
|
472 |
+
public function remove_column( $table_name, $column_name ) {
|
473 |
+
$sql = \sprintf( 'ALTER TABLE %s DROP COLUMN %s', $this->identifier( $table_name ), $this->identifier( $column_name ) );
|
474 |
+
return $this->execute_ddl( $sql );
|
475 |
+
}
|
476 |
+
// remove_column
|
477 |
+
/**
|
478 |
+
* Rename a column
|
479 |
+
*
|
480 |
+
* @param string $table_name the table name
|
481 |
+
* @param string $column_name the column name
|
482 |
+
* @param string $new_column_name the new column name
|
483 |
+
*
|
484 |
+
* @throws Ruckusing_Exception
|
485 |
+
* @return boolean
|
486 |
+
*/
|
487 |
+
public function rename_column( $table_name, $column_name, $new_column_name ) {
|
488 |
+
if ( empty( $table_name ) ) {
|
489 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
490 |
+
}
|
491 |
+
if ( empty( $column_name ) ) {
|
492 |
+
throw new Ruckusing_Exception( 'Missing original column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
493 |
+
}
|
494 |
+
if ( empty( $new_column_name ) ) {
|
495 |
+
throw new Ruckusing_Exception( 'Missing new column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
496 |
+
}
|
497 |
+
$column_info = $this->column_info( $table_name, $column_name );
|
498 |
+
$current_type = $column_info['type'];
|
499 |
+
$sql = \sprintf( 'ALTER TABLE %s CHANGE %s %s %s', $this->identifier( $table_name ), $this->identifier( $column_name ), $this->identifier( $new_column_name ), $current_type );
|
500 |
+
$sql .= $this->add_column_options( $current_type, $column_info );
|
501 |
+
return $this->execute_ddl( $sql );
|
502 |
+
}
|
503 |
+
// rename_column
|
504 |
+
/**
|
505 |
+
* Change a column
|
506 |
+
*
|
507 |
+
* @param string $table_name the table name
|
508 |
+
* @param string $column_name the column name
|
509 |
+
* @param string $type the column type
|
510 |
+
* @param array $options column options
|
511 |
+
*
|
512 |
+
* @throws Ruckusing_Exception
|
513 |
+
* @return boolean
|
514 |
+
*/
|
515 |
+
public function change_column( $table_name, $column_name, $type, $options = [] ) {
|
516 |
+
if ( empty( $table_name ) ) {
|
517 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
518 |
+
}
|
519 |
+
if ( empty( $column_name ) ) {
|
520 |
+
throw new Ruckusing_Exception( 'Missing original column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
521 |
+
}
|
522 |
+
if ( empty( $type ) ) {
|
523 |
+
throw new Ruckusing_Exception( 'Missing type parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
524 |
+
}
|
525 |
+
$column_info = $this->column_info( $table_name, $column_name );
|
526 |
+
// default types
|
527 |
+
if ( ! \array_key_exists( 'limit', $options ) ) {
|
528 |
+
$options['limit'] = null;
|
529 |
+
}
|
530 |
+
if ( ! \array_key_exists( 'precision', $options ) ) {
|
531 |
+
$options['precision'] = null;
|
532 |
+
}
|
533 |
+
if ( ! \array_key_exists( 'scale', $options ) ) {
|
534 |
+
$options['scale'] = null;
|
535 |
+
}
|
536 |
+
$sql = \sprintf( 'ALTER TABLE `%s` CHANGE `%s` `%s` %s', $table_name, $column_name, $column_name, $this->type_to_sql( $type, $options ) );
|
537 |
+
$sql .= $this->add_column_options( $type, $options );
|
538 |
+
return $this->execute_ddl( $sql );
|
539 |
+
}
|
540 |
+
// change_column
|
541 |
+
/**
|
542 |
+
* Get a column info
|
543 |
+
*
|
544 |
+
* @param string $table the table name
|
545 |
+
* @param string $column the column name
|
546 |
+
*
|
547 |
+
* @throws Ruckusing_Exception
|
548 |
+
* @return array
|
549 |
+
*/
|
550 |
+
public function column_info( $table, $column ) {
|
551 |
+
if ( empty( $table ) ) {
|
552 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
553 |
+
}
|
554 |
+
if ( empty( $column ) ) {
|
555 |
+
throw new Ruckusing_Exception( 'Missing original column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
556 |
+
}
|
557 |
+
try {
|
558 |
+
$sql = \sprintf( "SHOW FULL COLUMNS FROM %s LIKE '%s'", $this->identifier( $table ), $column );
|
559 |
+
$result = $this->select_one( $sql );
|
560 |
+
if ( \is_array( $result ) ) {
|
561 |
+
// lowercase key names
|
562 |
+
$result = \array_change_key_case( $result, \CASE_LOWER );
|
563 |
+
}
|
564 |
+
return $result;
|
565 |
+
} catch (\Exception $e) {
|
566 |
+
return null;
|
567 |
+
}
|
568 |
+
}
|
569 |
+
/**
|
570 |
+
* Add an index
|
571 |
+
*
|
572 |
+
* @param string $table_name the table name
|
573 |
+
* @param string $column_name the column name
|
574 |
+
* @param array $options index options
|
575 |
+
*
|
576 |
+
* @throws Ruckusing_Exception
|
577 |
+
* @return boolean
|
578 |
+
*/
|
579 |
+
public function add_index( $table_name, $column_name, $options = [] ) {
|
580 |
+
if ( empty( $table_name ) ) {
|
581 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
582 |
+
}
|
583 |
+
if ( empty( $column_name ) ) {
|
584 |
+
throw new Ruckusing_Exception( 'Missing column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
585 |
+
}
|
586 |
+
// unique index?
|
587 |
+
if ( \is_array( $options ) && \array_key_exists( 'unique', $options ) && $options['unique'] === true ) {
|
588 |
+
$unique = true;
|
589 |
+
} else {
|
590 |
+
$unique = false;
|
591 |
+
}
|
592 |
+
// did the user specify an index name?
|
593 |
+
if ( \is_array( $options ) && \array_key_exists( 'name', $options ) ) {
|
594 |
+
$index_name = $options['name'];
|
595 |
+
} else {
|
596 |
+
$index_name = Ruckusing_Util_Naming::index_name( $table_name, $column_name );
|
597 |
+
}
|
598 |
+
if ( \strlen( $index_name ) > MYSQL_MAX_IDENTIFIER_LENGTH ) {
|
599 |
+
$msg = 'The auto-generated index name is too long for MySQL (max is 64 chars). ';
|
600 |
+
$msg .= "Considering using 'name' option parameter to specify a custom name for this index.";
|
601 |
+
$msg .= ' Note: you will also need to specify';
|
602 |
+
$msg .= ' this custom name in a drop_index() - if you have one.';
|
603 |
+
throw new Ruckusing_Exception( $msg, Ruckusing_Exception::INVALID_INDEX_NAME );
|
604 |
+
}
|
605 |
+
if ( ! \is_array( $column_name ) ) {
|
606 |
+
$column_names = [ $column_name ];
|
607 |
+
} else {
|
608 |
+
$column_names = $column_name;
|
609 |
+
}
|
610 |
+
$cols = [];
|
611 |
+
foreach ( $column_names as $name ) {
|
612 |
+
$cols[] = $this->identifier( $name );
|
613 |
+
}
|
614 |
+
$sql = \sprintf( 'CREATE %sINDEX %s ON %s(%s)', $unique ? 'UNIQUE ' : '', $this->identifier( $index_name ), $this->identifier( $table_name ), \join( ', ', $cols ) );
|
615 |
+
return $this->execute_ddl( $sql );
|
616 |
+
}
|
617 |
+
/**
|
618 |
+
* Drop an index
|
619 |
+
*
|
620 |
+
* @param string $table_name the table name
|
621 |
+
* @param string $column_name the column name
|
622 |
+
* @param array $options index options
|
623 |
+
*
|
624 |
+
* @throws Ruckusing_Exception
|
625 |
+
* @return boolean
|
626 |
+
*/
|
627 |
+
public function remove_index( $table_name, $column_name, $options = [] ) {
|
628 |
+
if ( empty( $table_name ) ) {
|
629 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
630 |
+
}
|
631 |
+
if ( empty( $column_name ) ) {
|
632 |
+
throw new Ruckusing_Exception( 'Missing column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
633 |
+
}
|
634 |
+
// did the user specify an index name?
|
635 |
+
if ( \is_array( $options ) && \array_key_exists( 'name', $options ) ) {
|
636 |
+
$index_name = $options['name'];
|
637 |
+
} else {
|
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 |
+
*
|
646 |
+
* @param string $table_name The table name
|
647 |
+
* @param string $created_column_name Created at column name
|
648 |
+
* @param string $updated_column_name Updated at column name
|
649 |
+
*
|
650 |
+
* @return boolean
|
651 |
+
*/
|
652 |
+
public function add_timestamps( $table_name, $created_column_name, $updated_column_name ) {
|
653 |
+
if ( empty( $table_name ) ) {
|
654 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
655 |
+
}
|
656 |
+
if ( empty( $created_column_name ) ) {
|
657 |
+
throw new Ruckusing_Exception( 'Missing created at column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
658 |
+
}
|
659 |
+
if ( empty( $updated_column_name ) ) {
|
660 |
+
throw new Ruckusing_Exception( 'Missing updated at column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
661 |
+
}
|
662 |
+
$created_at = $this->add_column( $table_name, $created_column_name, 'datetime' );
|
663 |
+
$updated_at = $this->add_column( $table_name, $updated_column_name, 'timestamp', [ 'null' => false, 'default' => 'CURRENT_TIMESTAMP', 'extra' => 'ON UPDATE CURRENT_TIMESTAMP' ] );
|
664 |
+
return $created_at && $updated_at;
|
665 |
+
}
|
666 |
+
/**
|
667 |
+
* Remove timestamps
|
668 |
+
*
|
669 |
+
* @param string $table_name The table name
|
670 |
+
* @param string $created_column_name Created at column name
|
671 |
+
* @param string $updated_column_name Updated at column name
|
672 |
+
*
|
673 |
+
* @return boolean
|
674 |
+
*/
|
675 |
+
public function remove_timestamps( $table_name, $created_column_name, $updated_column_name ) {
|
676 |
+
if ( empty( $table_name ) ) {
|
677 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
678 |
+
}
|
679 |
+
if ( empty( $created_column_name ) ) {
|
680 |
+
throw new Ruckusing_Exception( 'Missing created at column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
681 |
+
}
|
682 |
+
if ( empty( $updated_column_name ) ) {
|
683 |
+
throw new Ruckusing_Exception( 'Missing updated at column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
684 |
+
}
|
685 |
+
$updated_at = $this->remove_column( $table_name, $created_column_name );
|
686 |
+
$created_at = $this->remove_column( $table_name, $updated_column_name );
|
687 |
+
return $created_at && $updated_at;
|
688 |
+
}
|
689 |
+
/**
|
690 |
+
* Check an index
|
691 |
+
*
|
692 |
+
* @param string $table_name the table name
|
693 |
+
* @param string $column_name the column name
|
694 |
+
* @param array $options index options
|
695 |
+
*
|
696 |
+
* @throws Ruckusing_Exception
|
697 |
+
* @return boolean
|
698 |
+
*/
|
699 |
+
public function has_index( $table_name, $column_name, $options = [] ) {
|
700 |
+
if ( empty( $table_name ) ) {
|
701 |
+
throw new Ruckusing_Exception( 'Missing table name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
702 |
+
}
|
703 |
+
if ( empty( $column_name ) ) {
|
704 |
+
throw new Ruckusing_Exception( 'Missing column name parameter', Ruckusing_Exception::INVALID_ARGUMENT );
|
705 |
+
}
|
706 |
+
// did the user specify an index name?
|
707 |
+
if ( \is_array( $options ) && \array_key_exists( 'name', $options ) ) {
|
708 |
+
$index_name = $options['name'];
|
709 |
+
} else {
|
710 |
+
$index_name = Ruckusing_Util_Naming::index_name( $table_name, $column_name );
|
711 |
+
}
|
712 |
+
$indexes = $this->indexes( $table_name );
|
713 |
+
foreach ( $indexes as $idx ) {
|
714 |
+
if ( $idx['name'] == $index_name ) {
|
715 |
+
return true;
|
716 |
+
}
|
717 |
+
}
|
718 |
+
return false;
|
719 |
+
}
|
720 |
+
/**
|
721 |
+
* Return all indexes of a table
|
722 |
+
*
|
723 |
+
* @param string $table_name the table name
|
724 |
+
*
|
725 |
+
* @return array
|
726 |
+
*/
|
727 |
+
public function indexes( $table_name ) {
|
728 |
+
$sql = \sprintf( 'SHOW KEYS FROM %s', $this->identifier( $table_name ) );
|
729 |
+
$result = $this->select_all( $sql );
|
730 |
+
$indexes = [];
|
731 |
+
$cur_idx = null;
|
732 |
+
foreach ( $result as $row ) {
|
733 |
+
// skip primary
|
734 |
+
if ( $row['Key_name'] == 'PRIMARY' ) {
|
735 |
+
continue;
|
736 |
+
}
|
737 |
+
$cur_idx = $row['Key_name'];
|
738 |
+
$indexes[] = [ 'name' => $row['Key_name'], 'unique' => (int) $row['Non_unique'] == 0 ? true : false ];
|
739 |
+
}
|
740 |
+
return $indexes;
|
741 |
+
}
|
742 |
+
/**
|
743 |
+
* Convert type to sql
|
744 |
+
* $limit = null, $precision = null, $scale = null
|
745 |
+
*
|
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();
|
754 |
+
if ( ! \array_key_exists( $type, $natives ) ) {
|
755 |
+
$error = \sprintf( "Error:I dont know what column type of '%s' maps to for MySQL.", $type );
|
756 |
+
$error .= "\nYou provided: {$type}\n";
|
757 |
+
$error .= "Valid types are: \n";
|
758 |
+
$types = \array_keys( $natives );
|
759 |
+
foreach ( $types as $t ) {
|
760 |
+
if ( $t == 'primary_key' ) {
|
761 |
+
continue;
|
762 |
+
}
|
763 |
+
$error .= "\t{$t}\n";
|
764 |
+
}
|
765 |
+
throw new Ruckusing_Exception( $error, Ruckusing_Exception::INVALID_ARGUMENT );
|
766 |
+
}
|
767 |
+
$scale = null;
|
768 |
+
$precision = null;
|
769 |
+
$limit = null;
|
770 |
+
if ( isset( $options['precision'] ) ) {
|
771 |
+
$precision = $options['precision'];
|
772 |
+
}
|
773 |
+
if ( isset( $options['scale'] ) ) {
|
774 |
+
$scale = $options['scale'];
|
775 |
+
}
|
776 |
+
if ( isset( $options['limit'] ) ) {
|
777 |
+
$limit = $options['limit'];
|
778 |
+
}
|
779 |
+
if ( isset( $options['values'] ) ) {
|
780 |
+
$values = $options['values'];
|
781 |
+
}
|
782 |
+
$native_type = $natives[ $type ];
|
783 |
+
if ( \is_array( $native_type ) && \array_key_exists( 'name', $native_type ) ) {
|
784 |
+
$column_type_sql = $native_type['name'];
|
785 |
+
} else {
|
786 |
+
return $native_type;
|
787 |
+
}
|
788 |
+
if ( $type == 'decimal' ) {
|
789 |
+
// ignore limit, use precison and scale
|
790 |
+
if ( $precision == null && \array_key_exists( 'precision', $native_type ) ) {
|
791 |
+
$precision = $native_type['precision'];
|
792 |
+
}
|
793 |
+
if ( $scale == null && \array_key_exists( 'scale', $native_type ) ) {
|
794 |
+
$scale = $native_type['scale'];
|
795 |
+
}
|
796 |
+
if ( $precision != null ) {
|
797 |
+
if ( \is_int( $scale ) ) {
|
798 |
+
$column_type_sql .= \sprintf( '(%d, %d)', $precision, $scale );
|
799 |
+
} else {
|
800 |
+
$column_type_sql .= \sprintf( '(%d)', $precision );
|
801 |
+
}
|
802 |
+
// scale
|
803 |
+
} else {
|
804 |
+
if ( $scale ) {
|
805 |
+
throw new Ruckusing_Exception( 'Error adding decimal column: precision cannot be empty if scale is specified', Ruckusing_Exception::INVALID_ARGUMENT );
|
806 |
+
}
|
807 |
+
}
|
808 |
+
// precision
|
809 |
+
} elseif ( $type == 'float' ) {
|
810 |
+
// ignore limit, use precison and scale
|
811 |
+
if ( $precision == null && \array_key_exists( 'precision', $native_type ) ) {
|
812 |
+
$precision = $native_type['precision'];
|
813 |
+
}
|
814 |
+
if ( $scale == null && \array_key_exists( 'scale', $native_type ) ) {
|
815 |
+
$scale = $native_type['scale'];
|
816 |
+
}
|
817 |
+
if ( $precision != null ) {
|
818 |
+
if ( \is_int( $scale ) ) {
|
819 |
+
$column_type_sql .= \sprintf( '(%d, %d)', $precision, $scale );
|
820 |
+
} else {
|
821 |
+
$column_type_sql .= \sprintf( '(%d)', $precision );
|
822 |
+
}
|
823 |
+
// scale
|
824 |
+
} else {
|
825 |
+
if ( $scale ) {
|
826 |
+
throw new Ruckusing_Exception( 'Error adding float column: precision cannot be empty if scale is specified', Ruckusing_Exception::INVALID_ARGUMENT );
|
827 |
+
}
|
828 |
+
}
|
829 |
+
// precision
|
830 |
+
} elseif ( $type == 'enum' ) {
|
831 |
+
if ( empty( $values ) ) {
|
832 |
+
throw new Ruckusing_Exception( 'Error adding enum column: there must be at least one value defined', Ruckusing_Exception::INVALID_ARGUMENT );
|
833 |
+
} else {
|
834 |
+
$column_type_sql .= \sprintf( "('%s')", \implode( "','", \array_map( [ $this, 'quote_string' ], $values ) ) );
|
835 |
+
}
|
836 |
+
}
|
837 |
+
// not a decimal column
|
838 |
+
if ( $limit == null && \array_key_exists( 'limit', $native_type ) ) {
|
839 |
+
$limit = $native_type['limit'];
|
840 |
+
}
|
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 = '';
|
857 |
+
if ( ! \is_array( $options ) ) {
|
858 |
+
return $sql;
|
859 |
+
}
|
860 |
+
if ( \array_key_exists( 'unsigned', $options ) && $options['unsigned'] === true ) {
|
861 |
+
$sql .= ' UNSIGNED';
|
862 |
+
}
|
863 |
+
if ( \array_key_exists( 'character', $options ) ) {
|
864 |
+
$sql .= \sprintf( ' CHARACTER SET %s', $this->identifier( $options['character'] ) );
|
865 |
+
}
|
866 |
+
if ( \array_key_exists( 'collate', $options ) ) {
|
867 |
+
$sql .= \sprintf( ' COLLATE %s', $this->identifier( $options['collate'] ) );
|
868 |
+
}
|
869 |
+
if ( \array_key_exists( 'auto_increment', $options ) && $options['auto_increment'] === true ) {
|
870 |
+
$sql .= ' auto_increment';
|
871 |
+
}
|
872 |
+
if ( \array_key_exists( 'default', $options ) && $options['default'] !== null ) {
|
873 |
+
if ( $this->is_sql_method_call( $options['default'] ) ) {
|
874 |
+
// $default_value = $options['default'];
|
875 |
+
throw new Ruckusing_Exception( 'MySQL does not support function calls as default values, constants only.', Ruckusing_Exception::INVALID_ARGUMENT );
|
876 |
+
}
|
877 |
+
if ( \is_int( $options['default'] ) ) {
|
878 |
+
$default_format = '%d';
|
879 |
+
} elseif ( \is_bool( $options['default'] ) ) {
|
880 |
+
$default_format = "'%d'";
|
881 |
+
} elseif ( $options['default'] == 'CURRENT_TIMESTAMP' ) {
|
882 |
+
$default_format = '%s';
|
883 |
+
} else {
|
884 |
+
$default_format = "'%s'";
|
885 |
+
}
|
886 |
+
$default_value = \sprintf( $default_format, $options['default'] );
|
887 |
+
$sql .= \sprintf( ' DEFAULT %s', $default_value );
|
888 |
+
}
|
889 |
+
if ( \array_key_exists( 'null', $options ) ) {
|
890 |
+
if ( $options['null'] === false || $options['null'] === 'NO' ) {
|
891 |
+
$sql .= ' NOT NULL';
|
892 |
+
} elseif ( 'timestamp' === $type ) {
|
893 |
+
$sql .= ' NULL';
|
894 |
+
}
|
895 |
+
}
|
896 |
+
if ( \array_key_exists( 'comment', $options ) ) {
|
897 |
+
$sql .= \sprintf( " COMMENT '%s'", $this->quote_string( $options['comment'] ) );
|
898 |
+
}
|
899 |
+
if ( \array_key_exists( 'extra', $options ) ) {
|
900 |
+
$sql .= \sprintf( ' %s', $this->quote_string( $options['extra'] ) );
|
901 |
+
}
|
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 |
+
*
|
910 |
+
* @param string $version the version
|
911 |
+
*
|
912 |
+
* @return boolean
|
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 |
+
*
|
921 |
+
* @param string $version the version
|
922 |
+
*
|
923 |
+
* @return boolean
|
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 |
+
*
|
932 |
+
* @return string
|
933 |
+
*/
|
934 |
+
public function __toString() {
|
935 |
+
return 'Ruckusing_Adapter, version ' . $this->_version;
|
936 |
+
}
|
937 |
+
// -----------------------------------
|
938 |
+
// PRIVATE METHODS
|
939 |
+
// -----------------------------------
|
940 |
+
/**
|
941 |
+
* Delegate to PEAR
|
942 |
+
*
|
943 |
+
* @param boolean $o
|
944 |
+
*
|
945 |
+
* @return boolean
|
946 |
+
*/
|
947 |
+
private function isError( $o ) {
|
948 |
+
return $o === false;
|
949 |
+
}
|
950 |
+
/**
|
951 |
+
* Initialize an array of table names
|
952 |
+
*
|
953 |
+
* @param boolean $reload
|
954 |
+
*/
|
955 |
+
private function load_tables( $reload = true ) {
|
956 |
+
global $wpdb;
|
957 |
+
|
958 |
+
if ( $this->_tables_loaded == false || $reload ) {
|
959 |
+
$this->_tables = [];
|
960 |
+
// clear existing structure
|
961 |
+
$query = 'SHOW TABLES';
|
962 |
+
$res = $wpdb->get_results( $query, \ARRAY_N );
|
963 |
+
// check for errors
|
964 |
+
if ( $this->isError( $res ) ) {
|
965 |
+
throw new Ruckusing_Exception( \sprintf( "Error executing 'query' with:\n%s\n\nReason: %s\n\n", $query, $wpdb->last_error ), Ruckusing_Exception::QUERY_ERROR );
|
966 |
+
}
|
967 |
+
foreach ( $res as $row ) {
|
968 |
+
$table = $row[0];
|
969 |
+
$this->_tables[ $table ] = true;
|
970 |
+
}
|
971 |
+
}
|
972 |
+
}
|
973 |
+
/**
|
974 |
+
* Check query type
|
975 |
+
*
|
976 |
+
* @param string $query query to run
|
977 |
+
*
|
978 |
+
* @return int
|
979 |
+
*/
|
980 |
+
private function determine_query_type( $query ) {
|
981 |
+
$query = \strtolower( \trim( $query ) );
|
982 |
+
$match = [];
|
983 |
+
\preg_match( '/^(\\w)*/i', $query, $match );
|
984 |
+
$type = $match[0];
|
985 |
+
switch ( $type ) {
|
986 |
+
case 'select':
|
987 |
+
return SQL_SELECT;
|
988 |
+
case 'update':
|
989 |
+
return SQL_UPDATE;
|
990 |
+
case 'delete':
|
991 |
+
return SQL_DELETE;
|
992 |
+
case 'insert':
|
993 |
+
return SQL_INSERT;
|
994 |
+
case 'alter':
|
995 |
+
return SQL_ALTER;
|
996 |
+
case 'drop':
|
997 |
+
return SQL_DROP;
|
998 |
+
case 'create':
|
999 |
+
return SQL_CREATE;
|
1000 |
+
case 'show':
|
1001 |
+
return SQL_SHOW;
|
1002 |
+
case 'rename':
|
1003 |
+
return SQL_RENAME;
|
1004 |
+
case 'set':
|
1005 |
+
return SQL_SET;
|
1006 |
+
default:
|
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.
|
1027 |
+
*
|
1028 |
+
* @param string $str
|
1029 |
+
*
|
1030 |
+
* @return boolean
|
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 |
+
*
|
1043 |
+
* @return boolean
|
1044 |
+
*/
|
1045 |
+
private function inTransaction() {
|
1046 |
+
return $this->_in_trx;
|
1047 |
+
}
|
1048 |
+
/**
|
1049 |
+
* Start transaction
|
1050 |
+
*/
|
1051 |
+
private function beginTransaction() {
|
1052 |
+
global $wpdb;
|
1053 |
+
|
1054 |
+
if ( $this->_in_trx === true ) {
|
1055 |
+
throw new Ruckusing_Exception( 'Transaction already started', Ruckusing_Exception::QUERY_ERROR );
|
1056 |
+
}
|
1057 |
+
$wpdb->query( 'START TRANSACTION' );
|
1058 |
+
$this->_in_trx = true;
|
1059 |
+
}
|
1060 |
+
/**
|
1061 |
+
* Commit a transaction
|
1062 |
+
*/
|
1063 |
+
private function commit() {
|
1064 |
+
global $wpdb;
|
1065 |
+
|
1066 |
+
if ( $this->_in_trx === false ) {
|
1067 |
+
throw new Ruckusing_Exception( 'Transaction not started', Ruckusing_Exception::QUERY_ERROR );
|
1068 |
+
}
|
1069 |
+
$wpdb->query( 'COMMIT' );
|
1070 |
+
$this->_in_trx = false;
|
1071 |
+
}
|
1072 |
+
/**
|
1073 |
+
* Rollback a transaction
|
1074 |
+
*/
|
1075 |
+
private function rollback() {
|
1076 |
+
global $wpdb;
|
1077 |
+
|
1078 |
+
if ( $this->_in_trx === false ) {
|
1079 |
+
throw new Ruckusing_Exception( 'Transaction not started', Ruckusing_Exception::QUERY_ERROR );
|
1080 |
+
}
|
1081 |
+
$wpdb->query( 'ROLLBACK' );
|
1082 |
+
$this->_in_trx = false;
|
1083 |
+
}
|
1084 |
+
}
|
lib/ruckusing-framework-runner.php
ADDED
@@ -0,0 +1,266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Yoast ORM class.
|
4 |
+
*
|
5 |
+
* @package Yoast\WP\Lib
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Yoast\WP\Lib;
|
9 |
+
|
10 |
+
use YoastSEO_Vendor\Ruckusing_Exception;
|
11 |
+
use YoastSEO_Vendor\Ruckusing_FrameworkRunner;
|
12 |
+
use YoastSEO_Vendor\Ruckusing_Task_Manager;
|
13 |
+
use YoastSEO_Vendor\Ruckusing_Util_Migrator;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Ruckusing
|
17 |
+
*
|
18 |
+
* @category Ruckusing
|
19 |
+
* @package Ruckusing
|
20 |
+
* @author Cody Caughlan <codycaughlan % gmail . com>
|
21 |
+
* @link https://github.com/ruckus/ruckusing-migrations
|
22 |
+
*/
|
23 |
+
/**
|
24 |
+
* Ruckusing_FrameworkRunner
|
25 |
+
*
|
26 |
+
* Primary work-horse class. This class bootstraps the framework by loading
|
27 |
+
* all adapters and tasks.
|
28 |
+
*
|
29 |
+
* @category Ruckusing
|
30 |
+
* @package Ruckusing
|
31 |
+
* @author Cody Caughlan <codycaughlan % gmail . com>
|
32 |
+
* @link https://github.com/ruckus/ruckusing-migrations
|
33 |
+
*/
|
34 |
+
class Ruckusing_Framework_Runner extends Ruckusing_FrameworkRunner {
|
35 |
+
/**
|
36 |
+
* Available DB config (e.g. test,development, production)
|
37 |
+
*
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
private $_config = [];
|
41 |
+
/**
|
42 |
+
* Task manager
|
43 |
+
*
|
44 |
+
* @var Ruckusing_Task_Manager
|
45 |
+
*/
|
46 |
+
private $_task_mgr = null;
|
47 |
+
/**
|
48 |
+
* Adapter
|
49 |
+
*
|
50 |
+
* @var Ruckusing_Adapter_Base
|
51 |
+
*/
|
52 |
+
private $_adapter = null;
|
53 |
+
/**
|
54 |
+
* Current task name
|
55 |
+
*
|
56 |
+
* @var string
|
57 |
+
*/
|
58 |
+
private $_cur_task_name = '';
|
59 |
+
/**
|
60 |
+
* Task options
|
61 |
+
*
|
62 |
+
* @var string
|
63 |
+
*/
|
64 |
+
private $_task_options = '';
|
65 |
+
/**
|
66 |
+
* Environment
|
67 |
+
* default is development
|
68 |
+
* but can also be one 'test', 'production', etc...
|
69 |
+
*
|
70 |
+
* @var string
|
71 |
+
*/
|
72 |
+
private $_env = 'development';
|
73 |
+
/**
|
74 |
+
* Flag to display help of task
|
75 |
+
*
|
76 |
+
* @see Ruckusing_FrameworkRunner::parse_args
|
77 |
+
*
|
78 |
+
* @var boolean
|
79 |
+
*/
|
80 |
+
private $_showhelp = \false;
|
81 |
+
/**
|
82 |
+
* Creates an instance of Ruckusing_Adapters_Base
|
83 |
+
*
|
84 |
+
* @param array $config The current config.
|
85 |
+
* @param array $argv the supplied command line arguments.
|
86 |
+
*
|
87 |
+
* @return Ruckusing_FrameworkRunner
|
88 |
+
*/
|
89 |
+
public function __construct( $config, $argv ) {
|
90 |
+
\set_error_handler( [ Ruckusing_Exception::class, 'errorHandler' ], \E_ALL );
|
91 |
+
\set_exception_handler( [ Ruckusing_Exception::class, 'exceptionHandler' ] );
|
92 |
+
// Parse arguments.
|
93 |
+
$this->parse_args( $argv );
|
94 |
+
// Set config variables.
|
95 |
+
$this->_config = $config;
|
96 |
+
// Verify config array.
|
97 |
+
$this->initialize_db();
|
98 |
+
// Initialize tasks.
|
99 |
+
$this->init_tasks();
|
100 |
+
}
|
101 |
+
/**
|
102 |
+
* Execute the current task
|
103 |
+
*/
|
104 |
+
public function execute() {
|
105 |
+
$output = '';
|
106 |
+
if ( empty( $this->_cur_task_name ) ) {
|
107 |
+
if ( isset( $_SERVER['argv'][1] ) && \stripos( $_SERVER['argv'][1], '=' ) === \false ) {
|
108 |
+
$output .= \sprintf( "\n\tWrong Task format: %s\n", $_SERVER['argv'][1] );
|
109 |
+
}
|
110 |
+
$output .= $this->help();
|
111 |
+
} else {
|
112 |
+
if ( $this->_task_mgr->has_task( $this->_cur_task_name ) ) {
|
113 |
+
if ( $this->_showhelp ) {
|
114 |
+
$output .= $this->_task_mgr->help( $this->_cur_task_name );
|
115 |
+
} else {
|
116 |
+
$output .= $this->_task_mgr->execute( $this, $this->_cur_task_name, $this->_task_options );
|
117 |
+
}
|
118 |
+
} else {
|
119 |
+
$output .= \sprintf( "\n\tTask not found: %s\n", $this->_cur_task_name );
|
120 |
+
$output .= $this->help();
|
121 |
+
}
|
122 |
+
}
|
123 |
+
return $output;
|
124 |
+
}
|
125 |
+
/**
|
126 |
+
* Get the current adapter
|
127 |
+
*
|
128 |
+
* @return object
|
129 |
+
*/
|
130 |
+
public function get_adapter() {
|
131 |
+
return $this->_adapter;
|
132 |
+
}
|
133 |
+
/**
|
134 |
+
* Initialize the task manager
|
135 |
+
*/
|
136 |
+
public function init_tasks() {
|
137 |
+
$this->_task_mgr = new Ruckusing_Task_Manager( $this->_adapter, $this->_config );
|
138 |
+
}
|
139 |
+
/**
|
140 |
+
* Get the current migration dir
|
141 |
+
*
|
142 |
+
* @param string $key the module key name.
|
143 |
+
*
|
144 |
+
* @return string
|
145 |
+
*/
|
146 |
+
public function migrations_directory( $key = '' ) {
|
147 |
+
$migration_dir = '';
|
148 |
+
if ( $key ) {
|
149 |
+
if ( ! isset( $this->_config['migrations_dir'][ $key ] ) ) {
|
150 |
+
throw new Ruckusing_Exception( \sprintf( 'No module %s migration_dir set in config', $key ), Ruckusing_Exception::INVALID_CONFIG );
|
151 |
+
}
|
152 |
+
$migration_dir = $this->_config['migrations_dir'][ $key ] . \DIRECTORY_SEPARATOR;
|
153 |
+
}
|
154 |
+
elseif ( \is_array( $this->_config['migrations_dir'] ) ) {
|
155 |
+
$migration_dir = $this->_config['migrations_dir']['default'] . \DIRECTORY_SEPARATOR;
|
156 |
+
}
|
157 |
+
else {
|
158 |
+
$migration_dir = $this->_config['migrations_dir'] . \DIRECTORY_SEPARATOR;
|
159 |
+
}
|
160 |
+
if ( \array_key_exists( 'directory', $this->_config['db'][ $this->_env ] ) ) {
|
161 |
+
return $migration_dir . $this->_config['db'][ $this->_env ]['directory'];
|
162 |
+
}
|
163 |
+
return $migration_dir . $this->_config['db'][ $this->_env ]['database'];
|
164 |
+
}
|
165 |
+
/**
|
166 |
+
* Get all migrations directory
|
167 |
+
*
|
168 |
+
* @return array
|
169 |
+
*/
|
170 |
+
public function migrations_directories() {
|
171 |
+
$result = [];
|
172 |
+
if ( \is_array( $this->_config['migrations_dir'] ) ) {
|
173 |
+
foreach ( $this->_config['migrations_dir'] as $name => $path ) {
|
174 |
+
$result[ $name ] = $path . \DIRECTORY_SEPARATOR;
|
175 |
+
}
|
176 |
+
} else {
|
177 |
+
$result['default'] = $this->_config['migrations_dir'] . \DIRECTORY_SEPARATOR;
|
178 |
+
}
|
179 |
+
return $result;
|
180 |
+
}
|
181 |
+
/**
|
182 |
+
* Get the current db schema dir
|
183 |
+
*
|
184 |
+
* @return string
|
185 |
+
*/
|
186 |
+
public function db_directory() {
|
187 |
+
$path = $this->_config['db_dir'] . \DIRECTORY_SEPARATOR;
|
188 |
+
if ( \array_key_exists( 'directory', $this->_config['db'][ $this->_env ] ) ) {
|
189 |
+
return $path . $this->_config['db'][ $this->_env ]['directory'];
|
190 |
+
}
|
191 |
+
return $path . $this->_config['db'][ $this->_env ]['database'];
|
192 |
+
}
|
193 |
+
/**
|
194 |
+
* Initialize the db
|
195 |
+
*/
|
196 |
+
public function initialize_db() {
|
197 |
+
$db = $this->_config['db'][ $this->_env ];
|
198 |
+
$this->_adapter = new Ruckusing_Adapter( $db );
|
199 |
+
}
|
200 |
+
/**
|
201 |
+
* $argv is our complete command line argument set.
|
202 |
+
* PHP gives us:
|
203 |
+
* [0] = the actual file name we're executing
|
204 |
+
* [1..N] = all other arguments
|
205 |
+
*
|
206 |
+
* Our task name should be at slot [1]
|
207 |
+
* Anything else are additional parameters that we can pass
|
208 |
+
* to our task and they can deal with them as they see fit.
|
209 |
+
*
|
210 |
+
* @param array $argv the current command line arguments
|
211 |
+
*/
|
212 |
+
private function parse_args( $argv ) {
|
213 |
+
$num_args = \count( $argv );
|
214 |
+
$options = [];
|
215 |
+
for ( $i = 0; $i < $num_args; $i++ ) {
|
216 |
+
$arg = $argv[ $i ];
|
217 |
+
if ( \stripos( $arg, ':' ) !== \false ) {
|
218 |
+
$this->_cur_task_name = $arg;
|
219 |
+
} elseif ( $arg == 'help' ) {
|
220 |
+
$this->_showhelp = \true;
|
221 |
+
continue;
|
222 |
+
} elseif ( \stripos( $arg, '=' ) !== \false ) {
|
223 |
+
list($key, $value) = \explode( '=', $arg );
|
224 |
+
$key = \strtolower( $key );
|
225 |
+
// Allow both upper and lower case parameters
|
226 |
+
$options[ $key ] = $value;
|
227 |
+
if ( $key == 'env' ) {
|
228 |
+
$this->_env = $value;
|
229 |
+
}
|
230 |
+
}
|
231 |
+
}
|
232 |
+
$this->_task_options = $options;
|
233 |
+
}
|
234 |
+
/**
|
235 |
+
* Update the local schema to handle multiple records versus the prior architecture
|
236 |
+
* of storing a single version. In addition take all existing migration files
|
237 |
+
* and register them in our new table, as they have already been executed.
|
238 |
+
*/
|
239 |
+
public function update_schema_for_timestamps() {
|
240 |
+
// only create the table if it doesnt already exist
|
241 |
+
$this->_adapter->create_schema_version_table();
|
242 |
+
// insert all existing records into our new table
|
243 |
+
$migrator_util = new Ruckusing_Util_Migrator( $this->_adapter );
|
244 |
+
$files = $migrator_util->get_migration_files( $this->migrations_directories(), 'up' );
|
245 |
+
foreach ( $files as $file ) {
|
246 |
+
if ( (int) $file['version'] >= \PHP_INT_MAX ) {
|
247 |
+
// its new style like '20081010170207' so its not a candidate
|
248 |
+
continue;
|
249 |
+
}
|
250 |
+
// query old table, if it less than or equal to our max version, then its a candidate for insertion
|
251 |
+
$query_sql = \sprintf( 'SELECT version FROM %s WHERE version >= %d', \YoastSEO_Vendor\RUCKUSING_SCHEMA_TBL_NAME, $file['version'] );
|
252 |
+
$existing_version_old_style = $this->_adapter->select_one( $query_sql );
|
253 |
+
if ( \count( $existing_version_old_style ) > 0 ) {
|
254 |
+
// make sure it doesnt exist in our new table, who knows how it got inserted?
|
255 |
+
$new_vers_sql = \sprintf( 'SELECT version FROM %s WHERE version = %d', $this->_adapter->get_schema_version_table_name(), $file['version'] );
|
256 |
+
$existing_version_new_style = $this->_adapter->select_one( $new_vers_sql );
|
257 |
+
if ( empty( $existing_version_new_style ) ) {
|
258 |
+
// use sprintf & %d to force it to be stripped of any leading zeros, we *know* this represents an old version style
|
259 |
+
// so we dont have to worry about PHP and integer overflow
|
260 |
+
$insert_sql = \sprintf( 'INSERT INTO %s (version) VALUES (%d)', $this->_adapter->get_schema_version_table_name(), $file['version'] );
|
261 |
+
$this->_adapter->query( $insert_sql );
|
262 |
+
}
|
263 |
+
}
|
264 |
+
}
|
265 |
+
}
|
266 |
+
}
|
migrations/20171228151840_WpYoastIndexable.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
@@ -155,6 +155,6 @@ class WpYoastIndexable extends Ruckusing_Migration_Base {
|
|
155 |
* @return string The table name to use.
|
156 |
*/
|
157 |
protected function get_table_name() {
|
158 |
-
return
|
159 |
}
|
160 |
}
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
+
use Yoast\WP\Lib\Model;
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
155 |
* @return string The table name to use.
|
156 |
*/
|
157 |
protected function get_table_name() {
|
158 |
+
return Model::get_table_name( 'Indexable' );
|
159 |
}
|
160 |
}
|
migrations/20171228151841_WpYoastPrimaryTerm.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
@@ -91,6 +91,6 @@ class WpYoastPrimaryTerm extends Ruckusing_Migration_Base {
|
|
91 |
* @return string Table name to use.
|
92 |
*/
|
93 |
protected function get_table_name() {
|
94 |
-
return
|
95 |
}
|
96 |
}
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
+
use Yoast\WP\Lib\Model;
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
91 |
* @return string Table name to use.
|
92 |
*/
|
93 |
protected function get_table_name() {
|
94 |
+
return Model::get_table_name( 'Primary_Term' );
|
95 |
}
|
96 |
}
|
migrations/20190529075038_WpYoastDropIndexableMetaTableIfExists.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
@@ -36,6 +36,6 @@ class WpYoastDropIndexableMetaTableIfExists extends Ruckusing_Migration_Base {
|
|
36 |
* @return string The table name to use.
|
37 |
*/
|
38 |
protected function get_table_name() {
|
39 |
-
return
|
40 |
}
|
41 |
}
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
+
use Yoast\WP\Lib\Model;
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
36 |
* @return string The table name to use.
|
37 |
*/
|
38 |
protected function get_table_name() {
|
39 |
+
return Model::get_table_name( 'Indexable_Meta' );
|
40 |
}
|
41 |
}
|
migrations/20191011111109_WpYoastIndexableHierarchy.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
@@ -53,6 +53,6 @@ class WpYoastIndexableHierarchy extends Ruckusing_Migration_Base {
|
|
53 |
* @return string The table name to use.
|
54 |
*/
|
55 |
protected function get_table_name() {
|
56 |
-
return
|
57 |
}
|
58 |
}
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
+
use Yoast\WP\Lib\Model;
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
53 |
* @return string The table name to use.
|
54 |
*/
|
55 |
protected function get_table_name() {
|
56 |
+
return Model::get_table_name( 'Indexable_Hierarchy' );
|
57 |
}
|
58 |
}
|
migrations/20200408101900_AddCollationToTables.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
@@ -25,10 +25,10 @@ class AddCollationToTables extends Ruckusing_Migration_Base {
|
|
25 |
}
|
26 |
|
27 |
$tables = [
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
];
|
33 |
|
34 |
foreach ( $tables as $table ) {
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
+
use Yoast\WP\Lib\Model;
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
25 |
}
|
26 |
|
27 |
$tables = [
|
28 |
+
Model::get_table_name( 'migrations' ),
|
29 |
+
Model::get_table_name( 'Indexable' ),
|
30 |
+
Model::get_table_name( 'Indexable_Hierarchy' ),
|
31 |
+
Model::get_table_name( 'Primary_Term' ),
|
32 |
];
|
33 |
|
34 |
foreach ( $tables as $table ) {
|
migrations/20200420073606_AddColumnsToIndexables.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
@@ -56,7 +56,7 @@ class AddColumnsToIndexables extends Ruckusing_Migration_Base {
|
|
56 |
* @return string The Indexable table name.
|
57 |
*/
|
58 |
protected function get_indexable_table() {
|
59 |
-
return
|
60 |
}
|
61 |
|
62 |
/**
|
@@ -67,8 +67,8 @@ class AddColumnsToIndexables extends Ruckusing_Migration_Base {
|
|
67 |
protected function get_tables() {
|
68 |
return [
|
69 |
$this->get_indexable_table(),
|
70 |
-
|
71 |
-
|
72 |
];
|
73 |
}
|
74 |
}
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
+
use Yoast\WP\Lib\Model;
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
56 |
* @return string The Indexable table name.
|
57 |
*/
|
58 |
protected function get_indexable_table() {
|
59 |
+
return Model::get_table_name( 'Indexable' );
|
60 |
}
|
61 |
|
62 |
/**
|
67 |
protected function get_tables() {
|
68 |
return [
|
69 |
$this->get_indexable_table(),
|
70 |
+
Model::get_table_name( 'Indexable_Hierarchy' ),
|
71 |
+
Model::get_table_name( 'Primary_Term' ),
|
72 |
];
|
73 |
}
|
74 |
}
|
migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
-
use Yoast\WP\
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
@@ -38,7 +38,7 @@ class BreadcrumbTitleAndHierarchyReset extends Ruckusing_Migration_Base {
|
|
38 |
* @return string The table name to use.
|
39 |
*/
|
40 |
protected function get_indexable_table_name() {
|
41 |
-
return
|
42 |
}
|
43 |
|
44 |
/**
|
@@ -47,6 +47,6 @@ class BreadcrumbTitleAndHierarchyReset extends Ruckusing_Migration_Base {
|
|
47 |
* @return string The table name to use.
|
48 |
*/
|
49 |
protected function get_indexable_hierarchy_table_name() {
|
50 |
-
return
|
51 |
}
|
52 |
}
|
5 |
* @package WPSEO\Migrations
|
6 |
*/
|
7 |
|
8 |
+
use Yoast\WP\Lib\Model;
|
9 |
use YoastSEO_Vendor\Ruckusing_Migration_Base;
|
10 |
|
11 |
/**
|
38 |
* @return string The table name to use.
|
39 |
*/
|
40 |
protected function get_indexable_table_name() {
|
41 |
+
return Model::get_table_name( 'Indexable' );
|
42 |
}
|
43 |
|
44 |
/**
|
47 |
* @return string The table name to use.
|
48 |
*/
|
49 |
protected function get_indexable_hierarchy_table_name() {
|
50 |
+
return Model::get_table_name( 'Indexable_Hierarchy' );
|
51 |
}
|
52 |
}
|
migrations/20200428194858_ExpandIndexableColumnLengths.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
* ExpandIndexableColumnLengths
|
13 |
+
*/
|
14 |
+
class ExpandIndexableColumnLengths extends Ruckusing_Migration_Base {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Migration up.
|
18 |
+
*/
|
19 |
+
public function up() {
|
20 |
+
$this->change_column( $this->get_table_name(), 'title', 'text', [ 'null' => true ] );
|
21 |
+
$this->change_column( $this->get_table_name(), 'open_graph_title', 'text', [ 'null' => true ] );
|
22 |
+
$this->change_column( $this->get_table_name(), 'twitter_title', 'text', [ 'null' => true ] );
|
23 |
+
$this->change_column( $this->get_table_name(), 'open_graph_image_source', 'text', [ 'null' => true ] );
|
24 |
+
$this->change_column( $this->get_table_name(), 'twitter_image_source', 'text', [ 'null' => true ] );
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Migration down.
|
29 |
+
*/
|
30 |
+
public function down() {
|
31 |
+
$this->change_column(
|
32 |
+
$this->get_table_name(),
|
33 |
+
'title',
|
34 |
+
'string',
|
35 |
+
[ 'null' => true, 'limit' => 191 ]
|
36 |
+
);
|
37 |
+
$this->change_column(
|
38 |
+
$this->get_table_name(),
|
39 |
+
'opengraph_title',
|
40 |
+
'string',
|
41 |
+
[ 'null' => true, 'limit' => 191 ]
|
42 |
+
);
|
43 |
+
$this->change_column(
|
44 |
+
$this->get_table_name(),
|
45 |
+
'twitter_title',
|
46 |
+
'string',
|
47 |
+
[ 'null' => true, 'limit' => 191 ]
|
48 |
+
);
|
49 |
+
$this->change_column(
|
50 |
+
$this->get_table_name(),
|
51 |
+
'open_graph_image_source',
|
52 |
+
'string',
|
53 |
+
[ 'null' => true, 'limit' => 191 ]
|
54 |
+
);
|
55 |
+
$this->change_column(
|
56 |
+
$this->get_table_name(),
|
57 |
+
'twitter_image_source',
|
58 |
+
'string',
|
59 |
+
[ 'null' => true, 'limit' => 191 ]
|
60 |
+
);
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Retrieves the table name to use for storing indexables.
|
65 |
+
*
|
66 |
+
* @return string The table name to use.
|
67 |
+
*/
|
68 |
+
protected function get_table_name() {
|
69 |
+
return Model::get_table_name( 'Indexable' );
|
70 |
+
}
|
71 |
+
}
|
migrations/20200429105310_TruncateIndexableTables.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
* TruncateIndexableTables
|
13 |
+
*/
|
14 |
+
class TruncateIndexableTables extends Ruckusing_Migration_Base {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Migration up.
|
18 |
+
*/
|
19 |
+
public function up() {
|
20 |
+
$this->query( 'TRUNCATE TABLE ' . $this->get_indexable_table_name() );
|
21 |
+
$this->query( 'TRUNCATE TABLE ' . $this->get_indexable_hierarchy_table_name() );
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Migration down.
|
26 |
+
*/
|
27 |
+
public function down() {
|
28 |
+
// Nothing to do.
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Retrieves the table name to use for storing indexables.
|
33 |
+
*
|
34 |
+
* @return string The table name to use.
|
35 |
+
*/
|
36 |
+
protected function get_indexable_table_name() {
|
37 |
+
return Model::get_table_name( 'Indexable' );
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Retrieves the table name to use.
|
42 |
+
*
|
43 |
+
* @return string The table name to use.
|
44 |
+
*/
|
45 |
+
protected function get_indexable_hierarchy_table_name() {
|
46 |
+
return Model::get_table_name( 'Indexable_Hierarchy' );
|
47 |
+
}
|
48 |
+
}
|
polyfills/pdo/pdo-mysqli-polyfill.php
DELETED
@@ -1,297 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* These are polyfills of PDO in case the extension isn't loaded.
|
4 |
-
*
|
5 |
-
* This code is primarily based on the MySQLi driver for Doctrine.
|
6 |
-
*
|
7 |
-
* The Doctrine license is included below:
|
8 |
-
*
|
9 |
-
* Copyright (c) 2006-2018 Doctrine Project
|
10 |
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
11 |
-
* this software and associated documentation files (the "Software"), to deal in
|
12 |
-
* the Software without restriction, including without limitation the rights to
|
13 |
-
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
14 |
-
* of the Software, and to permit persons to whom the Software is furnished to do
|
15 |
-
* so, subject to the following conditions:
|
16 |
-
*
|
17 |
-
* The above copyright notice and this permission notice shall be included in all
|
18 |
-
* copies or substantial portions of the Software.
|
19 |
-
*
|
20 |
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21 |
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22 |
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23 |
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24 |
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25 |
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26 |
-
* SOFTWARE.
|
27 |
-
*/
|
28 |
-
|
29 |
-
namespace Yoast\WP\Polyfills\PDO;
|
30 |
-
|
31 |
-
class PDO_MySQLi_Polyfill {
|
32 |
-
/**
|
33 |
-
* Name of the option to set connection flags
|
34 |
-
*/
|
35 |
-
const OPTION_FLAGS = 'flags';
|
36 |
-
|
37 |
-
/** @var mysqli */
|
38 |
-
private $conn;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* @param array<string, mixed> $params The params.
|
42 |
-
* @param array<int, mixed> $driverOptions The driver options.
|
43 |
-
*
|
44 |
-
* @throws \Exception
|
45 |
-
*/
|
46 |
-
public function __construct( $params, $username, $password, $driverOptions = [] ) {
|
47 |
-
if ( is_string( $params ) ) {
|
48 |
-
$config = substr( $params, 6 );
|
49 |
-
$parts = explode( ';', $config );
|
50 |
-
$params = [];
|
51 |
-
foreach ( $parts as $part ) {
|
52 |
-
if ( strpos( $part, '=' ) === false ) {
|
53 |
-
continue;
|
54 |
-
}
|
55 |
-
list( $key, $value ) = explode( '=', $part );
|
56 |
-
$params[ $key ] = $value;
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
|
61 |
-
$port = isset( $params['port'] ) ? $params['port'] : (int) ini_get( 'mysqli.default_port' );
|
62 |
-
|
63 |
-
// Fallback to default MySQL port if not given.
|
64 |
-
if ( ! $port ) {
|
65 |
-
$port = 3306;
|
66 |
-
}
|
67 |
-
|
68 |
-
$socket = isset( $params['unix_socket'] ) ? $params['unix_socket'] : ini_get( 'mysqli.default_socket' );
|
69 |
-
$dbname = isset( $params['dbname'] ) ? $params['dbname'] : '';
|
70 |
-
$host = $params['host'];
|
71 |
-
|
72 |
-
if ( ! empty( $params['persistent'] ) ) {
|
73 |
-
$host = 'p:' . $host;
|
74 |
-
}
|
75 |
-
|
76 |
-
$flags = isset( $driverOptions[ static::OPTION_FLAGS ] ) ? $driverOptions[ static::OPTION_FLAGS ] : 0;
|
77 |
-
|
78 |
-
$this->conn = mysqli_init();
|
79 |
-
|
80 |
-
$this->setSecureConnection( $params );
|
81 |
-
$this->setDriverOptions( $driverOptions );
|
82 |
-
|
83 |
-
set_error_handler(static function () {
|
84 |
-
return true;
|
85 |
-
});
|
86 |
-
try {
|
87 |
-
if ( ! $this->conn->real_connect( $host, $username, $password, $dbname, $port, $socket, $flags ) ) {
|
88 |
-
throw new \Exception( $this->conn->error, $this->conn->errno );
|
89 |
-
}
|
90 |
-
} finally {
|
91 |
-
restore_error_handler();
|
92 |
-
}
|
93 |
-
|
94 |
-
if ( ! isset( $params['charset'] ) ) {
|
95 |
-
return;
|
96 |
-
}
|
97 |
-
|
98 |
-
$this->conn->set_charset( $params['charset'] );
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Retrieves mysqli native resource handle.
|
103 |
-
*
|
104 |
-
* Could be used if part of your application is not using DBAL.
|
105 |
-
*/
|
106 |
-
public function getWrappedResourceHandle() {
|
107 |
-
return $this->conn;
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* @inheritdoc
|
112 |
-
*
|
113 |
-
* The server version detection includes a special case for MariaDB
|
114 |
-
* to support '5.5.5-' prefixed versions introduced in Maria 10+
|
115 |
-
*
|
116 |
-
* @link https://jira.mariadb.org/browse/MDEV-4088
|
117 |
-
*/
|
118 |
-
public function getServerVersion() {
|
119 |
-
$serverInfos = $this->conn->get_server_info();
|
120 |
-
if ( stripos( $serverInfos, 'mariadb' ) !== false ) {
|
121 |
-
return $serverInfos;
|
122 |
-
}
|
123 |
-
|
124 |
-
$majorVersion = floor( $this->conn->server_version / 10000 );
|
125 |
-
$minorVersion = floor( ($this->conn->server_version - $majorVersion * 10000) / 100 );
|
126 |
-
$patchVersion = floor( $this->conn->server_version - $majorVersion * 10000 - $minorVersion * 100 );
|
127 |
-
|
128 |
-
return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
|
129 |
-
}
|
130 |
-
|
131 |
-
/**
|
132 |
-
* @inheritDoc
|
133 |
-
*/
|
134 |
-
public function prepare( $sql ) {
|
135 |
-
return new PDO_MySQLi_Statement_Polyfill( $this->conn, $sql );
|
136 |
-
}
|
137 |
-
|
138 |
-
/**
|
139 |
-
* @inheritDoc
|
140 |
-
*/
|
141 |
-
public function query( $sql ) {
|
142 |
-
$stmt = $this->prepare( $sql );
|
143 |
-
$stmt->execute();
|
144 |
-
|
145 |
-
return $stmt;
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* @inheritDoc
|
150 |
-
*/
|
151 |
-
public function quote( $input ) {
|
152 |
-
return "'" . $this->conn->escape_string( $input ) . "'";
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* @inheritDoc
|
157 |
-
*/
|
158 |
-
public function exec( $statement ) {
|
159 |
-
if ( $this->conn->query( $statement ) === false ) {
|
160 |
-
throw new \Exception( $this->conn->error, $this->conn->errno );
|
161 |
-
}
|
162 |
-
|
163 |
-
return $this->conn->affected_rows;
|
164 |
-
}
|
165 |
-
|
166 |
-
/**
|
167 |
-
* @inheritDoc
|
168 |
-
*/
|
169 |
-
public function lastInsertId( $name = null ) {
|
170 |
-
return (string) $this->conn->insert_id;
|
171 |
-
}
|
172 |
-
|
173 |
-
/**
|
174 |
-
* @inheritDoc
|
175 |
-
*/
|
176 |
-
public function beginTransaction() {
|
177 |
-
$this->conn->query( 'START TRANSACTION' );
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* @inheritDoc
|
182 |
-
*/
|
183 |
-
public function commit() {
|
184 |
-
if ( ! $this->conn->commit() ) {
|
185 |
-
throw new \Exception( $this->conn->error, $this->conn->errno );
|
186 |
-
}
|
187 |
-
}
|
188 |
-
|
189 |
-
/**
|
190 |
-
* @inheritDoc
|
191 |
-
*/
|
192 |
-
public function rollBack() {
|
193 |
-
if ( ! $this->conn->rollback() ) {
|
194 |
-
throw new \Exception( $this->conn->error, $this->conn->errno );
|
195 |
-
}
|
196 |
-
}
|
197 |
-
|
198 |
-
/**
|
199 |
-
* Apply the driver options to the connection.
|
200 |
-
*
|
201 |
-
* @param array<int, mixed> $driverOptions
|
202 |
-
*
|
203 |
-
* @throws \Exception When one of of the options is not supported.
|
204 |
-
* @throws \Exception When applying doesn't work - e.g. due to incorrect value.
|
205 |
-
*/
|
206 |
-
private function setDriverOptions( $driverOptions = [] ) {
|
207 |
-
if ( empty( $driverOptions ) ) {
|
208 |
-
return;
|
209 |
-
}
|
210 |
-
|
211 |
-
$supportedDriverOptions = [
|
212 |
-
MYSQLI_OPT_CONNECT_TIMEOUT,
|
213 |
-
MYSQLI_OPT_LOCAL_INFILE,
|
214 |
-
MYSQLI_INIT_COMMAND,
|
215 |
-
MYSQLI_READ_DEFAULT_FILE,
|
216 |
-
MYSQLI_READ_DEFAULT_GROUP,
|
217 |
-
];
|
218 |
-
|
219 |
-
if ( defined( 'MYSQLI_SERVER_PUBLIC_KEY' ) ) {
|
220 |
-
$supportedDriverOptions[] = MYSQLI_SERVER_PUBLIC_KEY;
|
221 |
-
}
|
222 |
-
|
223 |
-
$exceptionMsg = "%s option '%s' with value '%s'";
|
224 |
-
|
225 |
-
foreach ( $driverOptions as $option => $value ) {
|
226 |
-
if ( $option === static::OPTION_FLAGS ) {
|
227 |
-
continue;
|
228 |
-
}
|
229 |
-
|
230 |
-
if ( ! in_array( $option, $supportedDriverOptions, true ) ) {
|
231 |
-
throw new \Exception(
|
232 |
-
sprintf( $exceptionMsg, 'Unsupported', $option, $value )
|
233 |
-
);
|
234 |
-
}
|
235 |
-
|
236 |
-
if ( @mysqli_options( $this->conn, $option, $value ) ) {
|
237 |
-
continue;
|
238 |
-
}
|
239 |
-
|
240 |
-
throw new \Exception( $this->conn->error, $this->conn->errno );
|
241 |
-
}
|
242 |
-
}
|
243 |
-
|
244 |
-
/**
|
245 |
-
* Pings the server and re-connects when `mysqli.reconnect = 1`
|
246 |
-
*
|
247 |
-
* @inheritDoc
|
248 |
-
*/
|
249 |
-
public function ping() {
|
250 |
-
if ( ! $this->conn->ping() ) {
|
251 |
-
throw new \Exception( $this->conn->error, $this->conn->errno );
|
252 |
-
}
|
253 |
-
}
|
254 |
-
|
255 |
-
/**
|
256 |
-
* @inheritDoc
|
257 |
-
*/
|
258 |
-
public function getAttribute( $name ) {
|
259 |
-
if ( $name === \PDO::ATTR_DRIVER_NAME ) {
|
260 |
-
return 'mysql';
|
261 |
-
}
|
262 |
-
return null;
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* @inheritDoc
|
267 |
-
*/
|
268 |
-
public function setAttribute( $attribute, $value ) {
|
269 |
-
return false;
|
270 |
-
}
|
271 |
-
|
272 |
-
/**
|
273 |
-
* Establish a secure connection
|
274 |
-
*
|
275 |
-
* @param array<string, mixed> $params
|
276 |
-
*
|
277 |
-
* @throws \Exception
|
278 |
-
*/
|
279 |
-
private function setSecureConnection( $params ) {
|
280 |
-
if ( ! isset( $params['ssl_key'] ) &&
|
281 |
-
! isset( $params['ssl_cert'] ) &&
|
282 |
-
! isset( $params['ssl_ca'] ) &&
|
283 |
-
! isset( $params['ssl_capath'] ) &&
|
284 |
-
! isset( $params['ssl_cipher'] )
|
285 |
-
) {
|
286 |
-
return;
|
287 |
-
}
|
288 |
-
|
289 |
-
$this->conn->ssl_set(
|
290 |
-
isset( $params['ssl_key'] ) ? $params['ssl_key'] : null,
|
291 |
-
isset( $params['ssl_cert'] ) ? $params['ssl_cert'] : null,
|
292 |
-
isset( $params['ssl_ca'] ) ? $params['ssl_ca'] : null,
|
293 |
-
isset( $params['ssl_capath'] ) ? $params['ssl_capath'] : null,
|
294 |
-
isset( $params['ssl_cipher'] ) ? $params['ssl_cipher'] : null
|
295 |
-
);
|
296 |
-
}
|
297 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
polyfills/pdo/pdo-mysqli-statement-polyfill.php
DELETED
@@ -1,448 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* These are polyfills of PDO in case the extension isn't loaded.
|
4 |
-
*
|
5 |
-
* This code is primarily based on the MySQLi driver for Doctrine.
|
6 |
-
*
|
7 |
-
* The Doctrine license is included below:
|
8 |
-
*
|
9 |
-
* Copyright (c) 2006-2018 Doctrine Project
|
10 |
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
11 |
-
* this software and associated documentation files (the "Software"), to deal in
|
12 |
-
* the Software without restriction, including without limitation the rights to
|
13 |
-
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
14 |
-
* of the Software, and to permit persons to whom the Software is furnished to do
|
15 |
-
* so, subject to the following conditions:
|
16 |
-
*
|
17 |
-
* The above copyright notice and this permission notice shall be included in all
|
18 |
-
* copies or substantial portions of the Software.
|
19 |
-
*
|
20 |
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21 |
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22 |
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23 |
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24 |
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25 |
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26 |
-
* SOFTWARE.
|
27 |
-
*/
|
28 |
-
|
29 |
-
namespace Yoast\WP\Polyfills\PDO;
|
30 |
-
|
31 |
-
final class PDO_MySQLi_Statement_Polyfill implements \IteratorAggregate {
|
32 |
-
|
33 |
-
/** @var string[] */
|
34 |
-
private static $paramTypeMap = [
|
35 |
-
\PDO::PARAM_STR => 's',
|
36 |
-
16 => 's',
|
37 |
-
\PDO::PARAM_BOOL => 'i',
|
38 |
-
\PDO::PARAM_NULL => 's',
|
39 |
-
\PDO::PARAM_INT => 'i',
|
40 |
-
\PDO::PARAM_LOB => 'b',
|
41 |
-
];
|
42 |
-
|
43 |
-
/** @var mysqli */
|
44 |
-
private $conn;
|
45 |
-
|
46 |
-
/** @var mysqli_stmt */
|
47 |
-
private $stmt;
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Whether the statement result metadata has been fetched.
|
51 |
-
*
|
52 |
-
* @var bool
|
53 |
-
*/
|
54 |
-
private $metadataFetched = false;
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Whether the statement result has columns. The property should be used only after the result metadata
|
58 |
-
* has been fetched ({@see $metadataFetched}). Otherwise, the property value is undetermined.
|
59 |
-
*
|
60 |
-
* @var bool
|
61 |
-
*/
|
62 |
-
private $hasColumns = false;
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Mapping of statement result column indexes to their names. The property should be used only
|
66 |
-
* if the statement result has columns ({@see $hasColumns}). Otherwise, the property value is undetermined.
|
67 |
-
*
|
68 |
-
* @var array<int,string>
|
69 |
-
*/
|
70 |
-
private $columnNames = [];
|
71 |
-
|
72 |
-
/** @var mixed[] */
|
73 |
-
private $rowBoundValues = [];
|
74 |
-
|
75 |
-
/** @var mixed[] */
|
76 |
-
private $boundValues = [];
|
77 |
-
|
78 |
-
/** @var string */
|
79 |
-
private $types;
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Contains ref values for bindValue().
|
83 |
-
*
|
84 |
-
* @var mixed[]
|
85 |
-
*/
|
86 |
-
private $values = [];
|
87 |
-
|
88 |
-
/** @var int */
|
89 |
-
private $defaultFetchMode = \PDO::FETCH_BOTH;
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Indicates whether the statement is in the state when fetching results is possible
|
93 |
-
*
|
94 |
-
* @var bool
|
95 |
-
*/
|
96 |
-
private $result = false;
|
97 |
-
|
98 |
-
/**
|
99 |
-
* @throws \Exception
|
100 |
-
*/
|
101 |
-
public function __construct( $conn, $sql ) {
|
102 |
-
$this->conn = $conn;
|
103 |
-
|
104 |
-
$stmt = $conn->prepare( $sql );
|
105 |
-
|
106 |
-
if ( $stmt === false ) {
|
107 |
-
throw new \Exception( $this->conn->error, $this->conn->errno );
|
108 |
-
}
|
109 |
-
|
110 |
-
$this->stmt = $stmt;
|
111 |
-
|
112 |
-
$paramCount = $this->stmt->param_count;
|
113 |
-
if ( 0 >= $paramCount ) {
|
114 |
-
return;
|
115 |
-
}
|
116 |
-
|
117 |
-
$this->types = str_repeat( 's', $paramCount );
|
118 |
-
$this->boundValues = array_fill( 1, $paramCount, null );
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* @inheritdoc
|
123 |
-
*/
|
124 |
-
public function bindParam( $param, &$variable, $type = \PDO::PARAM_STR, $length = null ) {
|
125 |
-
assert( is_int( $param ) );
|
126 |
-
|
127 |
-
if ( ! isset( self::$paramTypeMap[ $type ] ) ) {
|
128 |
-
throw new \Exception( sprintf( 'Unknown type, %d given.', $type ) );
|
129 |
-
}
|
130 |
-
|
131 |
-
$this->boundValues[ $param ] =& $variable;
|
132 |
-
$this->types[ ($param - 1) ] = self::$paramTypeMap[ $type ];
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* @inheritdoc
|
137 |
-
*/
|
138 |
-
public function bindValue( $param, $value, $type = \PDO::PARAM_STR ) {
|
139 |
-
assert( is_int( $param ) );
|
140 |
-
|
141 |
-
if ( ! isset( self::$paramTypeMap[ $type ] ) ) {
|
142 |
-
throw new \Exception( sprintf( 'Unknown type, %d given.', $type ) );
|
143 |
-
}
|
144 |
-
|
145 |
-
$this->values[ $param ] = $value;
|
146 |
-
$this->boundValues[ $param ] =& $this->values[ $param ];
|
147 |
-
$this->types[ ($param - 1) ] = self::$paramTypeMap[ $type ];
|
148 |
-
}
|
149 |
-
|
150 |
-
/**
|
151 |
-
* @inheritdoc
|
152 |
-
*/
|
153 |
-
public function execute( $params = null ) {
|
154 |
-
if ( $params !== null && count( $params ) > 0 ) {
|
155 |
-
if ( ! $this->bindUntypedValues( $params ) ) {
|
156 |
-
throw new \Exception( $this->stmt->error, $this->stmt->errno );
|
157 |
-
}
|
158 |
-
} else {
|
159 |
-
$this->bindTypedParameters();
|
160 |
-
}
|
161 |
-
|
162 |
-
if ( ! $this->stmt->execute() ) {
|
163 |
-
throw new \Exception( $this->stmt->error, $this->stmt->errno );
|
164 |
-
}
|
165 |
-
|
166 |
-
if ( ! $this->metadataFetched ) {
|
167 |
-
$meta = $this->stmt->result_metadata();
|
168 |
-
if ( $meta !== false ) {
|
169 |
-
$this->hasColumns = true;
|
170 |
-
|
171 |
-
$fields = $meta->fetch_fields();
|
172 |
-
assert( is_array( $fields ) );
|
173 |
-
|
174 |
-
$this->columnNames = array_map(static function ( \stdClass $field ) {
|
175 |
-
return $field->name;
|
176 |
-
}, $fields);
|
177 |
-
|
178 |
-
$meta->free();
|
179 |
-
} else {
|
180 |
-
$this->hasColumns = false;
|
181 |
-
}
|
182 |
-
|
183 |
-
$this->metadataFetched = true;
|
184 |
-
}
|
185 |
-
|
186 |
-
if ( $this->hasColumns ) {
|
187 |
-
// Store result of every execution which has it. Otherwise it will be impossible
|
188 |
-
// to execute a new statement in case if the previous one has non-fetched rows
|
189 |
-
// @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html
|
190 |
-
$this->stmt->store_result();
|
191 |
-
|
192 |
-
// Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql,
|
193 |
-
// it will have to allocate as much memory as it may be needed for the given column type
|
194 |
-
// (e.g. for a LONGBLOB field it's 4 gigabytes)
|
195 |
-
// @link https://bugs.php.net/bug.php?id=51386#1270673122
|
196 |
-
//
|
197 |
-
// Make sure that the values are bound after each execution. Otherwise, if closeCursor() has been
|
198 |
-
// previously called on the statement, the values are unbound making the statement unusable.
|
199 |
-
//
|
200 |
-
// It's also important that row values are bound after _each_ call to store_result(). Otherwise,
|
201 |
-
// if mysqli is compiled with libmysql, subsequently fetched string values will get truncated
|
202 |
-
// to the length of the ones fetched during the previous execution.
|
203 |
-
$this->rowBoundValues = array_fill( 0, count( $this->columnNames ), null );
|
204 |
-
|
205 |
-
$refs = [];
|
206 |
-
foreach ( $this->rowBoundValues as $key => &$value ) {
|
207 |
-
$refs[ $key ] =& $value;
|
208 |
-
}
|
209 |
-
|
210 |
-
if ( ! $this->stmt->bind_result( ...$refs ) ) {
|
211 |
-
throw new \Exception( $this->stmt->error, $this->stmt->errno );
|
212 |
-
}
|
213 |
-
}
|
214 |
-
|
215 |
-
$this->result = true;
|
216 |
-
}
|
217 |
-
|
218 |
-
/**
|
219 |
-
* Binds parameters with known types previously bound to the statement
|
220 |
-
*
|
221 |
-
* @throws \Exception
|
222 |
-
*/
|
223 |
-
private function bindTypedParameters() {
|
224 |
-
$streams = $values = [];
|
225 |
-
$types = $this->types;
|
226 |
-
|
227 |
-
foreach ( $this->boundValues as $parameter => $value ) {
|
228 |
-
assert( is_int( $parameter ) );
|
229 |
-
if ( ! isset( $types[ ($parameter - 1) ] ) ) {
|
230 |
-
$types[ ($parameter - 1) ] = self::$paramTypeMap[ \PDO::PARAM_STR ];
|
231 |
-
}
|
232 |
-
|
233 |
-
if ( $types[ ($parameter - 1) ] === self::$paramTypeMap[ \PDO::PARAM_LOB ] ) {
|
234 |
-
if ( is_resource( $value ) ) {
|
235 |
-
if ( get_resource_type( $value ) !== 'stream' ) {
|
236 |
-
throw new \Exception( 'Resources passed with the LARGE_OBJECT parameter type must be stream resources.' );
|
237 |
-
}
|
238 |
-
|
239 |
-
$streams[ $parameter ] = $value;
|
240 |
-
$values[ $parameter ] = null;
|
241 |
-
continue;
|
242 |
-
}
|
243 |
-
|
244 |
-
$types[ ($parameter - 1) ] = self::$paramTypeMap[ \PDO::PARAM_STR ];
|
245 |
-
}
|
246 |
-
|
247 |
-
$values[ $parameter ] = $value;
|
248 |
-
}
|
249 |
-
|
250 |
-
if ( count( $values ) > 0 && ! $this->stmt->bind_param( $types, ...$values ) ) {
|
251 |
-
throw new \Exception( $this->stmt->error, $this->stmt->errno );
|
252 |
-
}
|
253 |
-
|
254 |
-
$this->sendLongData( $streams );
|
255 |
-
}
|
256 |
-
|
257 |
-
/**
|
258 |
-
* Handle $this->_longData after regular query parameters have been bound
|
259 |
-
*
|
260 |
-
* @param array<int, resource> $streams
|
261 |
-
*
|
262 |
-
* @throws \Exception
|
263 |
-
*/
|
264 |
-
private function sendLongData( $streams ) {
|
265 |
-
foreach ( $streams as $paramNr => $stream ) {
|
266 |
-
while ( ! feof( $stream ) ) {
|
267 |
-
$chunk = fread( $stream, 8192 );
|
268 |
-
|
269 |
-
if ( $chunk === false ) {
|
270 |
-
return new \Exception( sprintf( 'Failed reading the stream resource for parameter offset %d.', $paramNr ) );
|
271 |
-
}
|
272 |
-
|
273 |
-
if ( ! $this->stmt->send_long_data( ($paramNr - 1), $chunk ) ) {
|
274 |
-
throw new \Exception( $this->stmt->error, $this->stmt->errno );
|
275 |
-
}
|
276 |
-
}
|
277 |
-
}
|
278 |
-
}
|
279 |
-
|
280 |
-
/**
|
281 |
-
* Binds a array of values to bound parameters.
|
282 |
-
*
|
283 |
-
* @param mixed[] $values
|
284 |
-
*/
|
285 |
-
private function bindUntypedValues( $values ) {
|
286 |
-
$params = [];
|
287 |
-
$types = str_repeat( 's', count( $values ) );
|
288 |
-
|
289 |
-
foreach ( $values as &$v ) {
|
290 |
-
$params[] =& $v;
|
291 |
-
}
|
292 |
-
|
293 |
-
return $this->stmt->bind_param( $types, ...$params );
|
294 |
-
}
|
295 |
-
|
296 |
-
/**
|
297 |
-
* @return mixed[]|false|null
|
298 |
-
*/
|
299 |
-
private function _fetch() {
|
300 |
-
$ret = $this->stmt->fetch();
|
301 |
-
|
302 |
-
if ( $ret === true ) {
|
303 |
-
$values = [];
|
304 |
-
foreach ( $this->rowBoundValues as $v ) {
|
305 |
-
$values[] = $v;
|
306 |
-
}
|
307 |
-
|
308 |
-
return $values;
|
309 |
-
}
|
310 |
-
|
311 |
-
return $ret;
|
312 |
-
}
|
313 |
-
|
314 |
-
/**
|
315 |
-
* @inheritdoc
|
316 |
-
*/
|
317 |
-
public function fetch( $fetchMode = null, ...$args ) {
|
318 |
-
// do not try fetching from the statement if it's not expected to contain result
|
319 |
-
// in order to prevent exceptional situation
|
320 |
-
if ( ! $this->result ) {
|
321 |
-
return false;
|
322 |
-
}
|
323 |
-
|
324 |
-
$fetchMode = $fetchMode ?: $this->defaultFetchMode;
|
325 |
-
|
326 |
-
if ( $fetchMode === \PDO::FETCH_COLUMN ) {
|
327 |
-
return $this->fetchColumn();
|
328 |
-
}
|
329 |
-
|
330 |
-
$values = $this->_fetch();
|
331 |
-
|
332 |
-
if ( $values === null ) {
|
333 |
-
return false;
|
334 |
-
}
|
335 |
-
|
336 |
-
if ( $values === false ) {
|
337 |
-
throw new \Exception( $this->stmt->error, $this->stmt->errno );
|
338 |
-
}
|
339 |
-
|
340 |
-
if ( $fetchMode === \PDO::FETCH_NUM ) {
|
341 |
-
return $values;
|
342 |
-
}
|
343 |
-
|
344 |
-
$assoc = array_combine( $this->columnNames, $values );
|
345 |
-
assert( is_array( $assoc ) );
|
346 |
-
|
347 |
-
switch ( $fetchMode ) {
|
348 |
-
case \PDO::FETCH_ASSOC:
|
349 |
-
return $assoc;
|
350 |
-
|
351 |
-
case \PDO::FETCH_BOTH:
|
352 |
-
return ($assoc + $values);
|
353 |
-
|
354 |
-
case \PDO::FETCH_OBJ:
|
355 |
-
return (object) $assoc;
|
356 |
-
|
357 |
-
default:
|
358 |
-
throw new \Exception( sprintf( 'Unknown fetch mode %d.', $fetchMode ) );
|
359 |
-
}
|
360 |
-
}
|
361 |
-
|
362 |
-
/**
|
363 |
-
* @inheritdoc
|
364 |
-
*/
|
365 |
-
public function fetchAll( $fetchMode = null, ...$args ) {
|
366 |
-
$fetchMode = $fetchMode ?: $this->defaultFetchMode;
|
367 |
-
|
368 |
-
$rows = [];
|
369 |
-
|
370 |
-
if ( $fetchMode === \PDO::FETCH_COLUMN ) {
|
371 |
-
while ( ($row = $this->fetchColumn()) !== false ) {
|
372 |
-
$rows[] = $row;
|
373 |
-
}
|
374 |
-
} else {
|
375 |
-
while ( ($row = $this->fetch( $fetchMode )) !== false ) {
|
376 |
-
$rows[] = $row;
|
377 |
-
}
|
378 |
-
}
|
379 |
-
|
380 |
-
return $rows;
|
381 |
-
}
|
382 |
-
|
383 |
-
/**
|
384 |
-
* @inheritdoc
|
385 |
-
*/
|
386 |
-
public function fetchColumn( $columnIndex = 0 ) {
|
387 |
-
$row = $this->fetch( \PDO::FETCH_NUM );
|
388 |
-
|
389 |
-
if ( $row === false ) {
|
390 |
-
return false;
|
391 |
-
}
|
392 |
-
|
393 |
-
if ( ! array_key_exists( $columnIndex, $row ) ) {
|
394 |
-
$count = count( $row );
|
395 |
-
throw new \Exception( sprintf(
|
396 |
-
'Invalid column index %d. The statement result contains %d column%s.',
|
397 |
-
$columnIndex,
|
398 |
-
$count,
|
399 |
-
$count === 1 ? '' : 's'
|
400 |
-
) );
|
401 |
-
}
|
402 |
-
|
403 |
-
return $row[ $columnIndex ];
|
404 |
-
}
|
405 |
-
|
406 |
-
|
407 |
-
/**
|
408 |
-
* @inheritDoc
|
409 |
-
*/
|
410 |
-
public function closeCursor() {
|
411 |
-
$this->stmt->free_result();
|
412 |
-
$this->result = false;
|
413 |
-
}
|
414 |
-
|
415 |
-
/**
|
416 |
-
* @inheritDoc
|
417 |
-
*/
|
418 |
-
public function rowCount() {
|
419 |
-
if ( $this->hasColumns ) {
|
420 |
-
return $this->stmt->num_rows;
|
421 |
-
}
|
422 |
-
|
423 |
-
return $this->stmt->affected_rows;
|
424 |
-
}
|
425 |
-
|
426 |
-
/**
|
427 |
-
* @inheritDoc
|
428 |
-
*/
|
429 |
-
public function columnCount() {
|
430 |
-
return $this->stmt->field_count;
|
431 |
-
}
|
432 |
-
|
433 |
-
/**
|
434 |
-
* @inheritdoc
|
435 |
-
*/
|
436 |
-
public function setFetchMode( $fetchMode, ...$args ) {
|
437 |
-
$this->defaultFetchMode = $fetchMode;
|
438 |
-
}
|
439 |
-
|
440 |
-
/**
|
441 |
-
* @inheritdoc
|
442 |
-
*/
|
443 |
-
public function getIterator() {
|
444 |
-
while ( ($result = $this->fetch()) !== false ) {
|
445 |
-
yield $result;
|
446 |
-
}
|
447 |
-
}
|
448 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,28 @@ Your question has most likely been answered on our knowledge base: [kb.yoast.com
|
|
209 |
|
210 |
== Changelog ==
|
211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
= 14.0.1 =
|
213 |
Release Date: April 28th, 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.2
|
10 |
Requires PHP: 5.6.20
|
11 |
|
12 |
Improve your WordPress SEO: Write better content and have a fully optimized WordPress site using the Yoast SEO plugin.
|
209 |
|
210 |
== Changelog ==
|
211 |
|
212 |
+
= 14.0.2 =
|
213 |
+
Release Date: April 29th, 2020
|
214 |
+
|
215 |
+
Because we’ve changed the underlying framework of our Indexables technology, we’ve chosen to rebuild the table. This means you will have to go through the indexing process again. We’re sorry. For sites with more than 10,000 posts, we advise using the [WP CLI command to do the indexation on the server](https://yoa.st/wp-cli-index).
|
216 |
+
|
217 |
+
Bugfixes:
|
218 |
+
|
219 |
+
* Fixes a bug where a fatal error would be thrown when a title contained more than 191 characters.
|
220 |
+
* Fixes a bug where a fatal error would be thrown when a focus keyphrase contained more than 191 characters.
|
221 |
+
* Fixes a bug where a fatal error would be thrown when search engines were disallowed from indexing the site.
|
222 |
+
* Fixes a bug where a fatal error would be thrown on WooCommerce installations when the `wpseo_metadesc` filter was called with only 1 argument.
|
223 |
+
* Fixes a bug where a fatal error would be thrown when using the `WPSEO_Frontend` class to get the meta description.
|
224 |
+
* Fixes a bug where a fatal error would be thrown when `WPSEO_Frontend` or `WPSEO_Breadcrumbs` was called before the `init` action.
|
225 |
+
* Fixes a bug where a non-object property retrieval notice would be thrown when the site's content was being indexed.
|
226 |
+
* Fixes a bug where a trailing slash would be added to canonical URLs and some `rel="prev"` URLs, even when the permalink structure settings didn't contain that trailing slash.
|
227 |
+
* Fixes a bug where a double breadcrumb would be shown on home pages.
|
228 |
+
* Fixes a bug where the indexation would continue indefinitely under specific circumstances.
|
229 |
+
|
230 |
+
Other:
|
231 |
+
|
232 |
+
* Removes all usages of `PDO` and `mysqli` directly and uses `wpdb` everywhere. This should prevent a lot of errors for database installations that have different encodings or configurations than what is generally seen.
|
233 |
+
|
234 |
= 14.0.1 =
|
235 |
Release Date: April 28th, 2020
|
236 |
|
src/actions/indexation/indexable-post-indexation-action.php
CHANGED
@@ -11,7 +11,7 @@ use wpdb;
|
|
11 |
use Yoast\WP\SEO\Builders\Indexable_Builder;
|
12 |
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
|
13 |
use Yoast\WP\SEO\Models\Indexable;
|
14 |
-
use Yoast\WP\
|
15 |
|
16 |
/**
|
17 |
* Indexable_Post_Indexation_Action class.
|
@@ -79,10 +79,7 @@ class Indexable_Post_Indexation_Action implements Indexation_Action_Interface {
|
|
79 |
|
80 |
$indexables = [];
|
81 |
foreach ( $post_ids as $post_id ) {
|
82 |
-
$
|
83 |
-
if ( $indexable !== false ) {
|
84 |
-
$indexables[] = $indexable;
|
85 |
-
}
|
86 |
}
|
87 |
|
88 |
return $indexables;
|
@@ -117,7 +114,7 @@ class Indexable_Post_Indexation_Action implements Indexation_Action_Interface {
|
|
117 |
protected function get_query( $count, $limit = 1 ) {
|
118 |
$public_post_types = $this->post_type_helper->get_public_post_types();
|
119 |
$placeholders = \implode( ', ', \array_fill( 0, \count( $public_post_types ), '%s' ) );
|
120 |
-
$indexable_table =
|
121 |
$replacements = $public_post_types;
|
122 |
|
123 |
$select = 'ID';
|
11 |
use Yoast\WP\SEO\Builders\Indexable_Builder;
|
12 |
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
|
13 |
use Yoast\WP\SEO\Models\Indexable;
|
14 |
+
use Yoast\WP\Lib\Model;
|
15 |
|
16 |
/**
|
17 |
* Indexable_Post_Indexation_Action class.
|
79 |
|
80 |
$indexables = [];
|
81 |
foreach ( $post_ids as $post_id ) {
|
82 |
+
$indexables[] = $this->builder->build_for_id_and_type( (int) $post_id, 'post' );
|
|
|
|
|
|
|
83 |
}
|
84 |
|
85 |
return $indexables;
|
114 |
protected function get_query( $count, $limit = 1 ) {
|
115 |
$public_post_types = $this->post_type_helper->get_public_post_types();
|
116 |
$placeholders = \implode( ', ', \array_fill( 0, \count( $public_post_types ), '%s' ) );
|
117 |
+
$indexable_table = Model::get_table_name( 'Indexable' );
|
118 |
$replacements = $public_post_types;
|
119 |
|
120 |
$select = 'ID';
|
src/actions/indexation/indexable-term-indexation-action.php
CHANGED
@@ -11,7 +11,7 @@ use wpdb;
|
|
11 |
use Yoast\WP\SEO\Builders\Indexable_Builder;
|
12 |
use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
|
13 |
use Yoast\WP\SEO\Models\Indexable;
|
14 |
-
use Yoast\WP\
|
15 |
|
16 |
/**
|
17 |
* Indexable_Term_Indexation_Action class.
|
@@ -80,10 +80,7 @@ class Indexable_Term_Indexation_Action implements Indexation_Action_Interface {
|
|
80 |
|
81 |
$indexables = [];
|
82 |
foreach ( $term_ids as $term_id ) {
|
83 |
-
$
|
84 |
-
if ( $indexable !== false ) {
|
85 |
-
$indexables[] = $indexable;
|
86 |
-
}
|
87 |
}
|
88 |
|
89 |
return $indexables;
|
@@ -118,7 +115,7 @@ class Indexable_Term_Indexation_Action implements Indexation_Action_Interface {
|
|
118 |
protected function get_query( $count, $limit = 1 ) {
|
119 |
$public_taxonomies = $this->taxonomy->get_public_taxonomies();
|
120 |
$placeholders = \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) );
|
121 |
-
$indexable_table =
|
122 |
$replacements = $public_taxonomies;
|
123 |
|
124 |
$select = 'term_id';
|
11 |
use Yoast\WP\SEO\Builders\Indexable_Builder;
|
12 |
use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
|
13 |
use Yoast\WP\SEO\Models\Indexable;
|
14 |
+
use Yoast\WP\Lib\Model;
|
15 |
|
16 |
/**
|
17 |
* Indexable_Term_Indexation_Action class.
|
80 |
|
81 |
$indexables = [];
|
82 |
foreach ( $term_ids as $term_id ) {
|
83 |
+
$indexables[] = $this->builder->build_for_id_and_type( (int) $term_id, 'term' );
|
|
|
|
|
|
|
84 |
}
|
85 |
|
86 |
return $indexables;
|
115 |
protected function get_query( $count, $limit = 1 ) {
|
116 |
$public_taxonomies = $this->taxonomy->get_public_taxonomies();
|
117 |
$placeholders = \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) );
|
118 |
+
$indexable_table = Model::get_table_name( 'Indexable' );
|
119 |
$replacements = $public_taxonomies;
|
120 |
|
121 |
$select = 'term_id';
|
src/builders/indexable-builder.php
CHANGED
@@ -147,6 +147,10 @@ class Indexable_Builder {
|
|
147 |
switch ( $object_type ) {
|
148 |
case 'post':
|
149 |
$indexable = $this->post_builder->build( $object_id, $indexable );
|
|
|
|
|
|
|
|
|
150 |
$this->primary_term_builder->build( $object_id );
|
151 |
|
152 |
$author = $this->indexable_repository->find_by_id_and_type( $indexable->author_id, 'user', false );
|
@@ -165,14 +169,18 @@ class Indexable_Builder {
|
|
165 |
return $indexable;
|
166 |
}
|
167 |
|
168 |
-
// Something went wrong building,
|
169 |
if ( $indexable === false ) {
|
170 |
-
|
|
|
|
|
|
|
|
|
171 |
}
|
172 |
|
173 |
$this->save_indexable( $indexable, $indexable_before );
|
174 |
|
175 |
-
if ( in_array( $object_type, [ 'post', 'term' ], true ) ) {
|
176 |
$this->hierarchy_builder->build( $indexable );
|
177 |
}
|
178 |
|
147 |
switch ( $object_type ) {
|
148 |
case 'post':
|
149 |
$indexable = $this->post_builder->build( $object_id, $indexable );
|
150 |
+
if ( $indexable === false ) {
|
151 |
+
break;
|
152 |
+
}
|
153 |
+
|
154 |
$this->primary_term_builder->build( $object_id );
|
155 |
|
156 |
$author = $this->indexable_repository->find_by_id_and_type( $indexable->author_id, 'user', false );
|
169 |
return $indexable;
|
170 |
}
|
171 |
|
172 |
+
// Something went wrong building, create a false indexable.
|
173 |
if ( $indexable === false ) {
|
174 |
+
$indexable = $this->indexable_repository->query()->create( [
|
175 |
+
'object_id' => $object_id,
|
176 |
+
'object_type' => $object_type,
|
177 |
+
'post_status' => 'unindexed',
|
178 |
+
] );
|
179 |
}
|
180 |
|
181 |
$this->save_indexable( $indexable, $indexable_before );
|
182 |
|
183 |
+
if ( in_array( $object_type, [ 'post', 'term' ], true ) && $indexable->post_status !== 'unindexed' ) {
|
184 |
$this->hierarchy_builder->build( $indexable );
|
185 |
}
|
186 |
|
src/builders/indexable-hierarchy-builder.php
CHANGED
@@ -127,7 +127,7 @@ class Indexable_Hierarchy_Builder {
|
|
127 |
|
128 |
if ( $post->post_parent !== 0 && $this->post->get_post( $post->post_parent ) !== null ) {
|
129 |
$ancestor = $this->indexable_repository->find_by_id_and_type( $post->post_parent, 'post' );
|
130 |
-
if ( $ancestor ===
|
131 |
return;
|
132 |
}
|
133 |
|
@@ -143,7 +143,7 @@ class Indexable_Hierarchy_Builder {
|
|
143 |
}
|
144 |
|
145 |
$ancestor = $this->indexable_repository->find_by_id_and_type( $primary_term_id, 'term' );
|
146 |
-
if ( $ancestor ===
|
147 |
return;
|
148 |
}
|
149 |
|
@@ -166,7 +166,7 @@ class Indexable_Hierarchy_Builder {
|
|
166 |
|
167 |
foreach ( $parents as $parent ) {
|
168 |
$ancestor = $this->indexable_repository->find_by_id_and_type( $parent->term_id, 'term' );
|
169 |
-
if ( $ancestor ===
|
170 |
continue;
|
171 |
}
|
172 |
$this->indexable_hierarchy_repository->add_ancestor( $indexable_id, $ancestor->id, $depth );
|
127 |
|
128 |
if ( $post->post_parent !== 0 && $this->post->get_post( $post->post_parent ) !== null ) {
|
129 |
$ancestor = $this->indexable_repository->find_by_id_and_type( $post->post_parent, 'post' );
|
130 |
+
if ( $ancestor->post_status === 'unindexed' ) {
|
131 |
return;
|
132 |
}
|
133 |
|
143 |
}
|
144 |
|
145 |
$ancestor = $this->indexable_repository->find_by_id_and_type( $primary_term_id, 'term' );
|
146 |
+
if ( $ancestor->post_status === 'unindexed' ) {
|
147 |
return;
|
148 |
}
|
149 |
|
166 |
|
167 |
foreach ( $parents as $parent ) {
|
168 |
$ancestor = $this->indexable_repository->find_by_id_and_type( $parent->term_id, 'term' );
|
169 |
+
if ( $ancestor->post_status === 'unindexed' ) {
|
170 |
continue;
|
171 |
}
|
172 |
$this->indexable_hierarchy_repository->add_ancestor( $indexable_id, $ancestor->id, $depth );
|
src/config/ruckusing-framework.php
CHANGED
@@ -8,10 +8,8 @@
|
|
8 |
namespace Yoast\WP\SEO\Config;
|
9 |
|
10 |
use wpdb;
|
|
|
11 |
use Yoast\WP\SEO\Config\Dependency_Management;
|
12 |
-
use Yoast\WP\SEO\Initializers\Database_Setup;
|
13 |
-
use Yoast\WP\SEO\Loggers\Migration_Logger;
|
14 |
-
use YoastSEO_Vendor\Ruckusing_FrameworkRunner;
|
15 |
use YoastSEO_Vendor\Ruckusing_Task_Manager;
|
16 |
use YoastSEO_Vendor\Task_Db_Migrate;
|
17 |
|
@@ -34,39 +32,18 @@ class Ruckusing_Framework {
|
|
34 |
*/
|
35 |
protected $dependency_management;
|
36 |
|
37 |
-
/**
|
38 |
-
* The migration logger object.
|
39 |
-
*
|
40 |
-
* @var \Yoast\WP\SEO\Loggers\Migration_Logger
|
41 |
-
*/
|
42 |
-
protected $migration_logger;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* The database setup object.
|
46 |
-
*
|
47 |
-
* @var \Yoast\WP\SEO\Initializers\Database_Setup
|
48 |
-
*/
|
49 |
-
protected $database_setup;
|
50 |
-
|
51 |
/**
|
52 |
* Ruckusing_Framework constructor.
|
53 |
*
|
54 |
* @param \wpdb $wpdb The wpdb instance.
|
55 |
* @param \Yoast\WP\SEO\Config\Dependency_Management $dependency_management The dependency management checker.
|
56 |
-
* @param \Yoast\WP\SEO\Loggers\Migration_Logger $migration_logger The migration logger, extends the
|
57 |
-
* Ruckusing logger.
|
58 |
-
* @param \Yoast\WP\SEO\Initializers\Database_Setup $database_setup The database setup object.
|
59 |
*/
|
60 |
public function __construct(
|
61 |
wpdb $wpdb,
|
62 |
-
Dependency_Management $dependency_management
|
63 |
-
Migration_Logger $migration_logger,
|
64 |
-
Database_Setup $database_setup
|
65 |
) {
|
66 |
$this->wpdb = $wpdb;
|
67 |
$this->dependency_management = $dependency_management;
|
68 |
-
$this->migration_logger = $migration_logger;
|
69 |
-
$this->database_setup = $database_setup;
|
70 |
}
|
71 |
|
72 |
/**
|
@@ -75,13 +52,13 @@ class Ruckusing_Framework {
|
|
75 |
* @param string $migrations_table_name The migrations table name.
|
76 |
* @param string $migrations_directory The migrations directory.
|
77 |
*
|
78 |
-
* @return
|
79 |
*/
|
80 |
public function get_framework_runner( $migrations_table_name, $migrations_directory ) {
|
81 |
$this->maybe_set_constant();
|
82 |
|
83 |
$configuration = $this->get_configuration( $migrations_table_name, $migrations_directory );
|
84 |
-
$instance = new
|
85 |
|
86 |
/*
|
87 |
* As the Ruckusing_FrameworkRunner is setting its own error and exception handlers,
|
@@ -119,27 +96,13 @@ class Ruckusing_Framework {
|
|
119 |
* @return array The configuration
|
120 |
*/
|
121 |
public function get_configuration( $migrations_table_name, $migrations_directory ) {
|
122 |
-
$config = $this->database_setup->get_database_config();
|
123 |
-
|
124 |
$ruckusing_config = [
|
125 |
'db' => [
|
126 |
'production' => [
|
127 |
-
'type' => 'mysql',
|
128 |
-
'host' => $config['host'],
|
129 |
-
'port' => $config['port'],
|
130 |
-
'database' => \DB_NAME,
|
131 |
-
'user' => \DB_USER,
|
132 |
-
'password' => \DB_PASSWORD,
|
133 |
-
'directory' => '', // This needs to be set, to use the migrations folder as base folder.
|
134 |
'schema_version_table_name' => $migrations_table_name,
|
135 |
],
|
136 |
],
|
137 |
'migrations_dir' => [ 'default' => $migrations_directory ],
|
138 |
-
// This needs to be set but is not used.
|
139 |
-
'db_dir' => true,
|
140 |
-
// This needs to be set but is not used.
|
141 |
-
'log_dir' => true,
|
142 |
-
// This needs to be set but is not used.
|
143 |
];
|
144 |
|
145 |
if ( ! empty( $this->wpdb->charset ) ) {
|
8 |
namespace Yoast\WP\SEO\Config;
|
9 |
|
10 |
use wpdb;
|
11 |
+
use Yoast\WP\Lib\Ruckusing_Framework_Runner;
|
12 |
use Yoast\WP\SEO\Config\Dependency_Management;
|
|
|
|
|
|
|
13 |
use YoastSEO_Vendor\Ruckusing_Task_Manager;
|
14 |
use YoastSEO_Vendor\Task_Db_Migrate;
|
15 |
|
32 |
*/
|
33 |
protected $dependency_management;
|
34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
/**
|
36 |
* Ruckusing_Framework constructor.
|
37 |
*
|
38 |
* @param \wpdb $wpdb The wpdb instance.
|
39 |
* @param \Yoast\WP\SEO\Config\Dependency_Management $dependency_management The dependency management checker.
|
|
|
|
|
|
|
40 |
*/
|
41 |
public function __construct(
|
42 |
wpdb $wpdb,
|
43 |
+
Dependency_Management $dependency_management
|
|
|
|
|
44 |
) {
|
45 |
$this->wpdb = $wpdb;
|
46 |
$this->dependency_management = $dependency_management;
|
|
|
|
|
47 |
}
|
48 |
|
49 |
/**
|
52 |
* @param string $migrations_table_name The migrations table name.
|
53 |
* @param string $migrations_directory The migrations directory.
|
54 |
*
|
55 |
+
* @return Ruckusing_Framework_Runner The framework runner.
|
56 |
*/
|
57 |
public function get_framework_runner( $migrations_table_name, $migrations_directory ) {
|
58 |
$this->maybe_set_constant();
|
59 |
|
60 |
$configuration = $this->get_configuration( $migrations_table_name, $migrations_directory );
|
61 |
+
$instance = new Ruckusing_Framework_Runner( $configuration, [ 'db:migrate', 'env=production' ] );
|
62 |
|
63 |
/*
|
64 |
* As the Ruckusing_FrameworkRunner is setting its own error and exception handlers,
|
96 |
* @return array The configuration
|
97 |
*/
|
98 |
public function get_configuration( $migrations_table_name, $migrations_directory ) {
|
|
|
|
|
99 |
$ruckusing_config = [
|
100 |
'db' => [
|
101 |
'production' => [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
'schema_version_table_name' => $migrations_table_name,
|
103 |
],
|
104 |
],
|
105 |
'migrations_dir' => [ 'default' => $migrations_directory ],
|
|
|
|
|
|
|
|
|
|
|
106 |
];
|
107 |
|
108 |
if ( ! empty( $this->wpdb->charset ) ) {
|
src/generated/container.php
CHANGED
@@ -106,7 +106,6 @@ class Cached_Container extends Container
|
|
106 |
'yoast\\wp\\seo\\helpers\\twitter\\image_helper' => 'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper',
|
107 |
'yoast\\wp\\seo\\helpers\\url_helper' => 'Yoast\\WP\\SEO\\Helpers\\Url_Helper',
|
108 |
'yoast\\wp\\seo\\helpers\\user_helper' => 'Yoast\\WP\\SEO\\Helpers\\User_Helper',
|
109 |
-
'yoast\\wp\\seo\\initializers\\database_setup' => 'Yoast\\WP\\SEO\\Initializers\\Database_Setup',
|
110 |
'yoast\\wp\\seo\\initializers\\migration_runner' => 'Yoast\\WP\\SEO\\Initializers\\Migration_Runner',
|
111 |
'yoast\\wp\\seo\\integrations\\admin\\indexation_integration' => 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration',
|
112 |
'yoast\\wp\\seo\\integrations\\admin\\migration_error_integration' => 'Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration',
|
@@ -141,7 +140,6 @@ class Cached_Container extends Container
|
|
141 |
'yoast\\wp\\seo\\integrations\\watchers\\option_titles_watcher' => 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher',
|
142 |
'yoast\\wp\\seo\\integrations\\watchers\\primary_term_watcher' => 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher',
|
143 |
'yoast\\wp\\seo\\loader' => 'Yoast\\WP\\SEO\\Loader',
|
144 |
-
'yoast\\wp\\seo\\loggers\\database_logger' => 'Yoast\\WP\\SEO\\Loggers\\Database_Logger',
|
145 |
'yoast\\wp\\seo\\loggers\\logger' => 'Yoast\\WP\\SEO\\Loggers\\Logger',
|
146 |
'yoast\\wp\\seo\\loggers\\migration_logger' => 'Yoast\\WP\\SEO\\Loggers\\Migration_Logger',
|
147 |
'yoast\\wp\\seo\\memoizers\\meta_tags_context_memoizer' => 'Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer',
|
@@ -261,7 +259,6 @@ class Cached_Container extends Container
|
|
261 |
'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => 'getImageHelper4Service',
|
262 |
'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => 'getUrlHelperService',
|
263 |
'Yoast\\WP\\SEO\\Helpers\\User_Helper' => 'getUserHelperService',
|
264 |
-
'Yoast\\WP\\SEO\\Initializers\\Database_Setup' => 'getDatabaseSetupService',
|
265 |
'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => 'getMigrationRunnerService',
|
266 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => 'getIndexationIntegrationService',
|
267 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration' => 'getMigrationErrorIntegrationService',
|
@@ -296,7 +293,6 @@ class Cached_Container extends Container
|
|
296 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher' => 'getOptionTitlesWatcherService',
|
297 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => 'getPrimaryTermWatcherService',
|
298 |
'Yoast\\WP\\SEO\\Loader' => 'getLoaderService',
|
299 |
-
'Yoast\\WP\\SEO\\Loggers\\Database_Logger' => 'getDatabaseLoggerService',
|
300 |
'Yoast\\WP\\SEO\\Loggers\\Logger' => 'getLoggerService',
|
301 |
'Yoast\\WP\\SEO\\Loggers\\Migration_Logger' => 'getMigrationLoggerService',
|
302 |
'Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer' => 'getMetaTagsContextMemoizerService',
|
@@ -350,6 +346,7 @@ class Cached_Container extends Container
|
|
350 |
'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
351 |
'YoastSEO_Vendor\\YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
352 |
'Yoast\\WP\\SEO\\Commands\\Command_Interface' => true,
|
|
|
353 |
'wpdb' => true,
|
354 |
];
|
355 |
}
|
@@ -388,7 +385,7 @@ class Cached_Container extends Container
|
|
388 |
*/
|
389 |
protected function getWPSEOBreadcrumbsService()
|
390 |
{
|
391 |
-
return $this->services['WPSEO_Breadcrumbs'] = new \WPSEO_Breadcrumbs(
|
392 |
}
|
393 |
|
394 |
/**
|
@@ -398,7 +395,7 @@ class Cached_Container extends Container
|
|
398 |
*/
|
399 |
protected function getWPSEOFrontendService()
|
400 |
{
|
401 |
-
return $this->services['WPSEO_Frontend'] = new \WPSEO_Frontend(
|
402 |
}
|
403 |
|
404 |
/**
|
@@ -770,7 +767,7 @@ class Cached_Container extends Container
|
|
770 |
*/
|
771 |
protected function getRuckusingFrameworkService()
|
772 |
{
|
773 |
-
return $this->services['Yoast\\WP\\SEO\\Config\\Ruckusing_Framework'] = new \Yoast\WP\SEO\Config\Ruckusing_Framework(${($_ = isset($this->services['wpdb']) ? $this->services['wpdb'] : $this->getWpdbService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Config\\Dependency_Management']) ? $this->services['Yoast\\WP\\SEO\\Config\\Dependency_Management'] : ($this->services['Yoast\\WP\\SEO\\Config\\Dependency_Management'] = new \Yoast\WP\SEO\Config\Dependency_Management())) && false ?: '_'}
|
774 |
}
|
775 |
|
776 |
/**
|
@@ -1223,16 +1220,6 @@ class Cached_Container extends Container
|
|
1223 |
return $this->services['Yoast\\WP\\SEO\\Helpers\\User_Helper'] = new \Yoast\WP\SEO\Helpers\User_Helper();
|
1224 |
}
|
1225 |
|
1226 |
-
/**
|
1227 |
-
* Gets the public 'Yoast\WP\SEO\Initializers\Database_Setup' shared autowired service.
|
1228 |
-
*
|
1229 |
-
* @return \Yoast\WP\SEO\Initializers\Database_Setup
|
1230 |
-
*/
|
1231 |
-
protected function getDatabaseSetupService()
|
1232 |
-
{
|
1233 |
-
return $this->services['Yoast\\WP\\SEO\\Initializers\\Database_Setup'] = new \Yoast\WP\SEO\Initializers\Database_Setup(${($_ = isset($this->services['Yoast\\WP\\SEO\\Loggers\\Logger']) ? $this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] : ($this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] = new \Yoast\WP\SEO\Loggers\Logger())) && false ?: '_'}, ${($_ = isset($this->services['wpdb']) ? $this->services['wpdb'] : $this->getWpdbService()) && false ?: '_'});
|
1234 |
-
}
|
1235 |
-
|
1236 |
/**
|
1237 |
* Gets the public 'Yoast\WP\SEO\Initializers\Migration_Runner' shared autowired service.
|
1238 |
*
|
@@ -1240,7 +1227,7 @@ class Cached_Container extends Container
|
|
1240 |
*/
|
1241 |
protected function getMigrationRunnerService()
|
1242 |
{
|
1243 |
-
return $this->services['Yoast\\WP\\SEO\\Initializers\\Migration_Runner'] = new \Yoast\WP\SEO\Initializers\Migration_Runner(${($_ = isset($this->services['Yoast\\WP\\SEO\\Config\\Migration_Status']) ? $this->services['Yoast\\WP\\SEO\\Config\\Migration_Status'] : ($this->services['Yoast\\WP\\SEO\\Config\\Migration_Status'] = new \Yoast\WP\SEO\Config\Migration_Status())) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Config\\Ruckusing_Framework']) ? $this->services['Yoast\\WP\\SEO\\Config\\Ruckusing_Framework'] : $this->getRuckusingFrameworkService()) && false ?: '_'}
|
1244 |
}
|
1245 |
|
1246 |
/**
|
@@ -1440,7 +1427,7 @@ class Cached_Container extends Container
|
|
1440 |
*/
|
1441 |
protected function getWooCommerceService()
|
1442 |
{
|
1443 |
-
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 ?: '_'});
|
1444 |
}
|
1445 |
|
1446 |
/**
|
@@ -1572,10 +1559,7 @@ class Cached_Container extends Container
|
|
1572 |
{
|
1573 |
$this->services['Yoast\\WP\\SEO\\Loader'] = $instance = new \Yoast\WP\SEO\Loader($this);
|
1574 |
|
1575 |
-
$instance->register_initializer('WPSEO_Breadcrumbs');
|
1576 |
-
$instance->register_initializer('WPSEO_Frontend');
|
1577 |
$instance->register_command('Yoast\\WP\\SEO\\Commands\\Index_Command');
|
1578 |
-
$instance->register_initializer('Yoast\\WP\\SEO\\Initializers\\Database_Setup');
|
1579 |
$instance->register_initializer('Yoast\\WP\\SEO\\Initializers\\Migration_Runner');
|
1580 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration');
|
1581 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration');
|
@@ -1609,7 +1593,6 @@ class Cached_Container extends Container
|
|
1609 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Term_Watcher');
|
1610 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher');
|
1611 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher');
|
1612 |
-
$instance->register_integration('Yoast\\WP\\SEO\\Loggers\\Database_Logger');
|
1613 |
$instance->register_route('Yoast\\WP\\SEO\\Routes\\Indexable_Indexation_Route');
|
1614 |
$instance->register_route('Yoast\\WP\\SEO\\Routes\\Indexables_Head_Route');
|
1615 |
$instance->register_route('Yoast\\WP\\SEO\\Routes\\Yoast_Head_REST_Field');
|
@@ -1617,16 +1600,6 @@ class Cached_Container extends Container
|
|
1617 |
return $instance;
|
1618 |
}
|
1619 |
|
1620 |
-
/**
|
1621 |
-
* Gets the public 'Yoast\WP\SEO\Loggers\Database_Logger' shared autowired service.
|
1622 |
-
*
|
1623 |
-
* @return \Yoast\WP\SEO\Loggers\Database_Logger
|
1624 |
-
*/
|
1625 |
-
protected function getDatabaseLoggerService()
|
1626 |
-
{
|
1627 |
-
return $this->services['Yoast\\WP\\SEO\\Loggers\\Database_Logger'] = new \Yoast\WP\SEO\Loggers\Database_Logger();
|
1628 |
-
}
|
1629 |
-
|
1630 |
/**
|
1631 |
* Gets the public 'Yoast\WP\SEO\Loggers\Logger' shared autowired service.
|
1632 |
*
|
106 |
'yoast\\wp\\seo\\helpers\\twitter\\image_helper' => 'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper',
|
107 |
'yoast\\wp\\seo\\helpers\\url_helper' => 'Yoast\\WP\\SEO\\Helpers\\Url_Helper',
|
108 |
'yoast\\wp\\seo\\helpers\\user_helper' => 'Yoast\\WP\\SEO\\Helpers\\User_Helper',
|
|
|
109 |
'yoast\\wp\\seo\\initializers\\migration_runner' => 'Yoast\\WP\\SEO\\Initializers\\Migration_Runner',
|
110 |
'yoast\\wp\\seo\\integrations\\admin\\indexation_integration' => 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration',
|
111 |
'yoast\\wp\\seo\\integrations\\admin\\migration_error_integration' => 'Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration',
|
140 |
'yoast\\wp\\seo\\integrations\\watchers\\option_titles_watcher' => 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher',
|
141 |
'yoast\\wp\\seo\\integrations\\watchers\\primary_term_watcher' => 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher',
|
142 |
'yoast\\wp\\seo\\loader' => 'Yoast\\WP\\SEO\\Loader',
|
|
|
143 |
'yoast\\wp\\seo\\loggers\\logger' => 'Yoast\\WP\\SEO\\Loggers\\Logger',
|
144 |
'yoast\\wp\\seo\\loggers\\migration_logger' => 'Yoast\\WP\\SEO\\Loggers\\Migration_Logger',
|
145 |
'yoast\\wp\\seo\\memoizers\\meta_tags_context_memoizer' => 'Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer',
|
259 |
'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => 'getImageHelper4Service',
|
260 |
'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => 'getUrlHelperService',
|
261 |
'Yoast\\WP\\SEO\\Helpers\\User_Helper' => 'getUserHelperService',
|
|
|
262 |
'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => 'getMigrationRunnerService',
|
263 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => 'getIndexationIntegrationService',
|
264 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration' => 'getMigrationErrorIntegrationService',
|
293 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher' => 'getOptionTitlesWatcherService',
|
294 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => 'getPrimaryTermWatcherService',
|
295 |
'Yoast\\WP\\SEO\\Loader' => 'getLoaderService',
|
|
|
296 |
'Yoast\\WP\\SEO\\Loggers\\Logger' => 'getLoggerService',
|
297 |
'Yoast\\WP\\SEO\\Loggers\\Migration_Logger' => 'getMigrationLoggerService',
|
298 |
'Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer' => 'getMetaTagsContextMemoizerService',
|
346 |
'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
347 |
'YoastSEO_Vendor\\YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
348 |
'Yoast\\WP\\SEO\\Commands\\Command_Interface' => true,
|
349 |
+
'Yoast\\WP\\SEO\\Initializers\\Initializer_Interface' => true,
|
350 |
'wpdb' => true,
|
351 |
];
|
352 |
}
|
385 |
*/
|
386 |
protected function getWPSEOBreadcrumbsService()
|
387 |
{
|
388 |
+
return $this->services['WPSEO_Breadcrumbs'] = new \WPSEO_Breadcrumbs();
|
389 |
}
|
390 |
|
391 |
/**
|
395 |
*/
|
396 |
protected function getWPSEOFrontendService()
|
397 |
{
|
398 |
+
return $this->services['WPSEO_Frontend'] = new \WPSEO_Frontend();
|
399 |
}
|
400 |
|
401 |
/**
|
767 |
*/
|
768 |
protected function getRuckusingFrameworkService()
|
769 |
{
|
770 |
+
return $this->services['Yoast\\WP\\SEO\\Config\\Ruckusing_Framework'] = new \Yoast\WP\SEO\Config\Ruckusing_Framework(${($_ = isset($this->services['wpdb']) ? $this->services['wpdb'] : $this->getWpdbService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Config\\Dependency_Management']) ? $this->services['Yoast\\WP\\SEO\\Config\\Dependency_Management'] : ($this->services['Yoast\\WP\\SEO\\Config\\Dependency_Management'] = new \Yoast\WP\SEO\Config\Dependency_Management())) && false ?: '_'});
|
771 |
}
|
772 |
|
773 |
/**
|
1220 |
return $this->services['Yoast\\WP\\SEO\\Helpers\\User_Helper'] = new \Yoast\WP\SEO\Helpers\User_Helper();
|
1221 |
}
|
1222 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1223 |
/**
|
1224 |
* Gets the public 'Yoast\WP\SEO\Initializers\Migration_Runner' shared autowired service.
|
1225 |
*
|
1227 |
*/
|
1228 |
protected function getMigrationRunnerService()
|
1229 |
{
|
1230 |
+
return $this->services['Yoast\\WP\\SEO\\Initializers\\Migration_Runner'] = new \Yoast\WP\SEO\Initializers\Migration_Runner(${($_ = isset($this->services['Yoast\\WP\\SEO\\Config\\Migration_Status']) ? $this->services['Yoast\\WP\\SEO\\Config\\Migration_Status'] : ($this->services['Yoast\\WP\\SEO\\Config\\Migration_Status'] = new \Yoast\WP\SEO\Config\Migration_Status())) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Config\\Ruckusing_Framework']) ? $this->services['Yoast\\WP\\SEO\\Config\\Ruckusing_Framework'] : $this->getRuckusingFrameworkService()) && false ?: '_'});
|
1231 |
}
|
1232 |
|
1233 |
/**
|
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 |
/**
|
1559 |
{
|
1560 |
$this->services['Yoast\\WP\\SEO\\Loader'] = $instance = new \Yoast\WP\SEO\Loader($this);
|
1561 |
|
|
|
|
|
1562 |
$instance->register_command('Yoast\\WP\\SEO\\Commands\\Index_Command');
|
|
|
1563 |
$instance->register_initializer('Yoast\\WP\\SEO\\Initializers\\Migration_Runner');
|
1564 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration');
|
1565 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration');
|
1593 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Term_Watcher');
|
1594 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher');
|
1595 |
$instance->register_integration('Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher');
|
|
|
1596 |
$instance->register_route('Yoast\\WP\\SEO\\Routes\\Indexable_Indexation_Route');
|
1597 |
$instance->register_route('Yoast\\WP\\SEO\\Routes\\Indexables_Head_Route');
|
1598 |
$instance->register_route('Yoast\\WP\\SEO\\Routes\\Yoast_Head_REST_Field');
|
1600 |
return $instance;
|
1601 |
}
|
1602 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1603 |
/**
|
1604 |
* Gets the public 'Yoast\WP\SEO\Loggers\Logger' shared autowired service.
|
1605 |
*
|
src/generators/breadcrumbs-generator.php
CHANGED
@@ -67,14 +67,14 @@ class Breadcrumbs_Generator implements Generator_Interface {
|
|
67 |
public function generate( Meta_Tags_Context $context ) {
|
68 |
$static_ancestors = [];
|
69 |
$breadcrumbs_home = $this->options->get( 'breadcrumbs-home' );
|
70 |
-
if ( $breadcrumbs_home !== '' ) {
|
71 |
$front_page_id = $this->current_page->get_front_page_id();
|
72 |
if ( $front_page_id === 0 ) {
|
73 |
$static_ancestors[] = $this->repository->find_for_home_page();
|
74 |
}
|
75 |
else {
|
76 |
$static_ancestor = $this->repository->find_by_id_and_type( $front_page_id, 'post' );
|
77 |
-
if ( $static_ancestor !==
|
78 |
$static_ancestors[] = $static_ancestor;
|
79 |
}
|
80 |
}
|
@@ -82,7 +82,7 @@ class Breadcrumbs_Generator implements Generator_Interface {
|
|
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 !==
|
86 |
$static_ancestors[] = $static_ancestor;
|
87 |
}
|
88 |
}
|
67 |
public function generate( Meta_Tags_Context $context ) {
|
68 |
$static_ancestors = [];
|
69 |
$breadcrumbs_home = $this->options->get( 'breadcrumbs-home' );
|
70 |
+
if ( $breadcrumbs_home !== '' && ! in_array( $this->current_page->get_page_type(), [ 'Home_Page', 'Static_Home_Page' ], true ) ) {
|
71 |
$front_page_id = $this->current_page->get_front_page_id();
|
72 |
if ( $front_page_id === 0 ) {
|
73 |
$static_ancestors[] = $this->repository->find_for_home_page();
|
74 |
}
|
75 |
else {
|
76 |
$static_ancestor = $this->repository->find_by_id_and_type( $front_page_id, 'post' );
|
77 |
+
if ( $static_ancestor->post_status !== 'unindexed' ) {
|
78 |
$static_ancestors[] = $static_ancestor;
|
79 |
}
|
80 |
}
|
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;
|
87 |
}
|
88 |
}
|
src/helpers/author-archive-helper.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Helpers;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Class Author_Archive_Helper
|
@@ -61,7 +61,7 @@ class Author_Archive_Helper {
|
|
61 |
* @return bool Whether the author has at least one public post.
|
62 |
*/
|
63 |
protected function author_has_a_public_post( $author_id ) {
|
64 |
-
$indexable_exists =
|
65 |
->where( 'object_type', 'post' )
|
66 |
->where_in( 'object_sub_type', $this->get_author_archive_post_types() )
|
67 |
->where( 'author_id', $author_id )
|
@@ -82,7 +82,7 @@ class Author_Archive_Helper {
|
|
82 |
* @return bool Whether the author has at least one post with the is public null.
|
83 |
*/
|
84 |
protected function author_has_a_post_with_is_public_null( $author_id ) {
|
85 |
-
$indexable_exists =
|
86 |
->where( 'object_type', 'post' )
|
87 |
->where_in( 'object_sub_type', $this->get_author_archive_post_types() )
|
88 |
->where( 'author_id', $author_id )
|
7 |
|
8 |
namespace Yoast\WP\SEO\Helpers;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Class Author_Archive_Helper
|
61 |
* @return bool Whether the author has at least one public post.
|
62 |
*/
|
63 |
protected function author_has_a_public_post( $author_id ) {
|
64 |
+
$indexable_exists = Model::of_type( 'Indexable' )
|
65 |
->where( 'object_type', 'post' )
|
66 |
->where_in( 'object_sub_type', $this->get_author_archive_post_types() )
|
67 |
->where( 'author_id', $author_id )
|
82 |
* @return bool Whether the author has at least one post with the is public null.
|
83 |
*/
|
84 |
protected function author_has_a_post_with_is_public_null( $author_id ) {
|
85 |
+
$indexable_exists = Model::of_type( 'Indexable' )
|
86 |
->where( 'object_type', 'post' )
|
87 |
->where_in( 'object_sub_type', $this->get_author_archive_post_types() )
|
88 |
->where( 'author_id', $author_id )
|
src/helpers/post-helper.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Helpers;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Class Redirect_Helper
|
@@ -115,16 +115,16 @@ class Post_Helper {
|
|
115 |
* @return bool Whether the update was successful.
|
116 |
*/
|
117 |
public function update_has_public_posts_on_attachments( $post_parent, $has_public_posts ) {
|
118 |
-
$orm_wrapper =
|
119 |
|
120 |
// Debatable way to get the table name in an update format.
|
121 |
$query = $orm_wrapper->set( 'has_public_posts', $has_public_posts )->get_update_sql();
|
122 |
-
$query = str_replace( 'WHERE `id` =
|
123 |
|
124 |
// Execute a raw query here to be able to find & set in one, i.e. more performant.
|
125 |
return $orm_wrapper
|
126 |
->raw_execute(
|
127 |
-
$query . 'WHERE `object_type` = \'post\' AND `object_sub_type` = \'attachment\' AND `post_status` = \'inherit\' AND `post_parent` =
|
128 |
[ $has_public_posts, $post_parent ]
|
129 |
);
|
130 |
}
|
7 |
|
8 |
namespace Yoast\WP\SEO\Helpers;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Class Redirect_Helper
|
115 |
* @return bool Whether the update was successful.
|
116 |
*/
|
117 |
public function update_has_public_posts_on_attachments( $post_parent, $has_public_posts ) {
|
118 |
+
$orm_wrapper = Model::of_type( 'Indexable' );
|
119 |
|
120 |
// Debatable way to get the table name in an update format.
|
121 |
$query = $orm_wrapper->set( 'has_public_posts', $has_public_posts )->get_update_sql();
|
122 |
+
$query = str_replace( 'WHERE `id` = %s', '', $query );
|
123 |
|
124 |
// Execute a raw query here to be able to find & set in one, i.e. more performant.
|
125 |
return $orm_wrapper
|
126 |
->raw_execute(
|
127 |
+
$query . 'WHERE `object_type` = \'post\' AND `object_sub_type` = \'attachment\' AND `post_status` = \'inherit\' AND `post_parent` = %s',
|
128 |
[ $has_public_posts, $post_parent ]
|
129 |
);
|
130 |
}
|
src/helpers/robots-helper.php
CHANGED
@@ -7,7 +7,6 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Helpers;
|
9 |
|
10 |
-
use Yoast\WP\SEO\Models\Indexable;
|
11 |
use Yoast\WP\SEO\Presentations\Indexable_Presentation;
|
12 |
|
13 |
/**
|
@@ -24,14 +23,22 @@ class Robots_Helper {
|
|
24 |
* @return string The altered robots string.
|
25 |
*/
|
26 |
public function set_robots_no_index( $robots, Indexable_Presentation $presentation ) {
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
return $robots;
|
29 |
}
|
30 |
|
31 |
-
|
32 |
-
$
|
33 |
-
|
|
|
34 |
|
35 |
-
|
|
|
36 |
}
|
37 |
}
|
7 |
|
8 |
namespace Yoast\WP\SEO\Helpers;
|
9 |
|
|
|
10 |
use Yoast\WP\SEO\Presentations\Indexable_Presentation;
|
11 |
|
12 |
/**
|
23 |
* @return string The altered robots string.
|
24 |
*/
|
25 |
public function set_robots_no_index( $robots, Indexable_Presentation $presentation ) {
|
26 |
+
// When robots is null just return the default but with noindex: `noindex, follow`.
|
27 |
+
if ( ! \is_string( $robots ) ) {
|
28 |
+
return 'noindex, follow';
|
29 |
+
}
|
30 |
+
|
31 |
+
// Already noindex.
|
32 |
+
if ( \strpos( $robots, 'noindex' ) !== false ) {
|
33 |
return $robots;
|
34 |
}
|
35 |
|
36 |
+
// Replace index with noindex.
|
37 |
+
if ( \strpos( $robots, 'index' ) !== false ) {
|
38 |
+
return \str_replace( 'index', 'noindex', $robots );
|
39 |
+
}
|
40 |
|
41 |
+
// Add noindex.
|
42 |
+
return 'noindex, ' . $robots;
|
43 |
}
|
44 |
}
|
src/initializers/database-setup.php
DELETED
@@ -1,115 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Yoast SEO Plugin File.
|
4 |
-
*
|
5 |
-
* @package Yoast\YoastSEO\Config
|
6 |
-
*/
|
7 |
-
|
8 |
-
namespace Yoast\WP\SEO\Initializers;
|
9 |
-
|
10 |
-
use wpdb;
|
11 |
-
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
12 |
-
use Yoast\WP\SEO\Loggers\Logger;
|
13 |
-
use Yoast\WP\SEO\ORM\Yoast_Model;
|
14 |
-
use YoastSEO_Vendor\ORM;
|
15 |
-
use YoastSEO_Vendor\Psr\Log\LoggerInterface;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Configures the ORM with the database credentials.
|
19 |
-
*/
|
20 |
-
class Database_Setup implements Initializer_Interface {
|
21 |
-
use No_Conditionals;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* The database object.
|
25 |
-
*
|
26 |
-
* @var wpdb
|
27 |
-
*/
|
28 |
-
protected $wpdb;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* The logger object.
|
32 |
-
*
|
33 |
-
* @var LoggerInterface
|
34 |
-
*/
|
35 |
-
protected $logger;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Database_Setup constructor.
|
39 |
-
*
|
40 |
-
* @param Logger $logger The logger.
|
41 |
-
* @param wpdb $wpdb The wpdb instance.
|
42 |
-
*/
|
43 |
-
public function __construct( Logger $logger, wpdb $wpdb ) {
|
44 |
-
$this->logger = $logger;
|
45 |
-
$this->wpdb = $wpdb;
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Initializes the database setup.
|
50 |
-
*/
|
51 |
-
public function initialize() {
|
52 |
-
ORM::configure( $this->get_connection_string() );
|
53 |
-
ORM::configure( 'username', \DB_USER );
|
54 |
-
ORM::configure( 'password', \DB_PASSWORD );
|
55 |
-
|
56 |
-
Yoast_Model::$auto_prefix_models = '\\Yoast\\WP\\SEO\\Models\\';
|
57 |
-
Yoast_Model::$logger = $this->logger;
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Retrieves the database config from wpdb.
|
62 |
-
*
|
63 |
-
* @return array An array with host, port and socket properties.
|
64 |
-
*/
|
65 |
-
public function get_database_config() {
|
66 |
-
$host = \DB_HOST;
|
67 |
-
$port = null;
|
68 |
-
$socket = null;
|
69 |
-
$is_ipv6 = false;
|
70 |
-
|
71 |
-
$host_data = $this->wpdb->parse_db_host( \DB_HOST );
|
72 |
-
if ( $host_data ) {
|
73 |
-
list( $host, $port, $socket, $is_ipv6 ) = $host_data;
|
74 |
-
}
|
75 |
-
if ( $is_ipv6 && extension_loaded( 'mysqlnd' ) ) {
|
76 |
-
$host = "[$host]";
|
77 |
-
}
|
78 |
-
if ( empty( $port ) ) {
|
79 |
-
$port = ini_get( 'mysqli.default_port' );
|
80 |
-
}
|
81 |
-
if ( empty( $port ) ) {
|
82 |
-
$port = 3306;
|
83 |
-
}
|
84 |
-
if ( empty( $socket ) ) {
|
85 |
-
$socket = ini_get( 'mysqli.default_socket' );
|
86 |
-
}
|
87 |
-
|
88 |
-
return [
|
89 |
-
'host' => $host,
|
90 |
-
'port' => $port,
|
91 |
-
'socket' => $socket,
|
92 |
-
];
|
93 |
-
}
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Builds a connection string from wpdb
|
97 |
-
*
|
98 |
-
* @return string The connection string.
|
99 |
-
*/
|
100 |
-
private function get_connection_string() {
|
101 |
-
$config = $this->get_database_config();
|
102 |
-
|
103 |
-
$connection_string = 'mysql:host=' . $config['host'] . ';dbname=' . \DB_NAME . ';';
|
104 |
-
if ( ! empty( $config['port'] ) ) {
|
105 |
-
$connection_string .= 'port=' . $config['port'] . ';';
|
106 |
-
}
|
107 |
-
if ( ! empty( $config['socket'] ) ) {
|
108 |
-
$connection_string .= 'unix_socket=' . $config['socket'] . ';';
|
109 |
-
}
|
110 |
-
if ( \defined( 'DB_CHARSET' ) && ! empty( \DB_CHARSET ) ) {
|
111 |
-
$connection_string .= 'charset=' . \DB_CHARSET . ';';
|
112 |
-
}
|
113 |
-
return $connection_string;
|
114 |
-
}
|
115 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/initializers/migration-runner.php
CHANGED
@@ -8,10 +8,9 @@
|
|
8 |
namespace Yoast\WP\SEO\Initializers;
|
9 |
|
10 |
use Exception;
|
11 |
-
use Yoast\WP\
|
12 |
use Yoast\WP\SEO\Config\Migration_Status;
|
13 |
-
use Yoast\WP\SEO\
|
14 |
-
use Yoast\WP\SEO\ORM\Yoast_Model;
|
15 |
|
16 |
/**
|
17 |
* Triggers database migrations and handles results.
|
@@ -34,13 +33,6 @@ class Migration_Runner implements Initializer_Interface {
|
|
34 |
*/
|
35 |
protected $framework;
|
36 |
|
37 |
-
/**
|
38 |
-
* The logger object.
|
39 |
-
*
|
40 |
-
* @var Logger
|
41 |
-
*/
|
42 |
-
protected $logger;
|
43 |
-
|
44 |
/**
|
45 |
* The migration status.
|
46 |
*
|
@@ -48,39 +40,24 @@ class Migration_Runner implements Initializer_Interface {
|
|
48 |
*/
|
49 |
protected $migration_status;
|
50 |
|
51 |
-
/**
|
52 |
-
* The database setup object.
|
53 |
-
*
|
54 |
-
* @var Database_Setup
|
55 |
-
*/
|
56 |
-
protected $database_setup;
|
57 |
-
|
58 |
/**
|
59 |
* Migrations constructor.
|
60 |
*
|
61 |
* @param Migration_Status $migration_status The migration status.
|
62 |
* @param Ruckusing_Framework $framework The Ruckusing framework runner.
|
63 |
-
* @param Logger $logger A PSR compatible logger.
|
64 |
-
* @param Database_Setup $database_setup The database setup.
|
65 |
*/
|
66 |
public function __construct(
|
67 |
Migration_Status $migration_status,
|
68 |
-
Ruckusing_Framework $framework
|
69 |
-
Logger $logger,
|
70 |
-
Database_Setup $database_setup
|
71 |
) {
|
72 |
$this->migration_status = $migration_status;
|
73 |
$this->framework = $framework;
|
74 |
-
$this->logger = $logger;
|
75 |
-
$this->database_setup = $database_setup;
|
76 |
}
|
77 |
|
78 |
/**
|
79 |
* Runs this initializer.
|
80 |
*
|
81 |
* @throws \Exception When a migration errored.
|
82 |
-
*
|
83 |
-
* @return void
|
84 |
*/
|
85 |
public function initialize() {
|
86 |
$this->run_free_migrations();
|
@@ -92,11 +69,9 @@ class Migration_Runner implements Initializer_Interface {
|
|
92 |
* Runs the free migrations.
|
93 |
*
|
94 |
* @throws \Exception When a migration errored.
|
95 |
-
*
|
96 |
-
* @return void
|
97 |
*/
|
98 |
public function run_free_migrations() {
|
99 |
-
$this->run_migrations( 'free',
|
100 |
}
|
101 |
|
102 |
/**
|
@@ -120,12 +95,6 @@ class Migration_Runner implements Initializer_Interface {
|
|
120 |
}
|
121 |
|
122 |
try {
|
123 |
-
$database_config = $this->database_setup->get_database_config();
|
124 |
-
if ( ! empty( $database_config['socket'] ) ) {
|
125 |
-
// Temporarily set the defined socket as the default as we can't pass it to ruckusing.
|
126 |
-
$old_mysqli_socket = @ini_set( 'mysqli.default_socket', $database_config['socket'] );
|
127 |
-
}
|
128 |
-
|
129 |
$framework_runner = $this->framework->get_framework_runner( $migrations_table_name, $migrations_directory );
|
130 |
/**
|
131 |
* This variable represents Ruckusing_Adapter_MySQL_Base adapter.
|
@@ -148,8 +117,6 @@ class Migration_Runner implements Initializer_Interface {
|
|
148 |
$task_manager = $this->framework->get_framework_task_manager( $adapter, $migrations_table_name, $migrations_directory );
|
149 |
$task_manager->execute( $framework_runner, 'db:migrate', [] );
|
150 |
} catch ( Exception $exception ) {
|
151 |
-
$this->logger->error( $exception->getMessage() );
|
152 |
-
|
153 |
// Something went wrong...
|
154 |
$this->migration_status->set_error( $name, $exception->getMessage() );
|
155 |
|
@@ -158,11 +125,6 @@ class Migration_Runner implements Initializer_Interface {
|
|
158 |
}
|
159 |
|
160 |
return false;
|
161 |
-
} finally {
|
162 |
-
if ( isset( $old_mysqli_socket ) && $old_mysqli_socket !== false ) {
|
163 |
-
// Always restore the old default if it was overwritten.
|
164 |
-
@ini_set( 'mysqli.default_socket', $old_mysqli_socket );
|
165 |
-
}
|
166 |
}
|
167 |
|
168 |
$this->migration_status->set_success( $name );
|
8 |
namespace Yoast\WP\SEO\Initializers;
|
9 |
|
10 |
use Exception;
|
11 |
+
use Yoast\WP\Lib\Model;
|
12 |
use Yoast\WP\SEO\Config\Migration_Status;
|
13 |
+
use Yoast\WP\SEO\Config\Ruckusing_Framework;
|
|
|
14 |
|
15 |
/**
|
16 |
* Triggers database migrations and handles results.
|
33 |
*/
|
34 |
protected $framework;
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
/**
|
37 |
* The migration status.
|
38 |
*
|
40 |
*/
|
41 |
protected $migration_status;
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
/**
|
44 |
* Migrations constructor.
|
45 |
*
|
46 |
* @param Migration_Status $migration_status The migration status.
|
47 |
* @param Ruckusing_Framework $framework The Ruckusing framework runner.
|
|
|
|
|
48 |
*/
|
49 |
public function __construct(
|
50 |
Migration_Status $migration_status,
|
51 |
+
Ruckusing_Framework $framework
|
|
|
|
|
52 |
) {
|
53 |
$this->migration_status = $migration_status;
|
54 |
$this->framework = $framework;
|
|
|
|
|
55 |
}
|
56 |
|
57 |
/**
|
58 |
* Runs this initializer.
|
59 |
*
|
60 |
* @throws \Exception When a migration errored.
|
|
|
|
|
61 |
*/
|
62 |
public function initialize() {
|
63 |
$this->run_free_migrations();
|
69 |
* Runs the free migrations.
|
70 |
*
|
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 |
/**
|
95 |
}
|
96 |
|
97 |
try {
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
$framework_runner = $this->framework->get_framework_runner( $migrations_table_name, $migrations_directory );
|
99 |
/**
|
100 |
* This variable represents Ruckusing_Adapter_MySQL_Base adapter.
|
117 |
$task_manager = $this->framework->get_framework_task_manager( $adapter, $migrations_table_name, $migrations_directory );
|
118 |
$task_manager->execute( $framework_runner, 'db:migrate', [] );
|
119 |
} catch ( Exception $exception ) {
|
|
|
|
|
120 |
// Something went wrong...
|
121 |
$this->migration_status->set_error( $name, $exception->getMessage() );
|
122 |
|
125 |
}
|
126 |
|
127 |
return false;
|
|
|
|
|
|
|
|
|
|
|
128 |
}
|
129 |
|
130 |
$this->migration_status->set_success( $name );
|
src/integrations/third-party/woocommerce.php
CHANGED
@@ -12,6 +12,7 @@ use Yoast\WP\SEO\Conditionals\Front_End_Conditional;
|
|
12 |
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\Presentations\Indexable_Presentation;
|
16 |
|
17 |
/**
|
@@ -33,6 +34,13 @@ class WooCommerce implements Integration_Interface {
|
|
33 |
*/
|
34 |
private $replace_vars;
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
/**
|
37 |
* @inheritDoc
|
38 |
*/
|
@@ -43,12 +51,18 @@ class WooCommerce implements Integration_Interface {
|
|
43 |
/**
|
44 |
* WooCommerce constructor.
|
45 |
*
|
46 |
-
* @param Options_Helper
|
47 |
-
* @param WPSEO_Replace_Vars
|
|
|
48 |
*/
|
49 |
-
public function __construct(
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
52 |
}
|
53 |
|
54 |
/**
|
@@ -83,7 +97,9 @@ class WooCommerce implements Integration_Interface {
|
|
83 |
*
|
84 |
* @return string The title to use.
|
85 |
*/
|
86 |
-
public function title( $title,
|
|
|
|
|
87 |
if ( $presentation->model->title ) {
|
88 |
return $title;
|
89 |
}
|
@@ -117,7 +133,9 @@ class WooCommerce implements Integration_Interface {
|
|
117 |
*
|
118 |
* @return string The description to use.
|
119 |
*/
|
120 |
-
public function description( $description,
|
|
|
|
|
121 |
if ( $presentation->model->description ) {
|
122 |
return $description;
|
123 |
}
|
@@ -187,4 +205,20 @@ class WooCommerce implements Integration_Interface {
|
|
187 |
|
188 |
return \wc_get_page_id( 'shop' );
|
189 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
190 |
}
|
12 |
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 |
/**
|
34 |
*/
|
35 |
private $replace_vars;
|
36 |
|
37 |
+
/**
|
38 |
+
* The memoizer for the meta tags context.
|
39 |
+
*
|
40 |
+
* @var Meta_Tags_Context_Memoizer
|
41 |
+
*/
|
42 |
+
protected $context_memoizer;
|
43 |
+
|
44 |
/**
|
45 |
* @inheritDoc
|
46 |
*/
|
51 |
/**
|
52 |
* WooCommerce constructor.
|
53 |
*
|
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 |
/**
|
97 |
*
|
98 |
* @return string The title to use.
|
99 |
*/
|
100 |
+
public function title( $title, $presentation = null ) {
|
101 |
+
$presentation = $this->ensure_presentation( $presentation );
|
102 |
+
|
103 |
if ( $presentation->model->title ) {
|
104 |
return $title;
|
105 |
}
|
133 |
*
|
134 |
* @return string The description to use.
|
135 |
*/
|
136 |
+
public function description( $description, $presentation = null ) {
|
137 |
+
$presentation = $this->ensure_presentation( $presentation );
|
138 |
+
|
139 |
if ( $presentation->model->description ) {
|
140 |
return $description;
|
141 |
}
|
205 |
|
206 |
return \wc_get_page_id( 'shop' );
|
207 |
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Ensures a presentation is available.
|
211 |
+
*
|
212 |
+
* @param Indexable_Presentation $presentation The indexable presentation.
|
213 |
+
*
|
214 |
+
* @return Indexable_Presentation The presentation, taken from the current page if the input was invalid.
|
215 |
+
*/
|
216 |
+
protected function ensure_presentation( $presentation ) {
|
217 |
+
if ( \is_a( $presentation, Indexable_Presentation::class ) ) {
|
218 |
+
return $presentation;
|
219 |
+
}
|
220 |
+
|
221 |
+
$context = $this->context_memoizer->for_current_page();
|
222 |
+
return $context->presentation;
|
223 |
+
}
|
224 |
}
|
src/integrations/watchers/indexable-permalink-watcher.php
CHANGED
@@ -10,7 +10,7 @@ namespace Yoast\WP\SEO\Integrations\Watchers;
|
|
10 |
use Yoast\WP\SEO\Conditionals\Migrations_Conditional;
|
11 |
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
|
12 |
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
13 |
-
use Yoast\WP\
|
14 |
use Yoast\WP\SEO\WordPress\Wrapper;
|
15 |
|
16 |
/**
|
@@ -159,7 +159,7 @@ class Indexable_Permalink_Watcher implements Integration_Interface {
|
|
159 |
}
|
160 |
|
161 |
Wrapper::get_wpdb()->update(
|
162 |
-
|
163 |
[
|
164 |
'permalink' => null,
|
165 |
],
|
10 |
use Yoast\WP\SEO\Conditionals\Migrations_Conditional;
|
11 |
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
|
12 |
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
13 |
+
use Yoast\WP\Lib\Model;
|
14 |
use Yoast\WP\SEO\WordPress\Wrapper;
|
15 |
|
16 |
/**
|
159 |
}
|
160 |
|
161 |
Wrapper::get_wpdb()->update(
|
162 |
+
Model::get_table_name( 'Indexable' ),
|
163 |
[
|
164 |
'permalink' => null,
|
165 |
],
|
src/integrations/watchers/indexable-post-watcher.php
CHANGED
@@ -198,10 +198,6 @@ class Indexable_Post_Watcher implements Integration_Interface {
|
|
198 |
// Update the author indexable's has public posts value.
|
199 |
try {
|
200 |
$author_indexable = $this->repository->find_by_id_and_type( $indexable->author_id, 'user' );
|
201 |
-
if ( $author_indexable === false ) {
|
202 |
-
return;
|
203 |
-
}
|
204 |
-
|
205 |
$author_indexable->has_public_posts = $this->author_archive->author_has_public_posts( $author_indexable->object_id );
|
206 |
$author_indexable->save();
|
207 |
} catch ( Exception $exception ) { // @codingStandardsIgnoreLine Generic.CodeAnalysis.EmptyStatement.DetectedCATCH -- There is nothing to do.
|
198 |
// Update the author indexable's has public posts value.
|
199 |
try {
|
200 |
$author_indexable = $this->repository->find_by_id_and_type( $indexable->author_id, 'user' );
|
|
|
|
|
|
|
|
|
201 |
$author_indexable->has_public_posts = $this->author_archive->author_has_public_posts( $author_indexable->object_id );
|
202 |
$author_indexable->save();
|
203 |
} catch ( Exception $exception ) { // @codingStandardsIgnoreLine Generic.CodeAnalysis.EmptyStatement.DetectedCATCH -- There is nothing to do.
|
src/integrations/watchers/option-titles-watcher.php
CHANGED
@@ -9,7 +9,7 @@ namespace Yoast\WP\SEO\Integrations\Watchers;
|
|
9 |
|
10 |
use Yoast\WP\SEO\Conditionals\Migrations_Conditional;
|
11 |
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
12 |
-
use Yoast\WP\
|
13 |
use Yoast\WP\SEO\WordPress\Wrapper;
|
14 |
|
15 |
/**
|
@@ -111,14 +111,14 @@ class Option_Titles_Watcher implements Integration_Interface {
|
|
111 |
$total = \count( $post_types );
|
112 |
$placeholders = \array_fill( 0, $total, '%s' );
|
113 |
$placeholders = \implode( ', ', $placeholders );
|
114 |
-
$hierarchy_table =
|
115 |
-
$indexable_table =
|
116 |
|
117 |
$result = $wpdb->query(
|
118 |
$wpdb->prepare( "
|
119 |
DELETE FROM `$hierarchy_table`
|
120 |
-
WHERE indexable_id IN(
|
121 |
-
SELECT id FROM `$indexable_table` WHERE object_type = 'post' AND object_sub_type IN( $placeholders )
|
122 |
)",
|
123 |
$post_types
|
124 |
)
|
9 |
|
10 |
use Yoast\WP\SEO\Conditionals\Migrations_Conditional;
|
11 |
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
12 |
+
use Yoast\WP\Lib\Model;
|
13 |
use Yoast\WP\SEO\WordPress\Wrapper;
|
14 |
|
15 |
/**
|
111 |
$total = \count( $post_types );
|
112 |
$placeholders = \array_fill( 0, $total, '%s' );
|
113 |
$placeholders = \implode( ', ', $placeholders );
|
114 |
+
$hierarchy_table = Model::get_table_name( 'Indexable_Hierarchy' );
|
115 |
+
$indexable_table = Model::get_table_name( 'Indexable' );
|
116 |
|
117 |
$result = $wpdb->query(
|
118 |
$wpdb->prepare( "
|
119 |
DELETE FROM `$hierarchy_table`
|
120 |
+
WHERE indexable_id IN(
|
121 |
+
SELECT id FROM `$indexable_table` WHERE object_type = 'post' AND object_sub_type IN( $placeholders )
|
122 |
)",
|
123 |
$post_types
|
124 |
)
|
src/loggers/database-logger.php
DELETED
@@ -1,173 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* A simple logger to allow query and memory usage logging.
|
4 |
-
*
|
5 |
-
* @package Yoast\WP\SEO\Loggers
|
6 |
-
*/
|
7 |
-
|
8 |
-
namespace Yoast\WP\SEO\Loggers;
|
9 |
-
|
10 |
-
use Yoast\WP\SEO\Conditionals\Development_Conditional;
|
11 |
-
use Yoast\WP\SEO\Integrations\Integration_Interface;
|
12 |
-
use YoastSEO_Vendor\ORM;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Class Database_Logger
|
16 |
-
*/
|
17 |
-
class Database_Logger implements Integration_Interface {
|
18 |
-
/**
|
19 |
-
* Private array of queries used for logging.
|
20 |
-
*
|
21 |
-
* @var array
|
22 |
-
*/
|
23 |
-
protected $query_log = [];
|
24 |
-
|
25 |
-
/**
|
26 |
-
* @inheritDoc
|
27 |
-
*/
|
28 |
-
public function register_hooks() {
|
29 |
-
ORM::configure( 'logging', true );
|
30 |
-
ORM::configure( 'logger', [ $this, 'logger' ] );
|
31 |
-
|
32 |
-
\add_action( 'shutdown', [ $this, 'log_output' ] );
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @inheritDoc
|
37 |
-
*/
|
38 |
-
public static function get_conditionals() {
|
39 |
-
return [ Development_Conditional::class ];
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Logs the query to a local variable for output on shutdown.
|
44 |
-
*
|
45 |
-
* @param string $query The query.
|
46 |
-
* @param float $time The time the query took to execute.
|
47 |
-
*
|
48 |
-
* @return void
|
49 |
-
*/
|
50 |
-
public function logger( $query, $time ) {
|
51 |
-
$query = [
|
52 |
-
'query' => $query,
|
53 |
-
'time' => $time,
|
54 |
-
];
|
55 |
-
$this->query_log[] = $query;
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Outputs some logging.
|
60 |
-
*
|
61 |
-
* @return void
|
62 |
-
*/
|
63 |
-
public function log_output() {
|
64 |
-
$content_type = $this->get_content_type();
|
65 |
-
|
66 |
-
if (
|
67 |
-
\wp_doing_ajax() ||
|
68 |
-
( defined( 'WP_CLI' ) && WP_CLI ) ||
|
69 |
-
( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
|
70 |
-
( stripos( $content_type, 'text/html' ) === false && $content_type !== '' )
|
71 |
-
) {
|
72 |
-
return;
|
73 |
-
}
|
74 |
-
|
75 |
-
echo PHP_EOL, PHP_EOL, '<!--';
|
76 |
-
|
77 |
-
$this->log_time();
|
78 |
-
$this->log_memory_usage();
|
79 |
-
$this->log_idiorm_queries();
|
80 |
-
$this->log_wpdb_queries();
|
81 |
-
|
82 |
-
echo '-->', PHP_EOL;
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Get the content type from the return header.
|
87 |
-
*
|
88 |
-
* @return string The return header if any, empty string if not.
|
89 |
-
*/
|
90 |
-
private function get_content_type() {
|
91 |
-
$headers = headers_list();
|
92 |
-
foreach ( $headers as $header ) {
|
93 |
-
if ( stripos( $header, 'Content-Type:' ) !== false ) {
|
94 |
-
return (string) preg_replace( '/^Content-Type:\s*(.*)/', '$1', $header );
|
95 |
-
}
|
96 |
-
}
|
97 |
-
|
98 |
-
return '';
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Outputs a log header.
|
103 |
-
*
|
104 |
-
* @param string $string The header to output.
|
105 |
-
*
|
106 |
-
* @return void
|
107 |
-
*/
|
108 |
-
private function header( $string ) {
|
109 |
-
echo PHP_EOL, PHP_EOL, $string, PHP_EOL;
|
110 |
-
echo '====', PHP_EOL;
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Logs the memory usage.
|
115 |
-
*
|
116 |
-
* @return void
|
117 |
-
*/
|
118 |
-
protected function log_memory_usage() {
|
119 |
-
$memory_used_peak = number_format( ( memory_get_peak_usage() / ( 1024 * 1024 ) ), 2 );
|
120 |
-
$memory_used = number_format( ( memory_get_usage() / ( 1024 * 1024 ) ), 2 );
|
121 |
-
|
122 |
-
$this->header( 'Memory usage' );
|
123 |
-
echo 'Peak: ', $memory_used_peak, 'MB', PHP_EOL;
|
124 |
-
echo 'Average: ', $memory_used, 'MB', PHP_EOL;
|
125 |
-
}
|
126 |
-
|
127 |
-
/**
|
128 |
-
* Logs the IdiORM queries.
|
129 |
-
*
|
130 |
-
* @return void
|
131 |
-
*/
|
132 |
-
protected function log_idiorm_queries() {
|
133 |
-
$this->header( 'Yoast Idiorm Queries (' . count( $this->query_log ) . ')' );
|
134 |
-
$i = 1;
|
135 |
-
foreach ( $this->query_log as $query ) {
|
136 |
-
echo $i, ': "', $query['query'], '" in ', round( $query['time'], 5 ), PHP_EOL;
|
137 |
-
$i ++;
|
138 |
-
}
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Logs the WPDB queries, if `SAVEQUERIES` has been set to true.
|
143 |
-
*
|
144 |
-
* @return void
|
145 |
-
*/
|
146 |
-
protected function log_wpdb_queries() {
|
147 |
-
if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
|
148 |
-
global $wpdb;
|
149 |
-
$this->header( 'WPDB Queries (' . count( $wpdb->queries ) . ')' );
|
150 |
-
$i = 1;
|
151 |
-
foreach ( $wpdb->queries as $query ) {
|
152 |
-
echo $i, ': "', trim( $query[0] ), '" in ', round( $query[1], 5 ), PHP_EOL;
|
153 |
-
echo ' ', $query[2], PHP_EOL;
|
154 |
-
$i ++;
|
155 |
-
}
|
156 |
-
|
157 |
-
return;
|
158 |
-
}
|
159 |
-
$this->header( 'WPDB Queries' );
|
160 |
-
echo 'Please add this to your wp-config.php to allow WPDB Query logging:', PHP_EOL;
|
161 |
-
echo "define( 'SAVEQUERIES', true );", PHP_EOL;
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* Logs the request time.
|
166 |
-
*
|
167 |
-
* @return void
|
168 |
-
*/
|
169 |
-
protected function log_time() {
|
170 |
-
$this->header( 'Request time' );
|
171 |
-
echo timer_stop(), 's', PHP_EOL;
|
172 |
-
}
|
173 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/models/indexable-extension.php
CHANGED
@@ -7,12 +7,12 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Abstract class for indexable extensions.
|
14 |
*/
|
15 |
-
abstract class Indexable_Extension extends
|
16 |
|
17 |
/**
|
18 |
* Holds the Indexable instance.
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Abstract class for indexable extensions.
|
14 |
*/
|
15 |
+
abstract class Indexable_Extension extends Model {
|
16 |
|
17 |
/**
|
18 |
* Holds the Indexable instance.
|
src/models/indexable-hierarchy.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Indexable Hierarchy model definition.
|
@@ -17,7 +17,7 @@ use Yoast\WP\SEO\ORM\Yoast_Model;
|
|
17 |
* @property int $depth The depth of the ancestry. 1 being a parent, 2 being a grandparent etc.
|
18 |
* @property int $blog_id Blog ID.
|
19 |
*/
|
20 |
-
class Indexable_Hierarchy extends
|
21 |
|
22 |
/**
|
23 |
* Which columns contain int values.
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Indexable Hierarchy model definition.
|
17 |
* @property int $depth The depth of the ancestry. 1 being a parent, 2 being a grandparent etc.
|
18 |
* @property int $blog_id Blog ID.
|
19 |
*/
|
20 |
+
class Indexable_Hierarchy extends Model {
|
21 |
|
22 |
/**
|
23 |
* Which columns contain int values.
|
src/models/indexable.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Indexable table definition.
|
@@ -78,7 +78,7 @@ use Yoast\WP\SEO\ORM\Yoast_Model;
|
|
78 |
* @property string $schema_page_type
|
79 |
* @property string $schema_article_type
|
80 |
*/
|
81 |
-
class Indexable extends
|
82 |
|
83 |
/**
|
84 |
* Whether nor this model uses timestamps.
|
@@ -153,9 +153,15 @@ class Indexable extends Yoast_Model {
|
|
153 |
*/
|
154 |
public function save() {
|
155 |
if ( $this->permalink ) {
|
156 |
-
$
|
|
|
|
|
|
|
157 |
$this->permalink_hash = \strlen( $this->permalink ) . ':' . \md5( $this->permalink );
|
158 |
}
|
|
|
|
|
|
|
159 |
|
160 |
return parent::save();
|
161 |
}
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Indexable table definition.
|
78 |
* @property string $schema_page_type
|
79 |
* @property string $schema_article_type
|
80 |
*/
|
81 |
+
class Indexable extends Model {
|
82 |
|
83 |
/**
|
84 |
* Whether nor this model uses timestamps.
|
153 |
*/
|
154 |
public function save() {
|
155 |
if ( $this->permalink ) {
|
156 |
+
$permalink_structure = get_option( 'permalink_structure' );
|
157 |
+
if ( substr( $permalink_structure , -1, 1 ) === '/' ) {
|
158 |
+
$this->permalink = \trailingslashit( $this->permalink );
|
159 |
+
}
|
160 |
$this->permalink_hash = \strlen( $this->permalink ) . ':' . \md5( $this->permalink );
|
161 |
}
|
162 |
+
if ( \strlen( $this->primary_focus_keyword ) > 191 ) {
|
163 |
+
$this->primary_focus_keyword = substr( $this->primary_focus_keyword, 0, 191 );
|
164 |
+
}
|
165 |
|
166 |
return parent::save();
|
167 |
}
|
src/models/primary-term.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Primary Term model definition.
|
@@ -21,7 +21,7 @@ use Yoast\WP\SEO\ORM\Yoast_Model;
|
|
21 |
* @property string $created_at
|
22 |
* @property string $updated_at
|
23 |
*/
|
24 |
-
class Primary_Term extends
|
25 |
|
26 |
/**
|
27 |
* Whether nor this model uses timestamps.
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Primary Term model definition.
|
21 |
* @property string $created_at
|
22 |
* @property string $updated_at
|
23 |
*/
|
24 |
+
class Primary_Term extends Model {
|
25 |
|
26 |
/**
|
27 |
* Whether nor this model uses timestamps.
|
src/models/seo-links.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Table definition for the SEO Meta table.
|
@@ -18,7 +18,7 @@ use Yoast\WP\SEO\ORM\Yoast_Model;
|
|
18 |
* @property int $target_post_id
|
19 |
* @property string $type
|
20 |
*/
|
21 |
-
class SEO_Links extends
|
22 |
|
23 |
/**
|
24 |
* Which columns contain int values.
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Table definition for the SEO Meta table.
|
18 |
* @property int $target_post_id
|
19 |
* @property string $type
|
20 |
*/
|
21 |
+
class SEO_Links extends Model {
|
22 |
|
23 |
/**
|
24 |
* Which columns contain int values.
|
src/models/seo-meta.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
-
use Yoast\WP\
|
11 |
|
12 |
/**
|
13 |
* Table definition for the SEO Meta table.
|
@@ -16,7 +16,7 @@ use Yoast\WP\SEO\ORM\Yoast_Model;
|
|
16 |
* @property int $internal_link_count
|
17 |
* @property int $incoming_link_count
|
18 |
*/
|
19 |
-
class SEO_Meta extends
|
20 |
|
21 |
/**
|
22 |
* Overwrites the default ID column name.
|
7 |
|
8 |
namespace Yoast\WP\SEO\Models;
|
9 |
|
10 |
+
use Yoast\WP\Lib\Model;
|
11 |
|
12 |
/**
|
13 |
* Table definition for the SEO Meta table.
|
16 |
* @property int $internal_link_count
|
17 |
* @property int $incoming_link_count
|
18 |
*/
|
19 |
+
class SEO_Meta extends Model {
|
20 |
|
21 |
/**
|
22 |
* Overwrites the default ID column name.
|
src/orm/yoast-orm-wrapper.php
DELETED
@@ -1,234 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Yoast extension of the ORM class.
|
4 |
-
*
|
5 |
-
* @package Yoast\YoastSEO
|
6 |
-
*/
|
7 |
-
|
8 |
-
namespace Yoast\WP\SEO\ORM;
|
9 |
-
|
10 |
-
use Exception;
|
11 |
-
use PDO;
|
12 |
-
use Yoast\WP\Polyfills\PDO\PDO_MySQLi_Polyfill;
|
13 |
-
use Yoast\WP\SEO\Initializers\Migration_Runner;
|
14 |
-
use YoastSEO_Vendor\ORM;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Subclass of Idiorm's ORM class that supports
|
18 |
-
* returning instances of a specified class rather
|
19 |
-
* than raw instances of the ORM class.
|
20 |
-
*
|
21 |
-
* You shouldn't need to interact with this class
|
22 |
-
* directly. It is used internally by the Model base
|
23 |
-
* class.
|
24 |
-
*
|
25 |
-
* The methods documented below are magic methods that conform to PSR-1.
|
26 |
-
* This documentation exposes these methods to doc generators and IDEs.
|
27 |
-
*
|
28 |
-
* @link http://www.php-fig.org/psr/psr-1/
|
29 |
-
*
|
30 |
-
* @method void setClassName($class_name)
|
31 |
-
* @method static \Yoast\WP\SEO\ORM\ORMWrapper forTable($table_name, $connection_name = parent::DEFAULT_CONNECTION)
|
32 |
-
* @method \Yoast\WP\SEO\ORM\\Model findOne($id=null)
|
33 |
-
* @method Array|\IdiormResultSet findMany()
|
34 |
-
*/
|
35 |
-
class ORMWrapper extends ORM {
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Contains the repositories.
|
39 |
-
*
|
40 |
-
* @var array
|
41 |
-
*/
|
42 |
-
public static $repositories = [];
|
43 |
-
|
44 |
-
/**
|
45 |
-
* The wrapped find_one and find_many classes will return an instance or
|
46 |
-
* instances of this class.
|
47 |
-
*
|
48 |
-
* @var string
|
49 |
-
*/
|
50 |
-
protected $class_name;
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Set the name of the class which the wrapped methods should return
|
54 |
-
* instances of.
|
55 |
-
*
|
56 |
-
* @param string $class_name The classname to set.
|
57 |
-
*
|
58 |
-
* @return void
|
59 |
-
*/
|
60 |
-
public function set_class_name( $class_name ) {
|
61 |
-
$this->class_name = $class_name;
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Add a custom filter to the method chain specified on the model class.
|
66 |
-
* This allows custom queries to be added to models. The filter should take
|
67 |
-
* an instance of the ORM wrapper as its first argument and return an
|
68 |
-
* instance of the ORM wrapper. Any arguments passed to this method after
|
69 |
-
* the name of the filter will be passed to the called filter function as
|
70 |
-
* arguments after the ORM class.
|
71 |
-
*
|
72 |
-
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM wrapper.
|
73 |
-
*/
|
74 |
-
public function filter() {
|
75 |
-
$args = \func_get_args();
|
76 |
-
$filter_function = \array_shift( $args );
|
77 |
-
\array_unshift( $args, $this );
|
78 |
-
if ( \method_exists( $this->class_name, $filter_function ) ) {
|
79 |
-
return \call_user_func_array( [ $this->class_name, $filter_function ], $args );
|
80 |
-
}
|
81 |
-
|
82 |
-
return null;
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Factory method, return an instance of this class bound to the supplied
|
87 |
-
* table name.
|
88 |
-
*
|
89 |
-
* A repeat of content in parent::for_table, so that created class is
|
90 |
-
* ORMWrapper, not ORM.
|
91 |
-
*
|
92 |
-
* @param string $table_name The table to create instance for.
|
93 |
-
* @param string $connection_name The connection name.
|
94 |
-
*
|
95 |
-
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM wrapper.
|
96 |
-
*/
|
97 |
-
public static function for_table( $table_name, $connection_name = parent::DEFAULT_CONNECTION ) {
|
98 |
-
static::_setup_db( $connection_name );
|
99 |
-
return new static( $table_name, [], $connection_name );
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* Method to create an instance of the model class associated with this
|
104 |
-
* wrapper and populate it with the supplied Idiorm instance.
|
105 |
-
*
|
106 |
-
* @param \Yoast\WP\SEO\ORM\ORMWrapper|\YoastSEO_Vendor\ORM $orm The ORM used by model.
|
107 |
-
*
|
108 |
-
* @return bool|\Yoast\WP\SEO\ORM\Yoast_Model Instance of the model class.
|
109 |
-
*/
|
110 |
-
protected function create_model_instance( $orm ) {
|
111 |
-
if ( $orm === false ) {
|
112 |
-
return false;
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* An instance of Yoast_Model is being made.
|
117 |
-
*
|
118 |
-
* @var \Yoast\WP\SEO\ORM\Yoast_Model $model
|
119 |
-
*/
|
120 |
-
$model = new $this->class_name();
|
121 |
-
$model->set_orm( $orm );
|
122 |
-
|
123 |
-
return $model;
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Wrap Idiorm's find_one method to return an instance of the class
|
128 |
-
* associated with this wrapper instead of the raw ORM class.
|
129 |
-
*
|
130 |
-
* @param null|integer $id The ID to lookup.
|
131 |
-
*
|
132 |
-
* @return \Yoast\WP\SEO\ORM\Yoast_Model Instance of the model.
|
133 |
-
*/
|
134 |
-
public function find_one( $id = null ) {
|
135 |
-
return $this->create_model_instance( parent::find_one( $id ) );
|
136 |
-
}
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Wrap Idiorm's find_many method to return an array of instances of the
|
140 |
-
* class associated with this wrapper instead of the raw ORM class.
|
141 |
-
*
|
142 |
-
* @return array The found results.
|
143 |
-
*/
|
144 |
-
public function find_many() {
|
145 |
-
$results = parent::find_many();
|
146 |
-
foreach ( $results as $key => $result ) {
|
147 |
-
$results[ $key ] = $this->create_model_instance( $result );
|
148 |
-
}
|
149 |
-
|
150 |
-
return $results;
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Wrap Idiorm's create method to return an empty instance of the class
|
155 |
-
* associated with this wrapper instead of the raw ORM class.
|
156 |
-
*
|
157 |
-
* @param null|mixed $data The data to pass.
|
158 |
-
*
|
159 |
-
* @return \Yoast\WP\SEO\ORM\Yoast_Model|bool Instance of the ORM.
|
160 |
-
*/
|
161 |
-
public function create( $data = null ) {
|
162 |
-
return $this->create_model_instance( parent::create( $data ) );
|
163 |
-
}
|
164 |
-
|
165 |
-
/**
|
166 |
-
* Returns the select query as SQL.
|
167 |
-
*
|
168 |
-
* @return string The select query in SQL.
|
169 |
-
*/
|
170 |
-
public function get_sql() {
|
171 |
-
return $this->_build_select();
|
172 |
-
}
|
173 |
-
|
174 |
-
/**
|
175 |
-
* Returns the update query as SQL.
|
176 |
-
*
|
177 |
-
* @return string The update query in SQL.
|
178 |
-
*/
|
179 |
-
public function get_update_sql() {
|
180 |
-
return $this->_build_update();
|
181 |
-
}
|
182 |
-
|
183 |
-
/**
|
184 |
-
* Set up the database connection used by the class
|
185 |
-
*
|
186 |
-
* @param string $connection_name Which connection to use.
|
187 |
-
*/
|
188 |
-
protected static function _setup_db( $connection_name = self::DEFAULT_CONNECTION ) {
|
189 |
-
if (
|
190 |
-
! array_key_exists( $connection_name, self::$_db ) ||
|
191 |
-
! is_object( self::$_db[ $connection_name ] )
|
192 |
-
) {
|
193 |
-
self::_setup_db_config( $connection_name );
|
194 |
-
|
195 |
-
if ( extension_loaded( 'pdo_mysql' ) ) {
|
196 |
-
// @codingStandardsIgnoreStart -- Reason: This is part of a well-tested library.
|
197 |
-
$db = new PDO(
|
198 |
-
self::$_config[ $connection_name ]['connection_string'],
|
199 |
-
self::$_config[ $connection_name ]['username'],
|
200 |
-
self::$_config[ $connection_name ]['password'],
|
201 |
-
self::$_config[ $connection_name ]['driver_options']
|
202 |
-
);
|
203 |
-
$db->setAttribute( PDO::ATTR_ERRMODE, self::$_config[ $connection_name ]['error_mode'] );
|
204 |
-
// @codingStandardsIgnoreEnd -- Reason: This is part of a well-tested library.
|
205 |
-
}
|
206 |
-
else {
|
207 |
-
$db = new PDO_MySQLi_Polyfill(
|
208 |
-
self::$_config[ $connection_name ]['connection_string'],
|
209 |
-
self::$_config[ $connection_name ]['username'],
|
210 |
-
self::$_config[ $connection_name ]['password'],
|
211 |
-
self::$_config[ $connection_name ]['driver_options']
|
212 |
-
);
|
213 |
-
}
|
214 |
-
|
215 |
-
self::set_db( $db, $connection_name );
|
216 |
-
}
|
217 |
-
}
|
218 |
-
|
219 |
-
/**
|
220 |
-
* Execute the SELECT query that has been built up by chaining methods
|
221 |
-
* on this class. Return an array of rows as associative arrays.
|
222 |
-
*/
|
223 |
-
protected function _run() {
|
224 |
-
try {
|
225 |
-
return parent::_run();
|
226 |
-
} catch ( Exception $exception ) {
|
227 |
-
// If the query fails run the migrations and try again.
|
228 |
-
// Action is intentionally undocumented and should not be used by third-parties.
|
229 |
-
\do_action( '_yoast_run_migrations' );
|
230 |
-
$this->_reset_idiorm_state();
|
231 |
-
return parent::_run();
|
232 |
-
}
|
233 |
-
}
|
234 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/presenters/admin/indexation-warning-presenter.php
CHANGED
@@ -21,7 +21,7 @@ class Indexation_Warning_Presenter extends Abstract_Presenter {
|
|
21 |
*/
|
22 |
public function present() {
|
23 |
return \sprintf(
|
24 |
-
'<div id="yoast-indexation-warning" class="notice notice-success"><p>%1$s</p>%
|
25 |
\sprintf(
|
26 |
/* translators: 1: Strong start tag, 2: Strong closing tag, 3: Yoast SEO. */
|
27 |
\esc_html__( '%1$sNEW:%2$s %3$s can now store your site’s SEO data in a smarter way!', 'wordpress-seo' ),
|
@@ -29,6 +29,7 @@ class Indexation_Warning_Presenter extends Abstract_Presenter {
|
|
29 |
'</strong>',
|
30 |
'Yoast SEO'
|
31 |
),
|
|
|
32 |
\sprintf(
|
33 |
/* translators: 1: Button start tag to open the indexation modal, 2: Button closing tag. */
|
34 |
\esc_html__( '%1$sClick here to speed up your site now%2$s', 'wordpress-seo' ),
|
21 |
*/
|
22 |
public function present() {
|
23 |
return \sprintf(
|
24 |
+
'<div id="yoast-indexation-warning" class="notice notice-success"><p>%1$s<br/>%2$s</p>%3$s<p>%4$s</p></div>',
|
25 |
\sprintf(
|
26 |
/* translators: 1: Strong start tag, 2: Strong closing tag, 3: Yoast SEO. */
|
27 |
\esc_html__( '%1$sNEW:%2$s %3$s can now store your site’s SEO data in a smarter way!', 'wordpress-seo' ),
|
29 |
'</strong>',
|
30 |
'Yoast SEO'
|
31 |
),
|
32 |
+
\esc_html__( 'Don\'t worry: this won\'t have to be done after each update.', 'wordpress-seo' ),
|
33 |
\sprintf(
|
34 |
/* translators: 1: Button start tag to open the indexation modal, 2: Button closing tag. */
|
35 |
\esc_html__( '%1$sClick here to speed up your site now%2$s', 'wordpress-seo' ),
|
src/repositories/indexable-hierarchy-repository.php
CHANGED
@@ -10,7 +10,7 @@ namespace Yoast\WP\SEO\Repositories;
|
|
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\
|
14 |
|
15 |
/**
|
16 |
* Class Indexable_Hierarchy_Repository
|
@@ -55,7 +55,7 @@ class Indexable_Hierarchy_Repository {
|
|
55 |
* @param int $ancestor_id The ancestor id.
|
56 |
* @param int $depth The depth.
|
57 |
*
|
58 |
-
* @return bool|
|
59 |
*/
|
60 |
public function add_ancestor( $indexable_id, $ancestor_id, $depth ) {
|
61 |
$hierarchy = $this->query()->create( [
|
@@ -101,6 +101,6 @@ class Indexable_Hierarchy_Repository {
|
|
101 |
* @return \Yoast\WP\SEO\ORM\ORMWrapper
|
102 |
*/
|
103 |
public function query() {
|
104 |
-
return
|
105 |
}
|
106 |
}
|
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
|
55 |
* @param int $ancestor_id The ancestor id.
|
56 |
* @param int $depth The depth.
|
57 |
*
|
58 |
+
* @return bool|Model
|
59 |
*/
|
60 |
public function add_ancestor( $indexable_id, $ancestor_id, $depth ) {
|
61 |
$hierarchy = $this->query()->create( [
|
101 |
* @return \Yoast\WP\SEO\ORM\ORMWrapper
|
102 |
*/
|
103 |
public function query() {
|
104 |
+
return Model::of_type( 'Indexable_Hierarchy' );
|
105 |
}
|
106 |
}
|
src/repositories/indexable-repository.php
CHANGED
@@ -13,7 +13,7 @@ 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\
|
17 |
|
18 |
/**
|
19 |
* Class Indexable_Repository
|
@@ -77,7 +77,7 @@ class Indexable_Repository {
|
|
77 |
* @return ORMWrapper
|
78 |
*/
|
79 |
public function query() {
|
80 |
-
return
|
81 |
}
|
82 |
|
83 |
/**
|
@@ -121,7 +121,7 @@ class Indexable_Repository {
|
|
121 |
}
|
122 |
|
123 |
if ( $indexable === false ) {
|
124 |
-
return $this->query()->create( [ 'object_type' => 'unknown' ] );
|
125 |
}
|
126 |
|
127 |
return $indexable;
|
@@ -335,14 +335,7 @@ class Indexable_Repository {
|
|
335 |
$indexables_to_create = \array_diff( $object_ids, $indexables_available );
|
336 |
|
337 |
foreach ( $indexables_to_create as $indexable_to_create ) {
|
338 |
-
$
|
339 |
-
if ( $indexable === false ) {
|
340 |
-
continue;
|
341 |
-
}
|
342 |
-
|
343 |
-
$indexable->save();
|
344 |
-
|
345 |
-
$indexables[] = $indexable;
|
346 |
}
|
347 |
}
|
348 |
|
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
|
77 |
* @return ORMWrapper
|
78 |
*/
|
79 |
public function query() {
|
80 |
+
return Model::of_type( 'Indexable' );
|
81 |
}
|
82 |
|
83 |
/**
|
121 |
}
|
122 |
|
123 |
if ( $indexable === false ) {
|
124 |
+
return $this->query()->create( [ 'object_type' => 'unknown', 'post_status' => 'unindexed' ] );
|
125 |
}
|
126 |
|
127 |
return $indexable;
|
335 |
$indexables_to_create = \array_diff( $object_ids, $indexables_available );
|
336 |
|
337 |
foreach ( $indexables_to_create as $indexable_to_create ) {
|
338 |
+
$indexables[] = $this->builder->build_for_id_and_type( $indexable_to_create, $object_type );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
}
|
340 |
}
|
341 |
|
src/repositories/primary-term-repository.php
CHANGED
@@ -9,7 +9,7 @@ namespace Yoast\WP\SEO\Repositories;
|
|
9 |
|
10 |
use Yoast\WP\SEO\Models\Primary_Term;
|
11 |
use Yoast\WP\SEO\ORM\ORMWrapper;
|
12 |
-
use Yoast\WP\
|
13 |
|
14 |
/**
|
15 |
* Class Primary_Term_Repository
|
@@ -24,7 +24,7 @@ class Primary_Term_Repository {
|
|
24 |
* @return ORMWrapper
|
25 |
*/
|
26 |
public function query() {
|
27 |
-
return
|
28 |
}
|
29 |
|
30 |
/**
|
9 |
|
10 |
use Yoast\WP\SEO\Models\Primary_Term;
|
11 |
use Yoast\WP\SEO\ORM\ORMWrapper;
|
12 |
+
use Yoast\WP\Lib\Model;
|
13 |
|
14 |
/**
|
15 |
* Class Primary_Term_Repository
|
24 |
* @return ORMWrapper
|
25 |
*/
|
26 |
public function query() {
|
27 |
+
return Model::of_type( 'Primary_Term' );
|
28 |
}
|
29 |
|
30 |
/**
|
src/repositories/seo-links-repository.php
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
namespace Yoast\WP\SEO\Repositories;
|
9 |
|
10 |
use Yoast\WP\SEO\ORM\ORMWrapper;
|
11 |
-
use Yoast\WP\
|
12 |
|
13 |
/**
|
14 |
* Class SEO_Links_Repository
|
@@ -23,6 +23,6 @@ class SEO_Links_Repository {
|
|
23 |
* @return ORMWrapper
|
24 |
*/
|
25 |
public function query() {
|
26 |
-
return
|
27 |
}
|
28 |
}
|
8 |
namespace Yoast\WP\SEO\Repositories;
|
9 |
|
10 |
use Yoast\WP\SEO\ORM\ORMWrapper;
|
11 |
+
use Yoast\WP\Lib\Model;
|
12 |
|
13 |
/**
|
14 |
* Class SEO_Links_Repository
|
23 |
* @return ORMWrapper
|
24 |
*/
|
25 |
public function query() {
|
26 |
+
return Model::of_type( 'SEO_Links' );
|
27 |
}
|
28 |
}
|
src/repositories/seo-meta-repository.php
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
namespace Yoast\WP\SEO\Repositories;
|
9 |
|
10 |
use Yoast\WP\SEO\ORM\ORMWrapper;
|
11 |
-
use Yoast\WP\
|
12 |
|
13 |
/**
|
14 |
* Class SEO_Meta_Repository
|
@@ -23,7 +23,7 @@ class SEO_Meta_Repository {
|
|
23 |
* @return ORMWrapper
|
24 |
*/
|
25 |
public function query() {
|
26 |
-
return
|
27 |
}
|
28 |
|
29 |
/**
|
8 |
namespace Yoast\WP\SEO\Repositories;
|
9 |
|
10 |
use Yoast\WP\SEO\ORM\ORMWrapper;
|
11 |
+
use Yoast\WP\Lib\Model;
|
12 |
|
13 |
/**
|
14 |
* Class SEO_Meta_Repository
|
23 |
* @return ORMWrapper
|
24 |
*/
|
25 |
public function query() {
|
26 |
+
return Model::of_type( 'SEO_Meta' );
|
27 |
}
|
28 |
|
29 |
/**
|
vendor/composer/autoload_classmap.php
CHANGED
@@ -125,7 +125,7 @@ return array(
|
|
125 |
'WPSEO_Advanced_Settings' => $baseDir . '/deprecated/class-wpseo-advanced-settings.php',
|
126 |
'WPSEO_Author_Sitemap_Provider' => $baseDir . '/inc/sitemaps/class-author-sitemap-provider.php',
|
127 |
'WPSEO_Base_Menu' => $baseDir . '/admin/menu/class-base-menu.php',
|
128 |
-
'WPSEO_Breadcrumbs' => $baseDir . '/
|
129 |
'WPSEO_Bulk_Description_List_Table' => $baseDir . '/admin/class-bulk-description-editor-list-table.php',
|
130 |
'WPSEO_Bulk_List_Table' => $baseDir . '/admin/class-bulk-editor-list-table.php',
|
131 |
'WPSEO_Bulk_Title_Editor_List_Table' => $baseDir . '/admin/class-bulk-title-editor-list-table.php',
|
@@ -210,7 +210,7 @@ return array(
|
|
210 |
'WPSEO_Features' => $baseDir . '/inc/class-wpseo-features.php',
|
211 |
'WPSEO_File_Size_Exception' => $baseDir . '/admin/exceptions/class-file-size-exception.php',
|
212 |
'WPSEO_File_Size_Service' => $baseDir . '/admin/services/class-file-size.php',
|
213 |
-
'WPSEO_Frontend' => $baseDir . '/
|
214 |
'WPSEO_Frontend_Page_Type' => $baseDir . '/frontend/class-frontend-page-type.php',
|
215 |
'WPSEO_Frontend_Primary_Category' => $baseDir . '/deprecated/frontend/class-primary-category.php',
|
216 |
'WPSEO_GSC' => $baseDir . '/admin/google_search_console/class-gsc.php',
|
@@ -621,6 +621,10 @@ return array(
|
|
621 |
'YoastSEO_Vendor\\Task_Db_Setup' => $baseDir . '/vendor_prefixed/ruckusing/lib/Task/Db/Setup.php',
|
622 |
'YoastSEO_Vendor\\Task_Db_Status' => $baseDir . '/vendor_prefixed/ruckusing/lib/Task/Db/Status.php',
|
623 |
'YoastSEO_Vendor\\Task_Db_Version' => $baseDir . '/vendor_prefixed/ruckusing/lib/Task/Db/Version.php',
|
|
|
|
|
|
|
|
|
624 |
'Yoast\\WP\\SEO\\Actions\\Indexables\\Indexable_Head_Action' => $baseDir . '/src/actions/indexables/indexable-head-action.php',
|
625 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_General_Indexation_Action' => $baseDir . '/src/actions/indexation/indexable-general-indexation-action.php',
|
626 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Indexation_Action' => $baseDir . '/src/actions/indexation/indexable-post-indexation-action.php',
|
@@ -707,7 +711,6 @@ return array(
|
|
707 |
'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => $baseDir . '/src/helpers/twitter/image-helper.php',
|
708 |
'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => $baseDir . '/src/helpers/url-helper.php',
|
709 |
'Yoast\\WP\\SEO\\Helpers\\User_Helper' => $baseDir . '/src/helpers/user-helper.php',
|
710 |
-
'Yoast\\WP\\SEO\\Initializers\\Database_Setup' => $baseDir . '/src/initializers/database-setup.php',
|
711 |
'Yoast\\WP\\SEO\\Initializers\\Initializer_Interface' => $baseDir . '/src/initializers/initializer-interface.php',
|
712 |
'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => $baseDir . '/src/initializers/migration-runner.php',
|
713 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => $baseDir . '/src/integrations/admin/indexation-integration.php',
|
@@ -745,7 +748,6 @@ return array(
|
|
745 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => $baseDir . '/src/integrations/watchers/primary-term-watcher.php',
|
746 |
'Yoast\\WP\\SEO\\Loadable_Interface' => $baseDir . '/src/loadable-interface.php',
|
747 |
'Yoast\\WP\\SEO\\Loader' => $baseDir . '/src/loader.php',
|
748 |
-
'Yoast\\WP\\SEO\\Loggers\\Database_Logger' => $baseDir . '/src/loggers/database-logger.php',
|
749 |
'Yoast\\WP\\SEO\\Loggers\\Logger' => $baseDir . '/src/loggers/logger.php',
|
750 |
'Yoast\\WP\\SEO\\Loggers\\Migration_Logger' => $baseDir . '/src/loggers/migration-logger.php',
|
751 |
'Yoast\\WP\\SEO\\Main' => $baseDir . '/src/main.php',
|
@@ -757,8 +759,6 @@ return array(
|
|
757 |
'Yoast\\WP\\SEO\\Models\\Primary_Term' => $baseDir . '/src/models/primary-term.php',
|
758 |
'Yoast\\WP\\SEO\\Models\\SEO_Links' => $baseDir . '/src/models/seo-links.php',
|
759 |
'Yoast\\WP\\SEO\\Models\\SEO_Meta' => $baseDir . '/src/models/seo-meta.php',
|
760 |
-
'Yoast\\WP\\SEO\\ORM\\ORMWrapper' => $baseDir . '/src/orm/yoast-orm-wrapper.php',
|
761 |
-
'Yoast\\WP\\SEO\\ORM\\Yoast_Model' => $baseDir . '/src/orm/yoast-model.php',
|
762 |
'Yoast\\WP\\SEO\\Oauth\\Client' => $baseDir . '/src/oauth/client.php',
|
763 |
'Yoast\\WP\\SEO\\Presentations\\Abstract_Presentation' => $baseDir . '/src/presentations/abstract-presentation.php',
|
764 |
'Yoast\\WP\\SEO\\Presentations\\Archive_Adjacent' => $baseDir . '/src/presentations/archive-adjacent.php',
|
125 |
'WPSEO_Advanced_Settings' => $baseDir . '/deprecated/class-wpseo-advanced-settings.php',
|
126 |
'WPSEO_Author_Sitemap_Provider' => $baseDir . '/inc/sitemaps/class-author-sitemap-provider.php',
|
127 |
'WPSEO_Base_Menu' => $baseDir . '/admin/menu/class-base-menu.php',
|
128 |
+
'WPSEO_Breadcrumbs' => $baseDir . '/deprecated/frontend/breadcrumbs.php',
|
129 |
'WPSEO_Bulk_Description_List_Table' => $baseDir . '/admin/class-bulk-description-editor-list-table.php',
|
130 |
'WPSEO_Bulk_List_Table' => $baseDir . '/admin/class-bulk-editor-list-table.php',
|
131 |
'WPSEO_Bulk_Title_Editor_List_Table' => $baseDir . '/admin/class-bulk-title-editor-list-table.php',
|
210 |
'WPSEO_Features' => $baseDir . '/inc/class-wpseo-features.php',
|
211 |
'WPSEO_File_Size_Exception' => $baseDir . '/admin/exceptions/class-file-size-exception.php',
|
212 |
'WPSEO_File_Size_Service' => $baseDir . '/admin/services/class-file-size.php',
|
213 |
+
'WPSEO_Frontend' => $baseDir . '/deprecated/frontend/frontend.php',
|
214 |
'WPSEO_Frontend_Page_Type' => $baseDir . '/frontend/class-frontend-page-type.php',
|
215 |
'WPSEO_Frontend_Primary_Category' => $baseDir . '/deprecated/frontend/class-primary-category.php',
|
216 |
'WPSEO_GSC' => $baseDir . '/admin/google_search_console/class-gsc.php',
|
621 |
'YoastSEO_Vendor\\Task_Db_Setup' => $baseDir . '/vendor_prefixed/ruckusing/lib/Task/Db/Setup.php',
|
622 |
'YoastSEO_Vendor\\Task_Db_Status' => $baseDir . '/vendor_prefixed/ruckusing/lib/Task/Db/Status.php',
|
623 |
'YoastSEO_Vendor\\Task_Db_Version' => $baseDir . '/vendor_prefixed/ruckusing/lib/Task/Db/Version.php',
|
624 |
+
'Yoast\\WP\\Lib\\Model' => $baseDir . '/lib/model.php',
|
625 |
+
'Yoast\\WP\\Lib\\ORM' => $baseDir . '/lib/orm.php',
|
626 |
+
'Yoast\\WP\\Lib\\Ruckusing_Adapter' => $baseDir . '/lib/ruckusing-adapter.php',
|
627 |
+
'Yoast\\WP\\Lib\\Ruckusing_Framework_Runner' => $baseDir . '/lib/ruckusing-framework-runner.php',
|
628 |
'Yoast\\WP\\SEO\\Actions\\Indexables\\Indexable_Head_Action' => $baseDir . '/src/actions/indexables/indexable-head-action.php',
|
629 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_General_Indexation_Action' => $baseDir . '/src/actions/indexation/indexable-general-indexation-action.php',
|
630 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Indexation_Action' => $baseDir . '/src/actions/indexation/indexable-post-indexation-action.php',
|
711 |
'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => $baseDir . '/src/helpers/twitter/image-helper.php',
|
712 |
'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => $baseDir . '/src/helpers/url-helper.php',
|
713 |
'Yoast\\WP\\SEO\\Helpers\\User_Helper' => $baseDir . '/src/helpers/user-helper.php',
|
|
|
714 |
'Yoast\\WP\\SEO\\Initializers\\Initializer_Interface' => $baseDir . '/src/initializers/initializer-interface.php',
|
715 |
'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => $baseDir . '/src/initializers/migration-runner.php',
|
716 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => $baseDir . '/src/integrations/admin/indexation-integration.php',
|
748 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => $baseDir . '/src/integrations/watchers/primary-term-watcher.php',
|
749 |
'Yoast\\WP\\SEO\\Loadable_Interface' => $baseDir . '/src/loadable-interface.php',
|
750 |
'Yoast\\WP\\SEO\\Loader' => $baseDir . '/src/loader.php',
|
|
|
751 |
'Yoast\\WP\\SEO\\Loggers\\Logger' => $baseDir . '/src/loggers/logger.php',
|
752 |
'Yoast\\WP\\SEO\\Loggers\\Migration_Logger' => $baseDir . '/src/loggers/migration-logger.php',
|
753 |
'Yoast\\WP\\SEO\\Main' => $baseDir . '/src/main.php',
|
759 |
'Yoast\\WP\\SEO\\Models\\Primary_Term' => $baseDir . '/src/models/primary-term.php',
|
760 |
'Yoast\\WP\\SEO\\Models\\SEO_Links' => $baseDir . '/src/models/seo-links.php',
|
761 |
'Yoast\\WP\\SEO\\Models\\SEO_Meta' => $baseDir . '/src/models/seo-meta.php',
|
|
|
|
|
762 |
'Yoast\\WP\\SEO\\Oauth\\Client' => $baseDir . '/src/oauth/client.php',
|
763 |
'Yoast\\WP\\SEO\\Presentations\\Abstract_Presentation' => $baseDir . '/src/presentations/abstract-presentation.php',
|
764 |
'Yoast\\WP\\SEO\\Presentations\\Archive_Adjacent' => $baseDir . '/src/presentations/archive-adjacent.php',
|
vendor/composer/autoload_static.php
CHANGED
@@ -140,7 +140,7 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
|
|
140 |
'WPSEO_Advanced_Settings' => __DIR__ . '/../..' . '/deprecated/class-wpseo-advanced-settings.php',
|
141 |
'WPSEO_Author_Sitemap_Provider' => __DIR__ . '/../..' . '/inc/sitemaps/class-author-sitemap-provider.php',
|
142 |
'WPSEO_Base_Menu' => __DIR__ . '/../..' . '/admin/menu/class-base-menu.php',
|
143 |
-
'WPSEO_Breadcrumbs' => __DIR__ . '/../..' . '/
|
144 |
'WPSEO_Bulk_Description_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-description-editor-list-table.php',
|
145 |
'WPSEO_Bulk_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-editor-list-table.php',
|
146 |
'WPSEO_Bulk_Title_Editor_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-title-editor-list-table.php',
|
@@ -225,7 +225,7 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
|
|
225 |
'WPSEO_Features' => __DIR__ . '/../..' . '/inc/class-wpseo-features.php',
|
226 |
'WPSEO_File_Size_Exception' => __DIR__ . '/../..' . '/admin/exceptions/class-file-size-exception.php',
|
227 |
'WPSEO_File_Size_Service' => __DIR__ . '/../..' . '/admin/services/class-file-size.php',
|
228 |
-
'WPSEO_Frontend' => __DIR__ . '/../..' . '/
|
229 |
'WPSEO_Frontend_Page_Type' => __DIR__ . '/../..' . '/frontend/class-frontend-page-type.php',
|
230 |
'WPSEO_Frontend_Primary_Category' => __DIR__ . '/../..' . '/deprecated/frontend/class-primary-category.php',
|
231 |
'WPSEO_GSC' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc.php',
|
@@ -636,6 +636,10 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
|
|
636 |
'YoastSEO_Vendor\\Task_Db_Setup' => __DIR__ . '/../..' . '/vendor_prefixed/ruckusing/lib/Task/Db/Setup.php',
|
637 |
'YoastSEO_Vendor\\Task_Db_Status' => __DIR__ . '/../..' . '/vendor_prefixed/ruckusing/lib/Task/Db/Status.php',
|
638 |
'YoastSEO_Vendor\\Task_Db_Version' => __DIR__ . '/../..' . '/vendor_prefixed/ruckusing/lib/Task/Db/Version.php',
|
|
|
|
|
|
|
|
|
639 |
'Yoast\\WP\\SEO\\Actions\\Indexables\\Indexable_Head_Action' => __DIR__ . '/../..' . '/src/actions/indexables/indexable-head-action.php',
|
640 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_General_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexation/indexable-general-indexation-action.php',
|
641 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexation/indexable-post-indexation-action.php',
|
@@ -722,7 +726,6 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
|
|
722 |
'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => __DIR__ . '/../..' . '/src/helpers/twitter/image-helper.php',
|
723 |
'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => __DIR__ . '/../..' . '/src/helpers/url-helper.php',
|
724 |
'Yoast\\WP\\SEO\\Helpers\\User_Helper' => __DIR__ . '/../..' . '/src/helpers/user-helper.php',
|
725 |
-
'Yoast\\WP\\SEO\\Initializers\\Database_Setup' => __DIR__ . '/../..' . '/src/initializers/database-setup.php',
|
726 |
'Yoast\\WP\\SEO\\Initializers\\Initializer_Interface' => __DIR__ . '/../..' . '/src/initializers/initializer-interface.php',
|
727 |
'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => __DIR__ . '/../..' . '/src/initializers/migration-runner.php',
|
728 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/indexation-integration.php',
|
@@ -760,7 +763,6 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
|
|
760 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/primary-term-watcher.php',
|
761 |
'Yoast\\WP\\SEO\\Loadable_Interface' => __DIR__ . '/../..' . '/src/loadable-interface.php',
|
762 |
'Yoast\\WP\\SEO\\Loader' => __DIR__ . '/../..' . '/src/loader.php',
|
763 |
-
'Yoast\\WP\\SEO\\Loggers\\Database_Logger' => __DIR__ . '/../..' . '/src/loggers/database-logger.php',
|
764 |
'Yoast\\WP\\SEO\\Loggers\\Logger' => __DIR__ . '/../..' . '/src/loggers/logger.php',
|
765 |
'Yoast\\WP\\SEO\\Loggers\\Migration_Logger' => __DIR__ . '/../..' . '/src/loggers/migration-logger.php',
|
766 |
'Yoast\\WP\\SEO\\Main' => __DIR__ . '/../..' . '/src/main.php',
|
@@ -772,8 +774,6 @@ class ComposerStaticInit424d5d6160c52f59ba476750c190098f
|
|
772 |
'Yoast\\WP\\SEO\\Models\\Primary_Term' => __DIR__ . '/../..' . '/src/models/primary-term.php',
|
773 |
'Yoast\\WP\\SEO\\Models\\SEO_Links' => __DIR__ . '/../..' . '/src/models/seo-links.php',
|
774 |
'Yoast\\WP\\SEO\\Models\\SEO_Meta' => __DIR__ . '/../..' . '/src/models/seo-meta.php',
|
775 |
-
'Yoast\\WP\\SEO\\ORM\\ORMWrapper' => __DIR__ . '/../..' . '/src/orm/yoast-orm-wrapper.php',
|
776 |
-
'Yoast\\WP\\SEO\\ORM\\Yoast_Model' => __DIR__ . '/../..' . '/src/orm/yoast-model.php',
|
777 |
'Yoast\\WP\\SEO\\Oauth\\Client' => __DIR__ . '/../..' . '/src/oauth/client.php',
|
778 |
'Yoast\\WP\\SEO\\Presentations\\Abstract_Presentation' => __DIR__ . '/../..' . '/src/presentations/abstract-presentation.php',
|
779 |
'Yoast\\WP\\SEO\\Presentations\\Archive_Adjacent' => __DIR__ . '/../..' . '/src/presentations/archive-adjacent.php',
|
140 |
'WPSEO_Advanced_Settings' => __DIR__ . '/../..' . '/deprecated/class-wpseo-advanced-settings.php',
|
141 |
'WPSEO_Author_Sitemap_Provider' => __DIR__ . '/../..' . '/inc/sitemaps/class-author-sitemap-provider.php',
|
142 |
'WPSEO_Base_Menu' => __DIR__ . '/../..' . '/admin/menu/class-base-menu.php',
|
143 |
+
'WPSEO_Breadcrumbs' => __DIR__ . '/../..' . '/deprecated/frontend/breadcrumbs.php',
|
144 |
'WPSEO_Bulk_Description_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-description-editor-list-table.php',
|
145 |
'WPSEO_Bulk_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-editor-list-table.php',
|
146 |
'WPSEO_Bulk_Title_Editor_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-title-editor-list-table.php',
|
225 |
'WPSEO_Features' => __DIR__ . '/../..' . '/inc/class-wpseo-features.php',
|
226 |
'WPSEO_File_Size_Exception' => __DIR__ . '/../..' . '/admin/exceptions/class-file-size-exception.php',
|
227 |
'WPSEO_File_Size_Service' => __DIR__ . '/../..' . '/admin/services/class-file-size.php',
|
228 |
+
'WPSEO_Frontend' => __DIR__ . '/../..' . '/deprecated/frontend/frontend.php',
|
229 |
'WPSEO_Frontend_Page_Type' => __DIR__ . '/../..' . '/frontend/class-frontend-page-type.php',
|
230 |
'WPSEO_Frontend_Primary_Category' => __DIR__ . '/../..' . '/deprecated/frontend/class-primary-category.php',
|
231 |
'WPSEO_GSC' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc.php',
|
636 |
'YoastSEO_Vendor\\Task_Db_Setup' => __DIR__ . '/../..' . '/vendor_prefixed/ruckusing/lib/Task/Db/Setup.php',
|
637 |
'YoastSEO_Vendor\\Task_Db_Status' => __DIR__ . '/../..' . '/vendor_prefixed/ruckusing/lib/Task/Db/Status.php',
|
638 |
'YoastSEO_Vendor\\Task_Db_Version' => __DIR__ . '/../..' . '/vendor_prefixed/ruckusing/lib/Task/Db/Version.php',
|
639 |
+
'Yoast\\WP\\Lib\\Model' => __DIR__ . '/../..' . '/lib/model.php',
|
640 |
+
'Yoast\\WP\\Lib\\ORM' => __DIR__ . '/../..' . '/lib/orm.php',
|
641 |
+
'Yoast\\WP\\Lib\\Ruckusing_Adapter' => __DIR__ . '/../..' . '/lib/ruckusing-adapter.php',
|
642 |
+
'Yoast\\WP\\Lib\\Ruckusing_Framework_Runner' => __DIR__ . '/../..' . '/lib/ruckusing-framework-runner.php',
|
643 |
'Yoast\\WP\\SEO\\Actions\\Indexables\\Indexable_Head_Action' => __DIR__ . '/../..' . '/src/actions/indexables/indexable-head-action.php',
|
644 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_General_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexation/indexable-general-indexation-action.php',
|
645 |
'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexation/indexable-post-indexation-action.php',
|
726 |
'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => __DIR__ . '/../..' . '/src/helpers/twitter/image-helper.php',
|
727 |
'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => __DIR__ . '/../..' . '/src/helpers/url-helper.php',
|
728 |
'Yoast\\WP\\SEO\\Helpers\\User_Helper' => __DIR__ . '/../..' . '/src/helpers/user-helper.php',
|
|
|
729 |
'Yoast\\WP\\SEO\\Initializers\\Initializer_Interface' => __DIR__ . '/../..' . '/src/initializers/initializer-interface.php',
|
730 |
'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => __DIR__ . '/../..' . '/src/initializers/migration-runner.php',
|
731 |
'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/indexation-integration.php',
|
763 |
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/primary-term-watcher.php',
|
764 |
'Yoast\\WP\\SEO\\Loadable_Interface' => __DIR__ . '/../..' . '/src/loadable-interface.php',
|
765 |
'Yoast\\WP\\SEO\\Loader' => __DIR__ . '/../..' . '/src/loader.php',
|
|
|
766 |
'Yoast\\WP\\SEO\\Loggers\\Logger' => __DIR__ . '/../..' . '/src/loggers/logger.php',
|
767 |
'Yoast\\WP\\SEO\\Loggers\\Migration_Logger' => __DIR__ . '/../..' . '/src/loggers/migration-logger.php',
|
768 |
'Yoast\\WP\\SEO\\Main' => __DIR__ . '/../..' . '/src/main.php',
|
774 |
'Yoast\\WP\\SEO\\Models\\Primary_Term' => __DIR__ . '/../..' . '/src/models/primary-term.php',
|
775 |
'Yoast\\WP\\SEO\\Models\\SEO_Links' => __DIR__ . '/../..' . '/src/models/seo-links.php',
|
776 |
'Yoast\\WP\\SEO\\Models\\SEO_Meta' => __DIR__ . '/../..' . '/src/models/seo-meta.php',
|
|
|
|
|
777 |
'Yoast\\WP\\SEO\\Oauth\\Client' => __DIR__ . '/../..' . '/src/oauth/client.php',
|
778 |
'Yoast\\WP\\SEO\\Presentations\\Abstract_Presentation' => __DIR__ . '/../..' . '/src/presentations/abstract-presentation.php',
|
779 |
'Yoast\\WP\\SEO\\Presentations\\Archive_Adjacent' => __DIR__ . '/../..' . '/src/presentations/archive-adjacent.php',
|
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' ) ) {
|
@@ -26,11 +26,6 @@ if ( ! defined( 'WPSEO_BASENAME' ) ) {
|
|
26 |
define( 'WPSEO_BASENAME', plugin_basename( WPSEO_FILE ) );
|
27 |
}
|
28 |
|
29 |
-
if ( ! extension_loaded( 'pdo_mysql' ) ) {
|
30 |
-
require_once WPSEO_PATH . 'polyfills/pdo/pdo-mysqli-polyfill.php';
|
31 |
-
require_once WPSEO_PATH . 'polyfills/pdo/pdo-mysqli-statement-polyfill.php';
|
32 |
-
}
|
33 |
-
|
34 |
/*
|
35 |
* {@internal The prefix constants are used to build prefixed versions of dependencies.
|
36 |
* These should not be changed on run-time, thus missing the ! defined() check.}}
|
15 |
* {@internal Nobody should be able to overrule the real version number as this can cause
|
16 |
* serious issues with the options, so no if ( ! defined() ).}}
|
17 |
*/
|
18 |
+
define( 'WPSEO_VERSION', '14.0.2' );
|
19 |
|
20 |
|
21 |
if ( ! defined( 'WPSEO_PATH' ) ) {
|
26 |
define( 'WPSEO_BASENAME', plugin_basename( WPSEO_FILE ) );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
29 |
/*
|
30 |
* {@internal The prefix constants are used to build prefixed versions of dependencies.
|
31 |
* These should not be changed on run-time, thus missing the ! defined() check.}}
|
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.2
|
12 |
* Plugin URI: https://yoa.st/1uj
|
13 |
* Description: The first true all-in-one SEO solution for WordPress, including on-page content analysis, XML sitemaps and much more.
|
14 |
* Author: Team Yoast
|