PluginProbe
ElasticPress / 4.3.0
ElasticPress v4.3.0
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / includes / classes / Indexable / Term / QueryIntegration.php

QueryIntegration.php in ElasticPress 4.3.0, at includes/classes/Indexable/Term/QueryIntegration.php

337 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Integrate with WP_Term_Query
4 *
5 * @since 3.1
6 * @package elasticpress
7 */
8
9 namespace ElasticPress\Indexable\Term;
10
11 use ElasticPress\Indexables as Indexables;
12 use \WP_Term_Query as WP_Term_Query;
13 use ElasticPress\Utils as Utils;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Query integration class
21 */
22 class QueryIntegration {
23
24 /**
25 * Checks to see if we should be integrating and if so, sets up the appropriate actions and filters.
26 *
27 * @param string $indexable_slug Indexable slug. Optional.
28 *
29 * @since 3.1
30 * @since 3.6.0 Added $indexable_slug
31 */
32 public function __construct( $indexable_slug = 'term' ) {
33 // Ensure that we are currently allowing ElasticPress to override the normal WP_Query
34 // Indexable->is_full_reindexing() is not available at this point yet, so using the IndexHelper version of it.
35 if ( \ElasticPress\IndexHelper::factory()->is_full_reindexing( $indexable_slug, get_current_blog_id() ) ) {
36 return;
37 }
38
39 // Add header
40 add_action( 'pre_get_terms', array( $this, 'action_pre_get_terms' ), 5 );
41
42 // Filter term query
43 add_filter( 'terms_pre_query', [ $this, 'maybe_filter_query' ], 10, 2 );
44 }
45
46 /**
47 * Add EP header
48 *
49 * @param WP_Term_Query $query Query object
50 * @since 3.1
51 * @return void
52 */
53 public function action_pre_get_terms( WP_Term_Query $query ) {
54 if ( ! Indexables::factory()->get( 'term' )->elasticpress_enabled( $query ) || apply_filters( 'ep_skip_term_query_integration', false, $query ) ) {
55 return;
56 }
57
58 if ( ! headers_sent() ) {
59 /**
60 * Manually setting a header as $wp_query isn't yet initialized
61 * when we call: add_filter('wp_headers', 'filter_wp_headers');
62 */
63 header( 'X-ElasticPress-Term-Search: true' );
64 }
65 }
66
67 /**
68 * If WP_Term_Query meets certain conditions, query results from ES
69 *
70 * @param array $results Term results.
71 * @param WP_Term_Query $query Current query.
72 * @since 3.1
73 * @return array
74 */
75 public function maybe_filter_query( $results, WP_Term_Query $query ) {
76 $indexable = Indexables::factory()->get( 'term' );
77
78 if ( ! $indexable->elasticpress_enabled( $query ) || apply_filters( 'ep_skip_term_query_integration', false, $query ) ) {
79 return $results;
80 }
81
82 $new_terms = apply_filters( 'ep_wp_query_cached_terms', null, $query );
83
84 if ( null === $new_terms ) {
85 $formatted_args = $indexable->format_args( $query->query_vars );
86
87 $scope = 'current';
88 if ( ! empty( $query->query_vars['sites'] ) ) {
89 $scope = $query->query_vars['sites'];
90 }
91
92 /**
93 * Filter search scope
94 *
95 * @since 3.1
96 *
97 * @param mixed $scope The search scope. Accepts `all` (string), a single
98 * site id (int or string), or an array of site ids (array).
99 */
100 $scope = apply_filters( 'ep_term_search_scope', $scope );
101
102 if ( ! defined( 'EP_IS_NETWORK' ) || ! EP_IS_NETWORK ) {
103 $scope = 'current';
104 }
105
106 $index = null;
107
108 if ( 'all' === $scope ) {
109 $index = $indexable->get_network_alias();
110 } elseif ( is_numeric( $scope ) ) {
111 $index = $indexable->get_index_name( (int) $scope );
112 } elseif ( is_array( $scope ) ) {
113 $index = [];
114
115 foreach ( $scope as $site_id ) {
116 $index[] = $indexable->get_index_name( $site_id );
117 }
118
119 $index = implode( ',', $index );
120 }
121
122 $ep_query = $indexable->query_es( $formatted_args, $query->query_vars, $index );
123
124 if ( false === $ep_query ) {
125 $query->elasticsearch_success = false;
126 return $results;
127 }
128
129 /**
130 * Elasticsearch 5 will return found_documents as a number,
131 * ES 7+ will return it as an object with `value`. If any of that is found,
132 * fallback to a simple count of returned documents.
133 *
134 * @since 3.6.3
135 */
136 if ( is_integer( $ep_query['found_documents'] ) ) {
137 $query->found_terms = $ep_query['found_documents'];
138 } elseif ( is_array( $ep_query['found_documents'] ) && isset( $ep_query['found_documents']['value'] ) ) {
139 $query->found_terms = $ep_query['found_documents']['value'];
140 } else {
141 $query->found_terms = count( $ep_query['documents'] );
142 }
143
144 $query->elasticsearch_success = true;
145
146 // Determine how we should format the results from ES based on the fields parameter.
147 $fields = $query->query_vars['fields'];
148
149 $new_terms = [];
150
151 switch ( $fields ) {
152 case 'all_with_object_id':
153 $new_terms = $this->format_hits_as_terms( $ep_query['documents'], $new_terms, $query->query_vars );
154 break;
155
156 case 'count':
157 $new_terms = count( $ep_query['documents'] );
158 break;
159
160 case 'ids':
161 $new_terms = $this->format_hits_as_ids( $ep_query['documents'], $new_terms );
162 break;
163
164 case 'id=>name':
165 $new_terms = $this->format_hits_as_id_name( $ep_query['documents'], $new_terms );
166 break;
167
168 case 'id=>parent':
169 $new_terms = $this->format_hits_as_id_parent( $ep_query['documents'], $new_terms );
170 break;
171
172 case 'id=>slug':
173 $new_terms = $this->format_hits_as_id_slug( $ep_query['documents'], $new_terms );
174 break;
175
176 case 'names':
177 $new_terms = $this->format_hits_as_names( $ep_query['documents'], $new_terms );
178 break;
179
180 case 'tt_ids':
181 $new_terms = $this->format_hits_as_ids( $ep_query['documents'], $new_terms, 'term_taxonomy_id' );
182 break;
183
184 default:
185 $new_terms = $this->format_hits_as_terms( $ep_query['documents'], $new_terms, $query->query_vars );
186 break;
187 }
188
189 if ( ! empty( $query->query_vars['count'] ) ) {
190 $new_terms = count( $ep_query['documents'] );
191 }
192 }
193
194 return $new_terms;
195 }
196
197 /**
198 * Format the ES hits/results as term objects.
199 *
200 * @param array $terms The terms that should be formatted.
201 * @param array $new_terms Array of terms from cache.
202 * @param array $query_vars Query variables.
203 * @since 3.1
204 * @return array
205 */
206 protected function format_hits_as_terms( $terms, $new_terms, $query_vars ) {
207 foreach ( $terms as $term_array ) {
208 $term = new \stdClass();
209
210 $term->ID = $term_array['term_id'];
211 $term->site_id = get_current_blog_id();
212
213 if ( ! empty( $term_array['site_id'] ) ) {
214 $term->site_id = $term_array['site_id'];
215 }
216
217 $term_return_args = apply_filters(
218 'ep_search_term_return_args',
219 array(
220 'term_id',
221 'name',
222 'slug',
223 'term_group',
224 'term_taxonomy_id',
225 'taxonomy',
226 'description',
227 'parent',
228 'count',
229 'meta',
230 )
231 );
232
233 foreach ( $term_return_args as $key ) {
234 if ( isset( $term_array[ $key ] ) ) {
235 if ( 'count' === $key && ! empty( $query_vars['pad_counts'] ) ) {
236 $term_array[ $key ] += $term_array['hierarchy']['children']['count'];
237 }
238
239 $term->$key = $term_array[ $key ];
240 }
241 }
242
243 $term->elasticsearch = true; // Super useful for debugging.
244
245 $term = new \WP_Term( $term ); // Necessary for WordPress actions that expect WP_Term as the object type.
246
247 if ( $term ) {
248 $new_terms[] = $term;
249 }
250 }
251
252 return $new_terms;
253 }
254
255 /**
256 * Format the ES hits/results as an array of ids.
257 *
258 * @param array $terms The terms that should be formatted.
259 * @param array $new_terms Array of terms from cache.
260 * @param string $type Type of ID to return. Default 'term_id'.
261 * @since 3.1
262 * @return array
263 */
264 protected function format_hits_as_ids( $terms, $new_terms, $type = 'term_id' ) {
265 foreach ( $terms as $term_array ) {
266 $new_terms[] = 'term_id' === $type ? $term_array['term_id'] : $term_array['term_taxonomy_id'];
267 }
268
269 return $new_terms;
270 }
271
272 /**
273 * Format the ES hits/results as an array of term ID and term name.
274 *
275 * @param array $terms The terms that should be formatted.
276 * @param array $new_terms Array of terms from cache.
277 * @since 3.1
278 * @return array Returns an associative array with ids as keys, term names as values
279 */
280 protected function format_hits_as_id_name( $terms, $new_terms ) {
281 foreach ( $terms as $term_array ) {
282 $new_terms[ $term_array['term_id'] ] = $term_array['name'];
283 }
284
285 return $new_terms;
286 }
287
288 /**
289 * Format the ES hits/results as an array of term ID and parent ID.
290 *
291 * @param array $terms The terms that should be formatted.
292 * @param array $new_terms Array of terms from cache.
293 * @since 3.1
294 * @return array Returns an associative array with ids as keys, parent term IDs as values
295 */
296 protected function format_hits_as_id_parent( $terms, $new_terms ) {
297 foreach ( $terms as $term_array ) {
298 $new_terms[ $term_array['term_id'] ] = $term_array['parent'];
299 }
300
301 return $new_terms;
302 }
303
304 /**
305 * Format the ES hits/results as an array of term ID and term slug.
306 *
307 * @param array $terms The terms that should be formatted.
308 * @param array $new_terms Array of terms from cache.
309 * @since 3.1
310 * @return array Returns an associative array with ids as keys, term slugs as values
311 */
312 protected function format_hits_as_id_slug( $terms, $new_terms ) {
313 foreach ( $terms as $term_array ) {
314 $new_terms[ $term_array['term_id'] ] = $term_array['slug'];
315 }
316
317 return $new_terms;
318 }
319
320 /**
321 * Format the ES hits/results as an array of term names.
322 *
323 * @param array $terms The terms that should be formatted.
324 * @param array $new_terms Array of terms from cache.
325 * @since 3.1
326 * @return array Returns an array of term names.
327 */
328 protected function format_hits_as_names( $terms, $new_terms ) {
329 foreach ( $terms as $term_array ) {
330 $new_terms[] = $term_array['name'];
331 }
332
333 return $new_terms;
334 }
335
336 }
337