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