PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.9
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.9
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
wordpress-seo / src / actions / indexing / indexable-term-indexation-action.php

indexable-term-indexation-action.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.9, at src/actions/indexing/indexable-term-indexation-action.php

198 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yoast\WP\SEO\Actions\Indexing;
4
5 use wpdb;
6 use Yoast\WP\Lib\Model;
7 use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
8 use Yoast\WP\SEO\Models\Indexable;
9 use Yoast\WP\SEO\Repositories\Indexable_Repository;
10 use Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions;
11
12 /**
13 * Reindexing action for term indexables.
14 */
15 class Indexable_Term_Indexation_Action extends Abstract_Indexing_Action {
16
17 /**
18 * The transient cache key.
19 */
20 public const UNINDEXED_COUNT_TRANSIENT = 'wpseo_total_unindexed_terms';
21
22 /**
23 * The transient cache key for limited counts.
24 *
25 * @var string
26 */
27 public const UNINDEXED_LIMITED_COUNT_TRANSIENT = self::UNINDEXED_COUNT_TRANSIENT . '_limited';
28
29 /**
30 * The post type helper.
31 *
32 * @var Taxonomy_Helper
33 */
34 protected $taxonomy;
35
36 /**
37 * The indexable repository.
38 *
39 * @var Indexable_Repository
40 */
41 protected $repository;
42
43 /**
44 * The WordPress database instance.
45 *
46 * @var wpdb
47 */
48 protected $wpdb;
49
50 /**
51 * The latest version of the Indexable term builder
52 *
53 * @var int
54 */
55 protected $version;
56
57 /**
58 * Indexable_Term_Indexation_Action constructor
59 *
60 * @param Taxonomy_Helper $taxonomy The taxonomy helper.
61 * @param Indexable_Repository $repository The indexable repository.
62 * @param wpdb $wpdb The WordPress database instance.
63 * @param Indexable_Builder_Versions $builder_versions The latest versions of all indexable builders.
64 */
65 public function __construct(
66 Taxonomy_Helper $taxonomy,
67 Indexable_Repository $repository,
68 wpdb $wpdb,
69 Indexable_Builder_Versions $builder_versions
70 ) {
71 $this->taxonomy = $taxonomy;
72 $this->repository = $repository;
73 $this->wpdb = $wpdb;
74 $this->version = $builder_versions->get_latest_version_for_type( 'term' );
75 }
76
77 /**
78 * Creates indexables for unindexed terms.
79 *
80 * @return Indexable[] The created indexables.
81 */
82 public function index() {
83 $query = $this->get_select_query( $this->get_limit() );
84
85 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Function get_select_query returns a prepared query.
86 $term_ids = ( $query === '' ) ? [] : $this->wpdb->get_col( $query );
87
88 $indexables = $this->repository->find_by_multiple_ids_and_type(
89 \array_map( 'intval', $term_ids ),
90 'term',
91 );
92
93 if ( \count( $indexables ) > 0 ) {
94 \delete_transient( static::UNINDEXED_COUNT_TRANSIENT );
95 \delete_transient( static::UNINDEXED_LIMITED_COUNT_TRANSIENT );
96 }
97
98 return $indexables;
99 }
100
101 /**
102 * Returns the number of terms that will be indexed in a single indexing pass.
103 *
104 * @return int The limit.
105 */
106 public function get_limit() {
107 /**
108 * Filter 'wpseo_term_indexation_limit' - Allow filtering the number of terms indexed during each indexing pass.
109 *
110 * @param int $limit The maximum number of terms indexed.
111 */
112 $limit = \apply_filters( 'wpseo_term_indexation_limit', 25 );
113
114 if ( ! \is_int( $limit ) || $limit < 1 ) {
115 $limit = 25;
116 }
117
118 return $limit;
119 }
120
121 /**
122 * Builds a query for counting the number of unindexed terms.
123 *
124 * @return string The prepared query string.
125 */
126 protected function get_count_query() {
127 $indexable_table = Model::get_table_name( 'Indexable' );
128 $taxonomy_table = $this->wpdb->term_taxonomy;
129 $public_taxonomies = $this->taxonomy->get_indexable_taxonomies();
130
131 if ( empty( $public_taxonomies ) ) {
132 return '';
133 }
134
135 $taxonomies_placeholders = \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) );
136
137 $replacements = [ $this->version ];
138 \array_push( $replacements, ...$public_taxonomies );
139
140 // Warning: If this query is changed, makes sure to update the query in get_count_query as well.
141 return $this->wpdb->prepare(
142 "
143 SELECT COUNT(term_id)
144 FROM {$taxonomy_table} AS T
145 LEFT JOIN $indexable_table AS I
146 ON T.term_id = I.object_id
147 AND I.object_type = 'term'
148 AND I.version = %d
149 WHERE I.object_id IS NULL
150 AND taxonomy IN ($taxonomies_placeholders)",
151 $replacements,
152 );
153 }
154
155 /**
156 * Builds a query for selecting the ID's of unindexed terms.
157 *
158 * @param bool $limit The maximum number of term IDs to return.
159 *
160 * @return string The prepared query string.
161 */
162 protected function get_select_query( $limit = false ) {
163 $indexable_table = Model::get_table_name( 'Indexable' );
164 $taxonomy_table = $this->wpdb->term_taxonomy;
165 $public_taxonomies = $this->taxonomy->get_indexable_taxonomies();
166
167 if ( empty( $public_taxonomies ) ) {
168 return '';
169 }
170
171 $placeholders = \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) );
172
173 $replacements = [ $this->version ];
174 \array_push( $replacements, ...$public_taxonomies );
175
176 $limit_query = '';
177 if ( $limit ) {
178 $limit_query = 'LIMIT %d';
179 $replacements[] = $limit;
180 }
181
182 // Warning: If this query is changed, makes sure to update the query in get_count_query as well.
183 return $this->wpdb->prepare(
184 "
185 SELECT term_id
186 FROM {$taxonomy_table} AS T
187 LEFT JOIN $indexable_table AS I
188 ON T.term_id = I.object_id
189 AND I.object_type = 'term'
190 AND I.version = %d
191 WHERE I.object_id IS NULL
192 AND taxonomy IN ($placeholders)
193 $limit_query",
194 $replacements,
195 );
196 }
197 }
198