Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add placeholders and integration tests to indexables builders queries #20834

Merged
merged 34 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ef1c669
Introduce %i placeholder
pls78 Nov 9, 2023
cf0574e
Add integration test
pls78 Nov 9, 2023
74a4eee
Fix cs
pls78 Nov 9, 2023
765fd27
Use common array notation
pls78 Nov 13, 2023
5c7b47d
Introduce %i placeholder
pls78 Nov 13, 2023
3dcc34a
Add integration test
pls78 Nov 14, 2023
4afe1b2
Use better variable names
pls78 Nov 14, 2023
981fe78
Introduce %i placeholder
pls78 Nov 14, 2023
fe10a04
Remove unused import
pls78 Nov 14, 2023
07d97b9
Use factories for objects creation
pls78 Nov 14, 2023
1396545
Fix trailing comma
pls78 Nov 15, 2023
f6b1700
Add integration test for the happy path only
pls78 Nov 15, 2023
96fab16
Fix post_status
pls78 Nov 15, 2023
c4e1f8e
Fix imports order
pls78 Nov 15, 2023
86be2b3
Fix cs
pls78 Nov 15, 2023
2b9196c
Introduce %i placeholder
pls78 Nov 16, 2023
05fd9c8
WIP: Add integration test
pls78 Nov 16, 2023
6b6a0a9
Added another integration test
pls78 Nov 17, 2023
27b5d36
Fix unit test
pls78 Nov 20, 2023
078c655
Fix cs
pls78 Nov 20, 2023
8dc0d16
Fix cs
pls78 Nov 20, 2023
fc877cd
Update tests to the new standards
pls78 Nov 23, 2023
c3b0a21
Use placeholder for field names too.
pls78 Nov 23, 2023
8c8ced0
Extended integration test
pls78 Nov 23, 2023
e24d0aa
Fix cs
pls78 Nov 23, 2023
ca84f92
Restructured and expanded integrationt test
pls78 Nov 24, 2023
99a5663
Removed mocked classes
pls78 Nov 24, 2023
450034f
Refactor and expand tests
pls78 Nov 24, 2023
2313691
Final polishing
pls78 Nov 26, 2023
7cb00d0
Try to fix github fail
pls78 Nov 26, 2023
6bda175
Remove wrong test
pls78 Nov 26, 2023
fcd13d7
Fix cs
pls78 Nov 26, 2023
09c8854
Use correct helpers surface
pls78 Nov 27, 2023
8fc0a13
Add case to integration test
pls78 Nov 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 28 additions & 24 deletions src/builders/indexable-author-builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Yoast\WP\SEO\Builders;

use wpdb;
use Yoast\WP\SEO\Exceptions\Indexable\Author_Not_Built_Exception;
use Yoast\WP\SEO\Helpers\Author_Archive_Helper;
use Yoast\WP\SEO\Helpers\Options_Helper;
Expand Down Expand Up @@ -47,34 +46,24 @@ class Indexable_Author_Builder {
*/
protected $post_helper;

/**
* The WPDB instance.
*
* @var wpdb
*/
protected $wpdb;

/**
* Indexable_Author_Builder constructor.
*
* @param Author_Archive_Helper $author_archive The author archive helper.
* @param Indexable_Builder_Versions $versions The Indexable version manager.
* @param Options_Helper $options_helper The options helper.
* @param Post_Helper $post_helper The post helper.
* @param wpdb $wpdb The WPDB instance.
*/
public function __construct(
Author_Archive_Helper $author_archive,
Indexable_Builder_Versions $versions,
Options_Helper $options_helper,
Post_Helper $post_helper,
wpdb $wpdb
Post_Helper $post_helper
) {
$this->author_archive = $author_archive;
$this->version = $versions->get_latest_version_for_type( 'user' );
$this->options_helper = $options_helper;
$this->post_helper = $post_helper;
$this->wpdb = $wpdb;
}

/**
Expand Down Expand Up @@ -194,20 +183,35 @@ protected function find_alternative_image( Indexable $indexable ) {
* @return object An object with last_modified and published_at timestamps.
*/
protected function get_object_timestamps( $author_id ) {
global $wpdb;
$post_statuses = $this->post_helper->get_public_post_statuses();

$sql = "
SELECT MAX(p.post_modified_gmt) AS last_modified, MIN(p.post_date_gmt) AS published_at
FROM {$this->wpdb->posts} AS p
WHERE p.post_status IN (" . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.post_password = ''
AND p.post_author = %d
";

$replacements = \array_merge( $post_statuses, [ $author_id ] );

// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- We are using wpdb prepare.
return $this->wpdb->get_row( $this->wpdb->prepare( $sql, $replacements ) );
$replacements = [];
$replacements[] = 'post_modified_gmt';
$replacements[] = 'post_date_gmt';
$replacements[] = $wpdb->posts;
$replacements[] = 'post_status';
$replacements = \array_merge( $replacements, $post_statuses );
$replacements[] = 'post_password';
$replacements[] = 'post_author';
$replacements[] = $author_id;

//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: Most performant way.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
return $wpdb->get_row(
$wpdb->prepare(
'
SELECT MAX(p.%i) AS last_modified, MIN(p.%i) AS published_at
FROM %i AS p
WHERE p.%i IN (' . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.%i = ''
AND p.%i = %d
",
$replacements
)
);
//phpcs:enable
}

/**
Expand Down
48 changes: 27 additions & 21 deletions src/builders/indexable-home-page-builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,34 +46,24 @@ class Indexable_Home_Page_Builder {
*/
protected $post_helper;

/**
* The WPDB instance.
*
* @var wpdb
*/
protected $wpdb;

/**
* Indexable_Home_Page_Builder constructor.
*
* @param Options_Helper $options The options helper.
* @param Url_Helper $url_helper The url helper.
* @param Indexable_Builder_Versions $versions Knows the latest version of each Indexable type.
* @param Post_Helper $post_helper The post helper.
* @param wpdb $wpdb The WPDB instance.
*/
public function __construct(
Options_Helper $options,
Url_Helper $url_helper,
Indexable_Builder_Versions $versions,
Post_Helper $post_helper,
wpdb $wpdb
Post_Helper $post_helper
) {
$this->options = $options;
$this->url_helper = $url_helper;
$this->version = $versions->get_latest_version_for_type( 'home-page' );
$this->post_helper = $post_helper;
$this->wpdb = $wpdb;
}

/**
Expand Down Expand Up @@ -127,17 +117,33 @@ public function build( $indexable ) {
* @return object An object with last_modified and published_at timestamps.
*/
protected function get_object_timestamps() {
global $wpdb;
$post_statuses = $this->post_helper->get_public_post_statuses();

$sql = "
SELECT MAX(p.post_modified_gmt) AS last_modified, MIN(p.post_date_gmt) AS published_at
FROM {$this->wpdb->posts} AS p
WHERE p.post_status IN (" . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.post_password = ''
AND p.post_type = 'post'
";

// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- We are using wpdb prepare.
return $this->wpdb->get_row( $this->wpdb->prepare( $sql, $post_statuses ) );
$replacements = [];
$replacements[] = 'post_modified_gmt';
$replacements[] = 'post_date_gmt';
$replacements[] = $wpdb->posts;
$replacements[] = 'post_status';
$replacements = \array_merge( $replacements, $post_statuses );
$replacements[] = 'post_password';
$replacements[] = 'post_type';

//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: Most performant way.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
return $wpdb->get_row(
$wpdb->prepare(
'
SELECT MAX(p.%i) AS last_modified, MIN(p.%i) AS published_at
FROM %i AS p
WHERE p.%i IN (' . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.%i = ''
AND p.%i = 'post'
",
$replacements
)
);
//phpcs:enable
}
}
52 changes: 28 additions & 24 deletions src/builders/indexable-post-type-archive-builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Yoast\WP\SEO\Builders;

use wpdb;
use Yoast\WP\SEO\Exceptions\Indexable\Post_Type_Not_Built_Exception;
use Yoast\WP\SEO\Helpers\Options_Helper;
use Yoast\WP\SEO\Helpers\Post_Helper;
Expand Down Expand Up @@ -45,34 +44,24 @@ class Indexable_Post_Type_Archive_Builder {
*/
protected $post_type_helper;

/**
* The WPDB instance.
*
* @var wpdb
*/
protected $wpdb;

/**
* Indexable_Post_Type_Archive_Builder constructor.
*
* @param Options_Helper $options The options helper.
* @param Indexable_Builder_Versions $versions The latest version of each Indexable builder.
* @param Post_Helper $post_helper The post helper.
* @param Post_Type_Helper $post_type_helper The post type helper.
* @param wpdb $wpdb The WPDB instance.
*/
public function __construct(
Options_Helper $options,
Indexable_Builder_Versions $versions,
Post_Helper $post_helper,
Post_Type_Helper $post_type_helper,
wpdb $wpdb
Post_Type_Helper $post_type_helper
) {
$this->options = $options;
$this->version = $versions->get_latest_version_for_type( 'post-type-archive' );
$this->post_helper = $post_helper;
$this->post_type_helper = $post_type_helper;
$this->wpdb = $wpdb;
}

/**
Expand Down Expand Up @@ -146,19 +135,34 @@ private function get_breadcrumb_title( $post_type ) {
* @return object An object with last_modified and published_at timestamps.
*/
protected function get_object_timestamps( $post_type ) {
global $wpdb;
$post_statuses = $this->post_helper->get_public_post_statuses();

$sql = "
SELECT MAX(p.post_modified_gmt) AS last_modified, MIN(p.post_date_gmt) AS published_at
FROM {$this->wpdb->posts} AS p
WHERE p.post_status IN (" . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.post_password = ''
AND p.post_type = %s
";

$replacements = \array_merge( $post_statuses, [ $post_type ] );

// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- We are using wpdb prepare.
return $this->wpdb->get_row( $this->wpdb->prepare( $sql, $replacements ) );
$replacements = [];
$replacements[] = 'post_modified_gmt';
$replacements[] = 'post_date_gmt';
$replacements[] = $wpdb->posts;
$replacements[] = 'post_status';
$replacements = \array_merge( $replacements, $post_statuses );
$replacements[] = 'post_password';
$replacements[] = 'post_type';
$replacements[] = $post_type;

//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to use a direct query here.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
return $wpdb->get_row(
$wpdb->prepare(
'
SELECT MAX(p.%i) AS last_modified, MIN(p.%i) AS published_at
FROM %i AS p
WHERE p.%i IN (' . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.%i = ''
AND p.%i = %s
",
$replacements
)
);
//phpcs:enable
}
}
70 changes: 41 additions & 29 deletions src/builders/indexable-term-builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Yoast\WP\SEO\Builders;

use wpdb;
use Yoast\WP\SEO\Exceptions\Indexable\Invalid_Term_Exception;
use Yoast\WP\SEO\Exceptions\Indexable\Term_Not_Built_Exception;
use Yoast\WP\SEO\Exceptions\Indexable\Term_Not_Found_Exception;
Expand Down Expand Up @@ -41,31 +40,21 @@ class Indexable_Term_Builder {
*/
protected $post_helper;

/**
* The WPDB instance.
*
* @var wpdb
*/
protected $wpdb;

/**
* Indexable_Term_Builder constructor.
*
* @param Taxonomy_Helper $taxonomy_helper The taxonomy helper.
* @param Indexable_Builder_Versions $versions The latest version of each Indexable Builder.
* @param Post_Helper $post_helper The post helper.
* @param wpdb $wpdb The WPDB instance.
*/
public function __construct(
Taxonomy_Helper $taxonomy_helper,
Indexable_Builder_Versions $versions,
Post_Helper $post_helper,
wpdb $wpdb
Post_Helper $post_helper
) {
$this->taxonomy_helper = $taxonomy_helper;
$this->version = $versions->get_latest_version_for_type( 'term' );
$this->post_helper = $post_helper;
$this->wpdb = $wpdb;
}

/**
Expand Down Expand Up @@ -256,24 +245,47 @@ protected function find_alternative_image( Indexable $indexable ) {
* @return object An object with last_modified and published_at timestamps.
*/
protected function get_object_timestamps( $term_id, $taxonomy ) {
global $wpdb;
$post_statuses = $this->post_helper->get_public_post_statuses();

$sql = "
SELECT MAX(p.post_modified_gmt) AS last_modified, MIN(p.post_date_gmt) AS published_at
FROM {$this->wpdb->posts} AS p
INNER JOIN {$this->wpdb->term_relationships} AS term_rel
ON term_rel.object_id = p.ID
INNER JOIN {$this->wpdb->term_taxonomy} AS term_tax
ON term_tax.term_taxonomy_id = term_rel.term_taxonomy_id
AND term_tax.taxonomy = %s
AND term_tax.term_id = %d
WHERE p.post_status IN (" . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.post_password = ''
";

$replacements = \array_merge( [ $taxonomy, $term_id ], $post_statuses );

// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- We are using wpdb prepare.
return $this->wpdb->get_row( $this->wpdb->prepare( $sql, $replacements ) );
$replacements = [];
$replacements[] = 'post_modified_gmt';
$replacements[] = 'post_date_gmt';
$replacements[] = $wpdb->posts;
$replacements[] = $wpdb->term_relationships;
$replacements[] = 'object_id';
$replacements[] = 'ID';
$replacements[] = $wpdb->term_taxonomy;
$replacements[] = 'term_taxonomy_id';
$replacements[] = 'term_taxonomy_id';
$replacements[] = 'taxonomy';
$replacements[] = $taxonomy;
$replacements[] = 'term_id';
$replacements[] = $term_id;
$replacements[] = 'post_status';
$replacements = \array_merge( $replacements, $post_statuses );
$replacements[] = 'post_password';

//phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: Most performant way.
//phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
return $wpdb->get_row(
$wpdb->prepare(
'
SELECT MAX(p.%i) AS last_modified, MIN(p.%i) AS published_at
FROM %i AS p
INNER JOIN %i AS term_rel
ON term_rel.%i = p.%i
INNER JOIN %i AS term_tax
ON term_tax.%i = term_rel.%i
AND term_tax.%i = %s
AND term_tax.%i = %d
WHERE p.%i IN (' . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
AND p.%i = ''
",
$replacements
)
);
//phpcs:enable
}
}
Loading