PluginProbe
ElasticPress / 5.0.1
ElasticPress v5.0.1
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 / Comment / Comment.php

Comment.php in ElasticPress 5.0.1, at includes/classes/Indexable/Comment/Comment.php

1,087 lines 26.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Comment indexable
4 *
5 * @since 3.6.0
6 * @package elasticpress
7 */
8
9 namespace ElasticPress\Indexable\Comment;
10
11 use \WP_Comment_Query;
12 use ElasticPress\Elasticsearch;
13 use ElasticPress\Features;
14 use ElasticPress\Indexable;
15 use ElasticPress\Indexable\Post\DateQuery;
16 use ElasticPress\Indexables;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21
22 /**
23 * Comment indexable class
24 */
25 class Comment extends Indexable {
26
27 /**
28 * Indexable slug
29 *
30 * @var string
31 * @since 3.6.0
32 */
33 public $slug = 'comment';
34
35 /**
36 * Create indexable and initialize dependencies
37 *
38 * @since 3.6.0
39 */
40 public function __construct() {
41 $this->labels = [
42 'plural' => esc_html__( 'Comments', 'elasticpress' ),
43 'singular' => esc_html__( 'Comment', 'elasticpress' ),
44 ];
45 }
46
47 /**
48 * Instantiate the indexable SyncManager and QueryIntegration, the main responsibles for the WP integration.
49 *
50 * @since 4.5.0
51 * @return void
52 */
53 public function setup() {
54 $this->sync_manager = new SyncManager( $this->slug );
55 $this->query_integration = new QueryIntegration();
56 }
57
58 /**
59 * Format query vars into ES query
60 *
61 * @param array $query_vars WP_Comment_Query args.
62 * @since 3.6.0
63 * @return array
64 */
65 public function format_args( $query_vars ) {
66 /**
67 * Support `number` query var
68 */
69 if ( ! empty( $query_vars['number'] ) ) {
70 $number = (int) $query_vars['number'];
71 } else {
72 /**
73 * Set the maximum results window size.
74 *
75 * The request will return a HTTP 500 Internal Error if the size of the
76 * request is larger than the [index.max_result_window] parameter in ES.
77 * See the scroll api for a more efficient way to request large data sets.
78 *
79 * @return int The max results window size.
80 *
81 * @since 2.3.0
82 */
83 $number = apply_filters( 'ep_max_results_window', 10000 );
84 }
85
86 $formatted_args = [
87 'from' => 0,
88 'size' => $number,
89 ];
90
91 /**
92 * Support `offset` query var
93 */
94 if ( isset( $query_vars['offset'] ) ) {
95 $formatted_args['from'] = (int) $query_vars['offset'];
96 if ( empty( $query_vars['number'] ) ) {
97 $formatted_args['size'] -= (int) $formatted_args['from'];
98 }
99 }
100
101 /**
102 * Support `paged` query var
103 *
104 * If `offset` is used, that takes precedence
105 * over this.
106 */
107 if ( isset( $query_vars['paged'] ) && empty( $query_vars['offset'] ) && $query_vars['paged'] > 1 ) {
108 $formatted_args['from'] = $number * ( $query_vars['paged'] - 1 );
109 }
110
111 /**
112 * Support `order` and `orderby` query vars
113 */
114
115 // Set sort order, default is 'desc'.
116 if ( ! empty( $query_vars['order'] ) ) {
117 $order = $this->parse_order( $query_vars['order'] );
118 } else {
119 $order = 'desc';
120 }
121
122 // Default sort by comment date
123 if ( empty( $query_vars['orderby'] ) ) {
124 $query_vars['orderby'] = 'comment_date_gmt';
125 }
126
127 // Set sort type.
128 $formatted_args['sort'] = $this->parse_orderby( $query_vars['orderby'], $order, $query_vars );
129
130 $filter = [
131 'bool' => [
132 'must' => [],
133 ],
134 ];
135
136 $use_filters = false;
137
138 /**
139 * Support `author_email` query var
140 */
141 if ( ! empty( $query_vars['author_email'] ) ) {
142 $filter['bool']['must'][] = [
143 'term' => [
144 'comment_author_email.raw' => $query_vars['author_email'],
145 ],
146 ];
147
148 $use_filters = true;
149 }
150
151 /**
152 * Support `author_url` query var
153 */
154 if ( ! empty( $query_vars['author_url'] ) ) {
155 $filter['bool']['must'][] = [
156 'term' => [
157 'comment_author_url.raw' => $query_vars['author_url'],
158 ],
159 ];
160
161 $use_filters = true;
162 }
163
164 /**
165 * Support `user_id` query var
166 */
167 if ( ! empty( $query_vars['user_id'] ) ) {
168 $filter['bool']['must'][] = [
169 'term' => [
170 'user_id' => (int) $query_vars['user_id'],
171 ],
172 ];
173
174 $use_filters = true;
175 }
176
177 /**
178 * Support `author__in` query var
179 */
180 if ( ! empty( $query_vars['author__in'] ) ) {
181 $filter['bool']['must'][]['bool']['must'] = [
182 'terms' => [
183 'user_id' => array_values( (array) $query_vars['author__in'] ),
184 ],
185 ];
186
187 $use_filters = true;
188 }
189
190 /**
191 * Support `author__not_in` query var
192 */
193 if ( ! empty( $query_vars['author__not_in'] ) ) {
194 $filter['bool']['must'][]['bool']['must_not'] = [
195 'terms' => [
196 'user_id' => array_values( (array) $query_vars['author__not_in'] ),
197 ],
198 ];
199
200 $use_filters = true;
201 }
202
203 /**
204 * Support `comment__in` query var
205 */
206 if ( ! empty( $query_vars['comment__in'] ) ) {
207 $filter['bool']['must'][]['bool']['must'] = [
208 'terms' => [
209 'comment_ID' => array_values( (array) $query_vars['comment__in'] ),
210 ],
211 ];
212
213 $use_filters = true;
214 }
215
216 /**
217 * Support `comment__not_in` query var
218 */
219 if ( ! empty( $query_vars['comment__not_in'] ) ) {
220 $filter['bool']['must'][]['bool']['must_not'] = [
221 'terms' => [
222 'comment_ID' => array_values( (array) $query_vars['comment__not_in'] ),
223 ],
224 ];
225
226 $use_filters = true;
227 }
228
229 /**
230 * Support `date_query` query var
231 */
232 if ( ! empty( $query_vars['date_query'] ) ) {
233 $date_query = new DateQuery( $query_vars['date_query'] );
234 $date_filter = $date_query->get_es_filter();
235
236 if ( array_key_exists( 'and', $date_filter ) ) {
237 $filter['bool']['must'][] = $date_filter['and'];
238 $use_filters = true;
239 }
240 }
241
242 /**
243 * Support `fields` query var.
244 */
245 if ( isset( $query_vars['fields'] ) ) {
246 switch ( $query_vars['fields'] ) {
247 case 'ids':
248 $formatted_args['_source'] = [
249 'includes' => [
250 'comment_ID',
251 ],
252 ];
253 break;
254 }
255 }
256
257 /**
258 * Support `karma` query var.
259 */
260 if ( ! empty( $query_vars['karma'] ) || 0 === $query_vars['karma'] ) {
261 $filter['bool']['must'][]['bool']['must'] = [
262 'term' => [
263 'comment_karma' => $query_vars['karma'],
264 ],
265 ];
266
267 $use_filters = true;
268 }
269
270 $meta_queries = [];
271
272 /**
273 * Support `meta_key` and `meta_value` query args
274 */
275 if ( ! empty( $query_vars['meta_key'] ) ) {
276 $meta_query_array = [
277 'key' => $query_vars['meta_key'],
278 ];
279
280 if ( isset( $query_vars['meta_value'] ) ) {
281 $meta_query_array['value'] = $query_vars['meta_value'];
282 }
283
284 $meta_queries[] = $meta_query_array;
285 }
286
287 /**
288 * Support 'meta_query' query var.
289 */
290 if ( ! empty( $query_vars['meta_query'] ) ) {
291 $meta_queries = array_merge( $meta_queries, $query_vars['meta_query'] );
292 }
293
294 if ( ! empty( $meta_queries ) ) {
295 $built_meta_queries = $this->build_meta_query( $meta_queries );
296
297 if ( $built_meta_queries ) {
298 $filter['bool']['must'][] = $built_meta_queries;
299 $use_filters = true;
300 }
301 }
302
303 /**
304 * Support `hierarchical` query var
305 */
306 if ( ! empty( $query_vars['hierarchical'] ) && empty( $query_vars['parent'] ) ) {
307 $query_vars['parent'] = 0;
308 }
309
310 /**
311 * Support `parent` query var.
312 */
313 if ( ! empty( $query_vars['parent'] ) || 0 === $query_vars['parent'] ) {
314 $filter['bool']['must'][]['bool']['must'] = [
315 'term' => [
316 'comment_parent' => (int) $query_vars['parent'],
317 ],
318 ];
319
320 $use_filters = true;
321 }
322
323 /**
324 * Support `parent__in` query var
325 */
326 if ( ! empty( $query_vars['parent__in'] ) ) {
327 $filter['bool']['must'][]['bool']['must'] = [
328 'terms' => [
329 'comment_parent' => array_values( (array) $query_vars['parent__in'] ),
330 ],
331 ];
332
333 $use_filters = true;
334 }
335
336 /**
337 * Support `parent__not_in` query var
338 */
339 if ( ! empty( $query_vars['parent__not_in'] ) ) {
340 $filter['bool']['must'][]['bool']['must_not'] = [
341 'terms' => [
342 'comment_parent' => array_values( (array) $query_vars['parent__not_in'] ),
343 ],
344 ];
345
346 $use_filters = true;
347 }
348
349 /**
350 * Support `post_author` query var.
351 */
352 if ( ! empty( $query_vars['post_author'] ) ) {
353 $filter['bool']['must'][]['bool']['must'] = [
354 'term' => [
355 'comment_post_author_ID' => (int) $query_vars['post_author'],
356 ],
357 ];
358
359 $use_filters = true;
360 }
361
362 /**
363 * Support `post_author__in` query var
364 */
365 if ( ! empty( $query_vars['post_author__in'] ) ) {
366 $filter['bool']['must'][]['bool']['must'] = [
367 'terms' => [
368 'comment_post_author_ID' => array_values( (array) $query_vars['post_author__in'] ),
369 ],
370 ];
371
372 $use_filters = true;
373 }
374
375 /**
376 * Support `post_author__not_in` query var
377 */
378 if ( ! empty( $query_vars['post_author__not_in'] ) ) {
379 $filter['bool']['must'][]['bool']['must_not'] = [
380 'terms' => [
381 'comment_post_author_ID' => array_values( (array) $query_vars['post_author__not_in'] ),
382 ],
383 ];
384
385 $use_filters = true;
386 }
387
388 /**
389 * Support `post_id` query var.
390 */
391 if ( ! empty( $query_vars['post_id'] ) ) {
392 $filter['bool']['must'][]['bool']['must'] = [
393 'term' => [
394 'comment_post_ID' => (int) $query_vars['post_id'],
395 ],
396 ];
397
398 $use_filters = true;
399 }
400
401 /**
402 * Support `post__in` query var
403 */
404 if ( ! empty( $query_vars['post__in'] ) ) {
405 $filter['bool']['must'][]['bool']['must'] = [
406 'terms' => [
407 'comment_post_ID' => array_values( (array) $query_vars['post__in'] ),
408 ],
409 ];
410
411 $use_filters = true;
412 }
413
414 /**
415 * Support `post__not_in` query var
416 */
417 if ( ! empty( $query_vars['post__not_in'] ) ) {
418 $filter['bool']['must'][]['bool']['must_not'] = [
419 'terms' => [
420 'comment_post_ID' => array_values( (array) $query_vars['post__not_in'] ),
421 ],
422 ];
423
424 $use_filters = true;
425 }
426
427 /**
428 * Support `post_status` query var
429 */
430 if ( ! empty( $query_vars['post_status'] ) && 'any' !== $query_vars['post_status'] ) {
431 $post_status = (array) ( is_string( $query_vars['post_status'] ) ? explode( ',', $query_vars['post_status'] ) : $query_vars['post_status'] );
432 $post_status = array_map( 'trim', $post_status );
433 $terms_map_name = 'terms';
434
435 if ( count( $post_status ) < 2 ) {
436 $terms_map_name = 'term';
437 $post_status = $post_status[0];
438 }
439
440 $filter['bool']['must'][] = array(
441 $terms_map_name => array(
442 'comment_post_status' => $post_status,
443 ),
444 );
445
446 $use_filters = true;
447 }
448
449 /**
450 * Support `post_type` query var.
451 */
452 if ( ! empty( $query_vars['post_type'] ) ) {
453 $filter['bool']['must'][]['bool']['must'] = [
454 'terms' => [
455 'comment_post_type.raw' => array_values( (array) $query_vars['post_type'] ),
456 ],
457 ];
458
459 $use_filters = true;
460 }
461
462 /**
463 * Support `post_name` query var.
464 */
465 if ( ! empty( $query_vars['post_name'] ) ) {
466 $filter['bool']['must'][]['bool']['must'] = [
467 'term' => [
468 'comment_post_name.raw' => $query_vars['post_name'],
469 ],
470 ];
471
472 $use_filters = true;
473 }
474
475 /**
476 * Support `post_parent` query var.
477 */
478 if ( ! empty( $query_vars['post_parent'] ) ) {
479 $filter['bool']['must'][]['bool']['must'] = [
480 'term' => [
481 'comment_post_parent' => (int) $query_vars['post_parent'],
482 ],
483 ];
484
485 $use_filters = true;
486 }
487
488 /**
489 * Support `search` query_var
490 */
491 if ( ! empty( $query_vars['search'] ) ) {
492
493 $search = ! empty( $query_vars['search'] ) ? $query_vars['search'] : '';
494 $search_fields = [];
495
496 /**
497 * Allow for search field specification
498 */
499 if ( ! empty( $query_vars['search_fields'] ) ) {
500 $search_fields = $query_vars['search_fields'];
501 }
502
503 if ( ! empty( $search_fields ) ) {
504 $prepared_search_fields = [];
505
506 if ( ! empty( $search_fields['meta'] ) ) {
507 $metas = (array) $search_fields['meta'];
508
509 foreach ( $metas as $meta ) {
510 $prepared_search_fields[] = 'meta.' . $meta . '.value';
511 }
512
513 unset( $search_fields['meta'] );
514 }
515
516 $prepared_search_fields = array_merge( $search_fields, $prepared_search_fields );
517 } else {
518 $prepared_search_fields = [
519 'comment_author',
520 'comment_author_email',
521 'comment_author_url',
522 'comment_content',
523 ];
524 }
525
526 /**
527 * Filter default comment search fields
528 *
529 * If you are using the weighting engine, this filter should not be used.
530 * Instead, you should use the ep_weighting_configuration_for_search filter.
531 *
532 * @hook ep_comment_search_fields
533 * @since 3.6.0
534 * @param {array} $search_fields Default search fields
535 * @param {array} $query_vars WP_Comment_Query args
536 * @return {array} New defaults
537 */
538 $prepared_search_fields = apply_filters( 'ep_comment_search_fields', $prepared_search_fields, $query_vars );
539
540 $search_algorithm = $this->get_search_algorithm( $search, $prepared_search_fields, $query_vars );
541 $formatted_args['query'] = $search_algorithm->get_query( 'comment', $search, $prepared_search_fields, $query_vars );
542 } else {
543 $formatted_args['query']['match_all'] = [
544 'boost' => 1,
545 ];
546 }
547
548 /**
549 * Support `status` query var
550 */
551 if ( ! empty( $query_vars['status'] ) && 'all' !== $query_vars['status'] ) {
552 $comment_stati = (array) ( is_string( $query_vars['status'] ) ? explode( ',', $query_vars['status'] ) : $query_vars['status'] );
553 $comment_stati = array_map( 'trim', $comment_stati );
554
555 foreach ( $comment_stati as $key => $status ) {
556 if ( 'hold' === $status ) {
557 $comment_stati[ $key ] = 0;
558 }
559
560 if ( 'approve' === $status ) {
561 $comment_stati[ $key ] = 1;
562 }
563 }
564
565 $terms_map_name = 'terms';
566
567 if ( count( $comment_stati ) < 2 ) {
568 $terms_map_name = 'term';
569 $comment_stati = $comment_stati[0];
570 }
571
572 /**
573 * Support `include_unapproved` query var
574 */
575 if ( ! empty( $query_vars['include_unapproved'] ) ) {
576 $include_unapproved = wp_parse_list( $query_vars['include_unapproved'] );
577 $unapproved_ids = [];
578 $unapproved_emails = [];
579
580 foreach ( $include_unapproved as $unapproved_identifier ) {
581 // Numeric values are assumed to be user ids.
582 if ( is_numeric( $unapproved_identifier ) ) {
583 $unapproved_ids[] = $unapproved_identifier;
584
585 // Otherwise we assume it's an email address.
586 } else {
587 $unapproved_emails[] = $unapproved_identifier;
588 }
589 }
590
591 $filter['bool']['must'][]['bool']['should'] = [
592 [
593 $terms_map_name => [
594 'comment_approved' => $comment_stati,
595 ],
596 ],
597 [
598 'terms' => [
599 'user_id' => array_values( array_map( 'absint', $unapproved_ids ) ),
600 ],
601 ],
602 [
603 'terms' => [
604 'comment_author_email.raw' => array_values( $unapproved_emails ),
605 ],
606 ],
607 ];
608 } else {
609 $filter['bool']['must'][] = [
610 $terms_map_name => [
611 'comment_approved' => $comment_stati,
612 ],
613 ];
614 }
615
616 $use_filters = true;
617 }
618
619 /**
620 * Support `type` query var
621 */
622 if ( ! empty( $query_vars['type'] ) ) {
623 $types = (array) ( is_string( $query_vars['type'] ) ? explode( ',', $query_vars['type'] ) : $query_vars['type'] );
624 $types = array_map( 'trim', $types );
625
626 $terms_map_name = 'terms';
627
628 if ( count( $types ) < 2 ) {
629 $terms_map_name = 'term';
630 $types = $types[0];
631 }
632
633 $filter['bool']['must'][] = [
634 $terms_map_name => [
635 'comment_type.raw' => $types,
636 ],
637 ];
638
639 $use_filters = true;
640 }
641
642 /**
643 * Support `type__in` query var
644 */
645 if ( ! empty( $query_vars['type__in'] ) ) {
646 $filter['bool']['must'][]['bool']['must'] = [
647 'terms' => [
648 'comment_type.raw' => array_values( (array) $query_vars['type__in'] ),
649 ],
650 ];
651
652 $use_filters = true;
653 }
654
655 /**
656 * Support `type__not_in` query var
657 */
658 if ( ! empty( $query_vars['type__not_in'] ) ) {
659 $filter['bool']['must'][]['bool']['must_not'] = [
660 'terms' => [
661 'comment_type.raw' => array_values( (array) $query_vars['type__not_in'] ),
662 ],
663 ];
664
665 $use_filters = true;
666 }
667
668 if ( $use_filters ) {
669 $formatted_args['post_filter'] = $filter;
670 }
671
672 /**
673 * Filter formatted Elasticsearch query (entire query)
674 *
675 * @hook ep_comment_formatted_args
676 * @since 3.6.0
677 * @param {array} $formatted_args Formatted Elasticsearch query
678 * @param {array} $query_vars WP_Comment_Query args
679 * @return {array} New query
680 */
681 return apply_filters( 'ep_comment_formatted_args', $formatted_args, $query_vars );
682 }
683
684 /**
685 * Generate the mapping array
686 *
687 * @since 4.1.0
688 * @return array
689 */
690 public function generate_mapping() {
691 $es_version = Elasticsearch::factory()->get_elasticsearch_version();
692
693 if ( empty( $es_version ) ) {
694 /**
695 * Filter fallback Elasticsearch version
696 *
697 * @hook ep_fallback_elasticsearch_version
698 * @param {string} $version Fall back Elasticsearch version
699 * @return {string} New version
700 */
701 $es_version = apply_filters( 'ep_fallback_elasticsearch_version', '2.0' );
702 }
703
704 $es_version = (string) $es_version;
705
706 $mapping_file = '7-0.php';
707
708 if ( version_compare( $es_version, '7.0', '<' ) ) {
709 $mapping_file = 'initial.php';
710 }
711
712 /**
713 * Filter comment indexable mapping file
714 *
715 * @hook ep_comment_mapping_file
716 * @since 3.6.0
717 * @param {string} $file Path to file
718 * @return {string} New file path
719 */
720 $mapping = require apply_filters( 'ep_comment_mapping_file', __DIR__ . '/../../../mappings/comment/' . $mapping_file );
721
722 /**
723 * Filter comment indexable mapping
724 *
725 * @hook ep_comment_mapping
726 * @since 3.6.0
727 * @param {array} $mapping Mapping
728 * @return {array} New mapping
729 */
730 $mapping = apply_filters( 'ep_comment_mapping', $mapping );
731
732 return $mapping;
733 }
734
735 /**
736 * Returns indexable comment types
737 *
738 * @since 3.6.0
739 * @return array
740 */
741 public function get_indexable_comment_types() {
742 $comment_types = [ 'comment' ];
743
744 if ( Features::factory()->registered_features['woocommerce']->is_active() ) {
745 $comment_types[] = 'review';
746 }
747
748 /**
749 * Filter indexable comment types
750 *
751 * @hook ep_indexable_comment_types
752 * @since 3.6.0
753 * @param {array} $comment_types Indexable comment types
754 * @return {array} comment types
755 */
756 return apply_filters( 'ep_indexable_comment_types', $comment_types );
757 }
758
759 /**
760 * Returns indexable comment status
761 *
762 * @since 3.6.0
763 * @return array
764 */
765 public function get_indexable_comment_status() {
766 $comment_status = [ '1' ];
767
768 /**
769 * Filter indexable comment status
770 *
771 * @hook ep_indexable_comment_status
772 * @since 3.6.0
773 * @param {array} $comment_status Indexable comment status
774 * @return {array} comment status
775 */
776 return apply_filters( 'ep_indexable_comment_status', $comment_status );
777 }
778
779 /**
780 * Query DB for comments
781 *
782 * @param array $args Query arguments
783 * @since 3.6.0
784 * @return array
785 */
786 public function query_db( $args ) {
787
788 $defaults = [
789 'type' => $this->get_indexable_comment_types(),
790 'status' => $this->get_indexable_comment_status(),
791 'post_type' => Indexables::factory()->get( 'post' )->get_indexable_post_types(),
792 'post_status' => Indexables::factory()->get( 'post' )->get_indexable_post_status(),
793 'number' => $this->get_bulk_items_per_page(),
794 'offset' => 0,
795 'orderby' => 'comment_ID',
796 'order' => 'desc',
797 ];
798
799 if ( isset( $args['per_page'] ) ) {
800 $args['number'] = $args['per_page'];
801 }
802
803 /**
804 * Filter database arguments for comment query
805 *
806 * @hook ep_comment_query_db_args
807 * @param {array} $args Query arguments based to WP_Comment_Query
808 * @since 3.6.0
809 * @return {array} New arguments
810 */
811 $args = apply_filters( 'ep_comment_query_db_args', wp_parse_args( $args, $defaults ) );
812
813 $all_query_args = $args;
814
815 unset( $all_query_args['number'] );
816 unset( $all_query_args['offset'] );
817 $all_query_args['count'] = true;
818
819 /**
820 * Filter database arguments for comment count query
821 *
822 * @hook ep_comment_all_query_db_args
823 * @param {array} $args Query arguments based to WP_Comment_Query
824 * @since 3.6.0
825 * @return {array} New arguments
826 */
827 $total_objects = get_comments( apply_filters( 'ep_comment_all_query_db_args', $all_query_args, $args ) );
828
829 if ( ! empty( $args['offset'] ) ) {
830 if ( (int) $args['offset'] >= $total_objects ) {
831 $total_objects = 0;
832 }
833 }
834
835 $query = new WP_Comment_Query( $args );
836
837 if ( is_array( $query->comments ) ) {
838 array_walk( $query->comments, [ $this, 'remap_comments' ] );
839 }
840
841 return [
842 'objects' => $query->comments,
843 'total_objects' => $total_objects,
844 ];
845 }
846
847 /**
848 * Prepare a comment document for indexing
849 *
850 * @param int $comment_id Comment ID
851 * @since 3.6.0
852 * @return bool|array
853 */
854 public function prepare_document( $comment_id ) {
855 $comment = get_comment( $comment_id );
856
857 if ( ! $comment || ! is_a( $comment, 'WP_Comment' ) ) {
858 return false;
859 }
860
861 $comment_post = get_post( $comment->comment_post_ID );
862
863 $comment_args = [
864 'comment_ID' => $comment->comment_ID,
865 'ID' => $comment->comment_ID,
866 'comment_post_ID' => $comment->comment_post_ID,
867 'comment_post_author_ID' => $comment_post->post_author,
868 'comment_post_status' => $comment_post->post_status,
869 'comment_post_type' => $comment_post->post_type,
870 'comment_post_name' => $comment_post->post_name,
871 'comment_post_parent' => $comment_post->post_parent,
872 'comment_author' => $comment->comment_author,
873 'comment_author_email' => $comment->comment_author_email,
874 'comment_author_url' => $comment->comment_author_url,
875 'comment_author_IP' => $comment->comment_author_IP,
876 'comment_date' => $comment->comment_date,
877 'comment_date_gmt' => $comment->comment_date_gmt,
878 'comment_content' => $comment->comment_content,
879 'comment_karma' => $comment->comment_karma,
880 'comment_approved' => $comment->comment_approved,
881 'comment_agent' => $comment->comment_agent,
882 'comment_type' => $comment->comment_type ? $comment->comment_type : 'comment',
883 'comment_parent' => $comment->comment_parent,
884 'user_id' => $comment->user_id,
885 'meta' => $this->prepare_meta_types( $this->prepare_meta( $comment->comment_ID ) ),
886 ];
887
888 /**
889 * Filter sync arguments for a comment.
890 *
891 * @hook ep_comment_sync_args
892 * @param {array} $comment_args Comment arguments
893 * @param {int} $comment_id Comment ID
894 * @return {array} New arguments
895 */
896 $comment_args = apply_filters( 'ep_comment_sync_args', $comment_args, $comment_id );
897
898 return $comment_args;
899 }
900
901 /**
902 * Rebuild our comment objects to match the fields we need.
903 *
904 * In particular, result of WP_Comment_Query does not
905 * include an "id" field, which our index command
906 * expects.
907 *
908 * @param object $value Comment object
909 * @since 3.6.0
910 * @return void Returns by reference
911 */
912 public function remap_comments( &$value ) {
913 $value = (object) [
914 'ID' => $value->comment_ID,
915 'comment_ID' => $value->comment_ID,
916 'comment_post_ID' => $value->comment_post_ID,
917 'comment_author' => $value->comment_author,
918 'comment_author_email' => $value->comment_author_email,
919 'comment_author_url' => $value->comment_author_url,
920 'comment_author_IP' => $value->comment_author_IP,
921 'comment_date' => $value->comment_date,
922 'comment_date_gmt' => $value->comment_date_gmt,
923 'comment_content' => $value->comment_content,
924 'comment_karma' => $value->comment_karma,
925 'comment_approved' => $value->comment_approved,
926 'comment_agent' => $value->comment_agent,
927 'comment_type' => $value->comment_type,
928 'comment_parent' => $value->comment_parent,
929 'user_id' => $value->user_id,
930 ];
931 }
932
933 /**
934 * Prepare meta to send to ES
935 *
936 * @param int $comment_id Comment ID
937 * @since 3.6.0
938 * @return array
939 */
940 public function prepare_meta( $comment_id ) {
941 $meta = (array) get_comment_meta( $comment_id );
942
943 if ( empty( $meta ) ) {
944 return [];
945 }
946
947 $prepared_meta = [];
948
949 /**
950 * Filter index-able private meta
951 *
952 * Allows for specifying private meta keys that may be indexed in the same manner as public meta keys.
953 *
954 * @since 3.6.0
955 *
956 * @param array Array of index-able private meta keys.
957 * @param int $comment_id Comment ID.
958 */
959 $allowed_protected_keys = apply_filters(
960 'ep_prepare_comment_meta_allowed_protected_keys',
961 [],
962 $comment_id
963 );
964
965 /**
966 * Filter non-indexed public meta
967 *
968 * Allows for specifying public meta keys that should be excluded from the ElasticPress index.
969 *
970 * @since 3.6.0
971 *
972 * @param array Array of public meta keys to exclude from index.
973 * @param int $comment_id Comment ID.
974 */
975 $excluded_public_keys = apply_filters(
976 'ep_prepare_comment_meta_excluded_public_keys',
977 [],
978 $comment_id
979 );
980
981 foreach ( $meta as $key => $value ) {
982
983 $allow_index = false;
984
985 if ( is_protected_meta( $key ) ) {
986
987 if ( true === $allowed_protected_keys || in_array( $key, $allowed_protected_keys, true ) ) {
988 $allow_index = true;
989 }
990 } else {
991
992 if ( true !== $excluded_public_keys && ! in_array( $key, $excluded_public_keys, true ) ) {
993 $allow_index = true;
994 }
995 }
996
997 /**
998 * Filter force allow a meta key
999 *
1000 * @hook ep_prepare_comment_meta_allowed_key
1001 * @since 3.6.0
1002 * @param {bool} $allowed True to allow the key
1003 * @param {string} $key Meta key
1004 * @param {int} $comment_id Comment ID
1005 * @return {bool} New allowed value
1006 */
1007 if ( true === $allow_index || apply_filters( 'ep_prepare_comment_meta_allowed_key', false, $key, $comment_id ) ) {
1008 $prepared_meta[ $key ] = maybe_unserialize( $value );
1009 }
1010 }
1011
1012 return $prepared_meta;
1013 }
1014
1015 /**
1016 * Parse an 'order' query variable and cast it to asc or desc as necessary.
1017 *
1018 * @access protected
1019 *
1020 * @param string $order The 'order' query variable.
1021 * @since 3.6.0
1022 * @return string The sanitized 'order' query variable.
1023 */
1024 protected function parse_order( $order ) {
1025 if ( ! is_string( $order ) || empty( $order ) ) {
1026 return 'desc';
1027 }
1028
1029 if ( 'ASC' === strtoupper( $order ) ) {
1030 return 'asc';
1031 } else {
1032 return 'desc';
1033 }
1034 }
1035
1036 /**
1037 * Convert the alias to a properly-prefixed sort value.
1038 *
1039 * @access protected
1040 *
1041 * @param string $orderby Alias or path for the field to order by.
1042 * @param string $order Order direction
1043 * @param array $args Query args
1044 * @since 3.6.0
1045 * @return array
1046 */
1047 protected function parse_orderby( $orderby, $order, $args ) {
1048 $sort = [];
1049
1050 if ( empty( $orderby ) ) {
1051 return $sort;
1052 }
1053
1054 $from_to = [
1055 'comment_agent' => 'comment_agent.raw',
1056 'comment_approved' => 'comment_approved.raw',
1057 'comment_author' => 'comment_author.raw',
1058 'comment_author_email' => 'comment_author_email.raw',
1059 'comment_author_IP' => 'comment_author_IP.raw',
1060 'comment_author_url' => 'comment_author_url.raw',
1061 'comment_content' => 'comment_content.raw',
1062 'comment_type' => 'comment_type.raw',
1063 'comment_post_type' => 'comment_post_type.raw',
1064 ];
1065
1066 if ( in_array( $orderby, [ 'meta_value', 'meta_value_num' ], true ) ) {
1067 if ( empty( $args['meta_key'] ) ) {
1068 return $sort;
1069 } else {
1070 $from_to['meta_value'] = 'meta.' . $args['meta_key'] . '.raw';
1071 $from_to['meta_value_num'] = 'meta.' . $args['meta_key'] . '.long';
1072 }
1073 }
1074
1075 $orderby = $from_to[ $orderby ] ?? $orderby;
1076
1077 $sort[] = array(
1078 $orderby => array(
1079 'order' => $order,
1080 ),
1081 );
1082
1083 return $sort;
1084 }
1085
1086 }
1087