PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
← All changes | src/builders/indexable-term-builder.php +64 -45 18.228.5 View file →
@@ -1,15 +1,14 @@
1 1 <?php
2 2
3 3 namespace Yoast\WP\SEO\Builders;
4 4
5 -use wpdb;
6 5 use Yoast\WP\SEO\Exceptions\Indexable\Invalid_Term_Exception;
6 +use Yoast\WP\SEO\Exceptions\Indexable\Term_Not_Built_Exception;
7 7 use Yoast\WP\SEO\Exceptions\Indexable\Term_Not_Found_Exception;
8 8 use Yoast\WP\SEO\Helpers\Post_Helper;
9 9 use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
10 10 use Yoast\WP\SEO\Models\Indexable;
11 -use Yoast\WP\SEO\Repositories\Indexable_Repository;
12 11 use Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions;
13 12
14 13 /**
15 14 * Term Builder for the indexables.
@@ -41,32 +40,22 @@
41 40 */
42 41 protected $post_helper;
43 42
44 43 /**
45 - * The WPDB instance.
46 - *
47 - * @var wpdb
48 - */
49 - protected $wpdb;
50 -
51 - /**
52 44 * Indexable_Term_Builder constructor.
53 45 *
54 46 * @param Taxonomy_Helper $taxonomy_helper The taxonomy helper.
55 47 * @param Indexable_Builder_Versions $versions The latest version of each Indexable Builder.
56 48 * @param Post_Helper $post_helper The post helper.
57 - * @param wpdb $wpdb The WPDB instance.
58 49 */
59 50 public function __construct(
60 51 Taxonomy_Helper $taxonomy_helper,
61 52 Indexable_Builder_Versions $versions,
62 - Post_Helper $post_helper,
63 - wpdb $wpdb
53 + Post_Helper $post_helper
64 54 ) {
65 55 $this->taxonomy_helper = $taxonomy_helper;
66 56 $this->version = $versions->get_latest_version_for_type( 'term' );
67 57 $this->post_helper = $post_helper;
68 - $this->wpdb = $wpdb;
69 58 }
70 59
71 60 /**
72 61 * Formats the data.
@@ -75,9 +64,10 @@
75 64 * @param Indexable $indexable The indexable to format.
76 65 *
77 66 * @return bool|Indexable The extended indexable. False when unable to build.
78 67 *
79 - * @throws Invalid_Term_Exception When the term is invalid.
68 + * @throws Invalid_Term_Exception When the term is invalid.
69 + * @throws Term_Not_Built_Exception When the term is not viewable.
80 70 * @throws Term_Not_Found_Exception When the term is not found.
81 71 */
82 72 public function build( $term_id, $indexable ) {
83 73 $term = \get_term( $term_id );
@@ -89,8 +79,13 @@
89 79 if ( \is_wp_error( $term ) ) {
90 80 throw new Invalid_Term_Exception( $term->get_error_message() );
91 81 }
92 82
83 + $indexable_taxonomies = $this->taxonomy_helper->get_indexable_taxonomies();
84 + if ( ! \in_array( $term->taxonomy, $indexable_taxonomies, true ) ) {
85 + throw Term_Not_Built_Exception::because_not_indexable( $term_id );
86 + }
87 +
93 88 $term_link = \get_term_link( $term, $term->taxonomy );
94 89
95 90 if ( \is_wp_error( $term_link ) ) {
96 91 throw new Invalid_Term_Exception( $term_link->get_error_message() );
@@ -105,9 +100,9 @@
105 100 $indexable->blog_id = \get_current_blog_id();
106 101
107 102 $indexable->primary_focus_keyword_score = $this->get_keyword_score(
108 103 $this->get_meta_value( 'wpseo_focuskw', $term_meta ),
109 - $this->get_meta_value( 'wpseo_linkdex', $term_meta )
104 + $this->get_meta_value( 'wpseo_linkdex', $term_meta ),
110 105 );
111 106
112 107 $indexable->is_robots_noindex = $this->get_noindex_value( $this->get_meta_value( 'wpseo_noindex', $term_meta ) );
113 108 $indexable->is_public = ( $indexable->is_robots_noindex === null ) ? null : ! $indexable->is_robots_noindex;
@@ -182,22 +177,23 @@
182 177 * @return array Lookup table for the indexable fields.
183 178 */
184 179 protected function get_indexable_lookup() {
185 180 return [
186 - 'wpseo_canonical' => 'canonical',
187 - 'wpseo_focuskw' => 'primary_focus_keyword',
188 - 'wpseo_title' => 'title',
189 - 'wpseo_desc' => 'description',
190 - 'wpseo_content_score' => 'readability_score',
191 - 'wpseo_bctitle' => 'breadcrumb_title',
192 - 'wpseo_opengraph-title' => 'open_graph_title',
193 - 'wpseo_opengraph-description' => 'open_graph_description',
194 - 'wpseo_opengraph-image' => 'open_graph_image',
195 - 'wpseo_opengraph-image-id' => 'open_graph_image_id',
196 - 'wpseo_twitter-title' => 'twitter_title',
197 - 'wpseo_twitter-description' => 'twitter_description',
198 - 'wpseo_twitter-image' => 'twitter_image',
199 - 'wpseo_twitter-image-id' => 'twitter_image_id',
181 + 'wpseo_canonical' => 'canonical',
182 + 'wpseo_focuskw' => 'primary_focus_keyword',
183 + 'wpseo_title' => 'title',
184 + 'wpseo_desc' => 'description',
185 + 'wpseo_content_score' => 'readability_score',
186 + 'wpseo_inclusive_language_score' => 'inclusive_language_score',
187 + 'wpseo_bctitle' => 'breadcrumb_title',
188 + 'wpseo_opengraph-title' => 'open_graph_title',
189 + 'wpseo_opengraph-description' => 'open_graph_description',
190 + 'wpseo_opengraph-image' => 'open_graph_image',
191 + 'wpseo_opengraph-image-id' => 'open_graph_image_id',
192 + 'wpseo_twitter-title' => 'twitter_title',
193 + 'wpseo_twitter-description' => 'twitter_description',
194 + 'wpseo_twitter-image' => 'twitter_image',
195 + 'wpseo_twitter-image-id' => 'twitter_image_id',
200 196 ];
201 197 }
202 198
203 199 /**
@@ -248,25 +244,48 @@
248 244 *
249 245 * @return object An object with last_modified and published_at timestamps.
250 246 */
251 247 protected function get_object_timestamps( $term_id, $taxonomy ) {
248 + global $wpdb;
252 249 $post_statuses = $this->post_helper->get_public_post_statuses();
253 250
254 - $sql = "
255 - SELECT MAX(p.post_modified_gmt) AS last_modified, MIN(p.post_date_gmt) AS published_at
256 - FROM {$this->wpdb->posts} AS p
257 - INNER JOIN {$this->wpdb->term_relationships} AS term_rel
258 - ON term_rel.object_id = p.ID
259 - INNER JOIN {$this->wpdb->term_taxonomy} AS term_tax
260 - ON term_tax.term_taxonomy_id = term_rel.term_taxonomy_id
261 - AND term_tax.taxonomy = %s
262 - AND term_tax.term_id = %d
263 - WHERE p.post_status IN (" . implode( ', ', array_fill( 0, count( $post_statuses ), '%s' ) ) . ")
264 - AND p.post_password = ''
265 - ";
251 + $replacements = [];
252 + $replacements[] = 'post_modified_gmt';
253 + $replacements[] = 'post_date_gmt';
254 + $replacements[] = $wpdb->posts;
255 + $replacements[] = $wpdb->term_relationships;
256 + $replacements[] = 'object_id';
257 + $replacements[] = 'ID';
258 + $replacements[] = $wpdb->term_taxonomy;
259 + $replacements[] = 'term_taxonomy_id';
260 + $replacements[] = 'term_taxonomy_id';
261 + $replacements[] = 'taxonomy';
262 + $replacements[] = $taxonomy;
263 + $replacements[] = 'term_id';
264 + $replacements[] = $term_id;
265 + $replacements[] = 'post_status';
266 + $replacements = \array_merge( $replacements, $post_statuses );
267 + $replacements[] = 'post_password';
266 268
267 - $replacements = \array_merge( [ $taxonomy, $term_id ], $post_statuses );
268 -
269 - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- We are using wpdb prepare.
270 - return $this->wpdb->get_row( $this->wpdb->prepare( $sql, $replacements ) );
269 + //phpcs:disable WordPress.DB.PreparedSQLPlaceholders -- %i placeholder is still not recognized.
270 + //phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: Most performant way.
271 + //phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: No relevant caches.
272 + return $wpdb->get_row(
273 + $wpdb->prepare(
274 + '
275 + SELECT MAX(p.%i) AS last_modified, MIN(p.%i) AS published_at
276 + FROM %i AS p
277 + INNER JOIN %i AS term_rel
278 + ON term_rel.%i = p.%i
279 + INNER JOIN %i AS term_tax
280 + ON term_tax.%i = term_rel.%i
281 + AND term_tax.%i = %s
282 + AND term_tax.%i = %d
283 + WHERE p.%i IN (' . \implode( ', ', \array_fill( 0, \count( $post_statuses ), '%s' ) ) . ")
284 + AND p.%i = ''
285 + ",
286 + $replacements,
287 + ),
288 + );
289 + //phpcs:enable
271 290 }
272 291 }