PluginProbe
ElasticPress / 4.7.2
ElasticPress v4.7.2
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.7.2, at includes/classes/Feature/Comments/Comments.php

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