PluginProbe
ElasticPress / 4.4.0
ElasticPress v4.4.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 / Feature / Comments / Comments.php

Comments.php in ElasticPress 4.4.0, at includes/classes/Feature/Comments/Comments.php

427 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Comments feature
4 *
5 * @since 3.6.0
6 * @package elasticpress
7 */
8
9 namespace ElasticPress\Feature\Comments;
10
11 use ElasticPress\Feature as Feature;
12 use ElasticPress\Indexables as Indexables;
13 use ElasticPress\Indexable as Indexable;
14 use ElasticPress\Features as Features;
15 use ElasticPress\FeatureRequirementsStatus as FeatureRequirementsStatus;
16 use ElasticPress\Utils;
17
18 /**
19 * Comments feature class
20 */
21 class Comments extends Feature {
22
23 /**
24 * Initialize feature, setting it's config
25 *
26 * @since 3.6.0
27 */
28 public function __construct() {
29 $this->slug = 'comments';
30
31 $this->title = esc_html__( 'Comments', 'elasticpress' );
32
33 $this->summary = __( 'Improve comment search relevancy and query performance.', 'elasticpress' );
34
35 $this->docs_url = __( 'https://elasticpress.zendesk.com/hc/en-us/articles/360050447492-Configuring-ElasticPress-via-the-Plugin-Dashboard#comments', 'elasticpress' );
36
37 $this->requires_install_reindex = true;
38
39 parent::__construct();
40 }
41
42 /**
43 * Setup search functionality
44 *
45 * @since 3.6.0
46 */
47 public function setup() {
48 Indexables::factory()->register( new Indexable\Comment\Comment() );
49
50 add_action( 'init', [ $this, 'register_block' ] );
51 add_action( 'init', [ $this, 'search_setup' ] );
52 add_action( 'widgets_init', [ $this, 'register_widget' ] );
53 add_action( 'rest_api_init', [ $this, 'rest_api_init' ] );
54 add_action( 'wp_enqueue_scripts', [ $this, 'frontend_scripts' ] );
55 add_filter( 'widget_types_to_hide_from_legacy_widget_block', [ $this, 'hide_legacy_widget' ] );
56 }
57
58 /**
59 * Setup search integration
60 *
61 * @since 3.6.0
62 */
63 public function search_setup() {
64 $admin_integration = apply_filters( 'ep_admin_wp_query_integration', false );
65
66 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
67 /**
68 * Filter to integrate with admin ajax queries
69 *
70 * @hook ep_ajax_wp_query_integration
71 * @param {bool} $integrate True to integrate
72 * @return {bool} New value
73 */
74 if ( ! apply_filters( 'ep_ajax_wp_query_integration', false ) ) {
75 return;
76 } else {
77 $admin_integration = true;
78 }
79 }
80
81 if ( is_admin() && ! $admin_integration ) {
82 return;
83 }
84
85 add_filter( 'ep_elasticpress_enabled', [ $this, 'integrate_search_queries' ], 10, 2 );
86 }
87
88 /**
89 * Output feature box long text
90 *
91 * @since 3.6.0
92 */
93 public function output_feature_box_long() {
94 ?>
95 <p><?php esc_html_e( 'This feature will empower your website to overcome traditional WordPress comment search and query limitations that can present themselves at scale.', 'elasticpress' ); ?></p>
96 <?php
97 }
98
99 /**
100 * Enable integration on search queries
101 *
102 * @param bool $enabled Whether EP is enabled
103 * @param \WP_Comment_Query $query Current query object.
104 * @since 3.6.0
105 * @return bool
106 */
107 public function integrate_search_queries( $enabled, $query ) {
108 if ( ! is_a( $query, 'WP_Comment_Query' ) ) {
109 return $enabled;
110 }
111
112 if ( isset( $query->query_vars['ep_integrate'] ) && ! filter_var( $query->query_vars['ep_integrate'], FILTER_VALIDATE_BOOLEAN ) ) {
113 $enabled = false;
114 } elseif ( ! empty( $query->query_vars['search'] ) ) {
115 $enabled = true;
116 }
117
118 return $enabled;
119 }
120
121 /**
122 * Determine feature reqs status
123 *
124 * @since 3.6.0
125 * @return FeatureRequirementsStatus
126 */
127 public function requirements_status() {
128 $status = new FeatureRequirementsStatus( 1 );
129
130 return $status;
131 }
132
133 /**
134 * Register comments widget
135 *
136 * @since 3.6.0
137 */
138 public function register_widget() {
139 register_widget( __NAMESPACE__ . '\Widget' );
140 }
141
142 /**
143 * Registers the API endpoint to search for comments
144 *
145 * @since 3.6.0
146 */
147 public function rest_api_init() {
148 register_rest_route(
149 'elasticpress/v1',
150 'comments',
151 [
152 'methods' => 'GET',
153 'callback' => [ $this, 'handle_comments_search' ],
154 'permission_callback' => '__return_true',
155 'args' => [
156 's' => [
157 'validate_callback' => function ( $param ) {
158 return ! empty( $param );
159 },
160 'required' => true,
161 ],
162 'post_type' => [
163 'validate_callback' => function ( $param ) {
164 return ! empty( $param );
165 },
166 ],
167 ],
168 ]
169 );
170 }
171
172 /**
173 * Handles the search for comments
174 *
175 * @since 3.6.0
176 * @param \WP_REST_Request $request Rest request
177 * @return array
178 */
179 public function handle_comments_search( $request ) {
180 $search = $request->get_param( 's' );
181
182 if ( empty( $search ) ) {
183 return new \WP_Error( 400 );
184 }
185
186 $post_type_filter = explode( ',', $request->get_param( 'post_type' ) );
187 $searchable_post_types = array_filter(
188 Features::factory()->get_registered_feature( 'search' )->get_searchable_post_types(),
189 function ( $post_type ) {
190 return post_type_supports( $post_type, 'comments' );
191 }
192 );
193
194 if ( ! empty( $post_type_filter ) && is_array( $searchable_post_types ) ) {
195 $post_type_filter = array_intersect( $post_type_filter, $searchable_post_types );
196 }
197
198 $default_args = [
199 'status' => 'approve',
200 'search' => $search,
201 'type' => Indexables::factory()->get( 'comment' )->get_indexable_comment_types(),
202 'post_type' => empty( $post_type_filter ) ? $searchable_post_types : $post_type_filter,
203 'post_status' => 'publish',
204 'number' => 5,
205 ];
206
207 /**
208 * Filter to args used in WP_Comment_Query in Widget Search Comment
209 *
210 * @hook ep_comment_search_widget_args
211 * @since 3.6.0
212 * @param {array} $default_args Defaults args
213 * @return {array} New value
214 */
215 $args = apply_filters( 'ep_comment_search_widget_args', $default_args );
216
217 /**
218 * Fires before the comment query is executed.
219 *
220 * @hook ep_comment_pre_search_widget
221 * @since 3.6.0
222 * @param {array} $args Args passed to `WP_Comment_Query`.
223 * @param {WP_REST_Request} $request Rest request.
224 */
225 do_action( 'ep_comment_pre_search_widget', $args, $request );
226
227 $comment_query = new \WP_Comment_Query( $args );
228
229 /**
230 * Fires after the comment query is executed.
231 *
232 * @hook ep_comment_after_search_widget
233 * @since 3.6.0
234 * @param {WP_Comment_Query} $comment_query WP_Comment_Query object.
235 * @param {WP_REST_Request} $request Rest request.
236 */
237 do_action( 'ep_comment_after_search_widget', $comment_query, $request );
238
239 $return = [];
240 foreach ( $comment_query->comments as $comment ) {
241 $return[ $comment->comment_ID ] = [
242 'id' => $comment->comment_ID,
243 'content' => $comment->comment_content,
244 'link' => get_comment_link( $comment ),
245 ];
246 }
247
248 /**
249 * Filters the comments response
250 *
251 * @hook ep_comment_search_widget_response
252 * @since 3.6.0
253 * @param {array} $return The result of fetched comments.
254 * @return {array} New value
255 */
256 return apply_filters( 'ep_comment_search_widget_response', $return );
257 }
258
259 /**
260 * Get a list of searchable post types that support comments.
261 *
262 * @return array Array of post type labels keyed by post type.
263 * @since 4.4.0
264 */
265 public static function get_searchable_post_types() {
266 $searchable_post_types = array();
267
268 $post_types = Features::factory()->get_registered_feature( 'search' )->get_searchable_post_types();
269 $post_types = array_filter(
270 $post_types,
271 function( $post_type ) {
272 return post_type_supports( $post_type, 'comments' );
273 }
274 );
275
276 foreach ( $post_types as $post_type ) {
277 $post_type_object = get_post_type_object( $post_type );
278 $post_type_labels = get_post_type_labels( $post_type_object );
279
280 $searchable_post_types[ $post_type ] = $post_type_labels->name;
281 }
282
283 return $searchable_post_types;
284 }
285
286 /**
287 * Enqueue frontend scripts.
288 *
289 * @since 4.4.0
290 */
291 public function frontend_scripts() {
292 wp_register_script(
293 'elasticpress-comments',
294 EP_URL . 'dist/js/comments-script.js',
295 Utils\get_asset_info( 'comments-script', 'dependencies' ),
296 Utils\get_asset_info( 'comments-script', 'version' ),
297 true
298 );
299
300 wp_set_script_translations( 'elasticpress-comments', 'elasticpress' );
301
302 wp_register_style(
303 'elasticpress-comments',
304 EP_URL . 'dist/css/comments-styles.css',
305 Utils\get_asset_info( 'comments-styles', 'dependencies' ),
306 Utils\get_asset_info( 'comments-styles', 'version' )
307 );
308
309 $default_script_data = [
310 'noResultsFoundText' => esc_html__( 'We could not find any results', 'elasticpress' ),
311 'minimumLengthToSearch' => 2,
312 'restApiEndpoint' => get_rest_url( null, 'elasticpress/v1/comments' ),
313 ];
314
315 /**
316 * Filter the l10n data attached to the Widget Search Comments script
317 *
318 * @since 3.6.0
319 * @hook ep_comment_search_widget_l10n_data_script
320 * @param {array} $default_script_data Default data attached to the script
321 * @return {array} New l10n data to be attached
322 */
323 $script_data = apply_filters( 'ep_comment_search_widget_l10n_data_script', $default_script_data );
324
325 wp_localize_script(
326 'elasticpress-comments',
327 'epc',
328 $script_data
329 );
330 }
331
332 /**
333 * Register block.
334 *
335 * @since 4.4.0
336 */
337 public function register_block() {
338 /**
339 * Registering it here so translation works
340 *
341 * @see https://core.trac.wordpress.org/ticket/54797#comment:20
342 */
343 wp_register_script(
344 'elasticpress-comments-editor-script',
345 EP_URL . 'dist/js/comments-block-script.js',
346 Utils\get_asset_info( 'comments-block-script', 'dependencies' ),
347 Utils\get_asset_info( 'comments-block-script', 'version' ),
348 true
349 );
350
351 wp_set_script_translations( 'elasticpress-comments-editor-script', 'elasticpress' );
352
353 wp_localize_script(
354 'elasticpress-comments-editor-script',
355 'epComments',
356 [
357 'searchablePostTypes' => self::get_searchable_post_types(),
358 ]
359 );
360
361 register_block_type_from_metadata(
362 EP_PATH . 'assets/js/blocks/comments',
363 [
364 'render_callback' => [ $this, 'render_block' ],
365 ]
366 );
367 }
368
369 /**
370 * Render block.
371 *
372 * @param array $attributes Block attributes
373 * @since 4.4.0
374 * @return string
375 */
376 public function render_block( $attributes ) {
377 $wrapper_id = 'ep-search-comments-' . uniqid();
378 $wrapper_attributes = get_block_wrapper_attributes(
379 array(
380 'id' => $wrapper_id,
381 'class' => 'ep-widget-search-comments',
382 )
383 );
384
385 $label = ! empty( $attributes['label'] )
386 ? sprintf(
387 '<label for="%1$s-s">%2$s</label>',
388 esc_attr( $wrapper_id ),
389 wp_kses_post( $attributes['label'] )
390 )
391 : '';
392
393 $post_types_input = ! empty( $attributes['postTypes'] )
394 ? sprintf(
395 '<input class="ep-widget-search-comments-post-type" type="hidden" id="%1$s-post-type" value="%2$s">',
396 esc_attr( $wrapper_id ),
397 esc_attr( implode( ',', $attributes['postTypes'] ) )
398 )
399 : '';
400
401 $block_html = sprintf(
402 '<div %1$s>%2$s%3$s</div>',
403 $wrapper_attributes, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
404 $label,
405 $post_types_input
406 );
407
408 return $block_html;
409 }
410
411 /**
412 * Hide the legacy widget.
413 *
414 * Hides the legacy widget in favor of the Block when the block editor
415 * is in use and the legacy widget has not been used.
416 *
417 * @since 4.4.0
418 * @param array $widgets An array of excluded widget-type IDs.
419 * @return array array of excluded widget-type IDs to hide.
420 */
421 public function hide_legacy_widget( $widgets ) {
422 $widgets[] = 'ep-comments';
423
424 return $widgets;
425 }
426 }
427