PluginProbe
ShopBuilder – WooCommerce Builder For Elementor / 3.4.0
ShopBuilder – WooCommerce Builder For Elementor v3.4.0
3.4.2 3.4.1 3.4.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 All 63 releases
shopbuilder / app / Controllers / Hooks / ActionHooks.php

ActionHooks.php in ShopBuilder – WooCommerce Builder For Elementor 3.4.0, at app/Controllers/Hooks/ActionHooks.php

568 lines 20.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Main ActionHooks class.
4 *
5 * @package RadiusTheme\SB
6 */
7
8 namespace RadiusTheme\SB\Controllers\Hooks;
9
10 use RadiusTheme\SB\Helpers\Fns;
11 use RadiusTheme\SB\Helpers\Cache;
12 use RadiusTheme\SB\Models\GeneralList;
13 use RadiusTheme\SB\Helpers\BuilderFns;
14 use RadiusTheme\SB\Models\TemplateSettings;
15 use RadiusTheme\SB\Elementor\Render\Render;
16 use RadiusTheme\SB\Elementor\Helper\RenderHelpers;
17 use RadiusTheme\SB\Modules\AbandonedCartRecovery\CartRecoveryCron;
18
19 defined( 'ABSPATH' ) || exit();
20
21 /**
22 * Main ActionHooks class.
23 */
24 class ActionHooks {
25 /**
26 * Init Hooks.
27 *
28 * @return void
29 */
30 public static function init_hooks() {
31 add_action( 'rtsb/before/save/options', [ __CLASS__, 'clear_cron_schedule' ], 10, 3 );
32 // Always register custom cron schedules so already-scheduled rtsb_* events
33 // can reschedule even when the Abandoned Cart Recovery module is inactive,
34 // preventing the "invalid_schedule" (Event schedule does not exist) error.
35 add_filter( 'cron_schedules', [ CartRecoveryCron::instance(), 'abandoned_cart_cron' ] ); // phpcs:ignore WordPress.WP.CronInterval.ChangeDetected
36 add_action( 'wp_head', [ __CLASS__, 'og_metatags_for_sharing' ], 1 );
37 add_action( 'woocommerce_share', [ __CLASS__, 'shopbuilder_share' ], 20 );
38 add_action( 'rtsb/wcqv/product/summary', [ __CLASS__, 'shopbuilder_share' ], 40 );
39 add_action( 'rtsb/shop/product/image', [ __CLASS__, 'render_image' ], 10, 2 );
40
41 add_action(
42 'admin_init',
43 function () {
44 remove_post_type_support( BuilderFns::$post_type_tb, 'revisions' );
45 }
46 );
47 add_action( 'deleted_post', [ __CLASS__, 'deleted_post' ], 10, 2 );
48 add_action( 'rtsb/elements/render/before_query', [ __CLASS__, 'modify_wc_query_args' ] );
49 add_action( 'rtsb/elements/render/after_query', [ __CLASS__, 'reset_wc_query_args' ] );
50 // Cart Table.
51 remove_action( 'woocommerce_cart_is_empty', 'wc_empty_cart_message', 10 );
52 add_action( 'woocommerce_cart_is_empty', [ __CLASS__, 'cart_is_empty' ], 10 );
53 /**
54 * Notices.
55 */
56 remove_action( 'woocommerce_cart_is_empty', 'woocommerce_output_all_notices', 5 );
57 remove_action( 'woocommerce_shortcode_before_product_cat_loop', 'woocommerce_output_all_notices', 10 );
58 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_output_all_notices', 10 );
59 remove_action( 'woocommerce_before_single_product', 'woocommerce_output_all_notices', 10 );
60 remove_action( 'woocommerce_before_cart', 'woocommerce_output_all_notices', 10 );
61 remove_action( 'woocommerce_before_checkout_form_cart_notices', 'woocommerce_output_all_notices', 10 );
62 remove_action( 'woocommerce_before_checkout_form', 'woocommerce_output_all_notices', 10 );
63 remove_action( 'woocommerce_account_content', 'woocommerce_output_all_notices', 5 );
64 remove_action( 'woocommerce_before_customer_login_form', 'woocommerce_output_all_notices', 10 );
65 remove_action( 'woocommerce_before_lost_password_form', 'woocommerce_output_all_notices', 10 );
66 remove_action( 'before_woocommerce_pay', 'woocommerce_output_all_notices', 10 );
67 remove_action( 'woocommerce_before_reset_password_form', 'woocommerce_output_all_notices', 10 );
68
69 /**
70 * Notices.
71 */
72 add_action( 'woocommerce_shortcode_before_product_cat_loop', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
73 add_action( 'woocommerce_before_shop_loop', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
74 add_action( 'woocommerce_before_single_product', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
75 add_action( 'woocommerce_before_cart', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
76 add_action( 'woocommerce_before_checkout_form_cart_notices', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
77 add_action( 'woocommerce_before_checkout_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
78 add_action( 'woocommerce_account_content', [ Fns::class, 'woocommerce_output_all_notices' ], 5 );
79 add_action( 'woocommerce_before_customer_login_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
80 add_action( 'woocommerce_before_lost_password_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
81 add_action( 'before_woocommerce_pay', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
82 add_action( 'woocommerce_before_reset_password_form', [ Fns::class, 'woocommerce_output_all_notices' ], 10 );
83
84 // Checkout Page.
85 remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_login_form', 10 );
86 remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
87 add_action( 'woocommerce_before_checkout_form', [ __CLASS__, 'woocommerce_checkout_login_form' ], 10 );
88 add_action( 'woocommerce_before_checkout_form', [ __CLASS__, 'woocommerce_checkout_coupon_form' ], 10 );
89 add_action( 'woocommerce_after_checkout_form', [ __CLASS__, 'postcode_validation_placeholder' ] );
90 // My Account Order Page.
91 add_action( 'woocommerce_before_account_orders', [ __CLASS__, 'before_account_orders' ], 10 );
92 add_action( 'woocommerce_after_account_orders', [ __CLASS__, 'after_account_orders' ], 10 );
93
94 // Product Filter Widget Hooks.
95 add_action( 'rtsb/before/archive/default/filter/items', [ __CLASS__,'default_filter_header' ], 10 );
96 add_action( 'rtsb/before/archive/default/filter/items', [ __CLASS__,'default_filter_search' ], 15 );
97
98 // WC Query modifier. Always registered so the free `rtsb-product-filters`
99 // widget's URL params (product_cat, product_tag, product_brand, rating_filter,
100 // sale_filter) are applied to the main WooCommerce product query regardless
101 // of whether the Pro add-on is active.
102 add_action( 'woocommerce_product_query', [ __CLASS__, 'query_modifier' ], 15 );
103
104 add_action( 'switch_theme', [ __CLASS__, 'clear_cache' ] );
105 }
106 /**
107 * Clear scheduled cron events when a module is deactivated.
108 *
109 * Checks the given block ID against predefined schedules and clears
110 * related cron hooks if the corresponding module is turned off.
111 *
112 * @param string $section_id Section identifier (not used in this function).
113 * @param string $block_id Module/block identifier to check scheduled hooks.
114 * @param array $rawOptions Module options array containing 'active' status.
115 *
116 * @return void
117 */
118 public static function clear_cron_schedule( $section_id, $block_id, $rawOptions ) {
119 $schedule = [
120 'abandoned_cart_recovery' => [
121 'rtsb_abandoned_cart_recovery_action',
122 'rtsb_send_abandoned_cart_emails',
123 ],
124 'currency_switcher' => [
125 'update_exchange_rates_hourly',
126 ],
127 ];
128 if ( ! isset( $schedule[ $block_id ] ) ) {
129 return;
130 }
131 if ( ! isset( $rawOptions['active'] ) ) {
132 return;
133 }
134 if ( 'on' === $rawOptions['active'] ) {
135 return;
136 }
137 // CLear All Custom Schedule If module disabled.
138 foreach ( $schedule[ $block_id ] as $hook ) {
139 wp_clear_scheduled_hook( $hook );
140 }
141 }
142
143 /**
144 * @param boolen $has_orders Order exist or not.
145 *
146 * @return void
147 */
148 public static function after_account_orders( $has_orders ) {
149 if ( ! $has_orders ) {
150 echo '</div>';
151 }
152 }
153
154 /**
155 * @param boolen $has_orders Order exist or not.
156 *
157 * @return void
158 */
159 public static function before_account_orders( $has_orders ) {
160 if ( ! $has_orders ) {
161 echo '<div class="rtsb-notice">';
162 }
163 }
164
165
166 /**
167 * Render postcode validation placeholder for fragment replacement.
168 *
169 * WooCommerce fragment replacement only targets existing DOM elements.
170 * This placeholder ensures the server-side validation flag can be
171 * injected via the update_order_review AJAX response.
172 *
173 * @return void
174 */
175 public static function postcode_validation_placeholder() {
176 echo '<div class="rtsb-postcode-invalid" style="display:none;"></div>';
177 }
178
179 /**
180 * @return void
181 */
182 public static function woocommerce_checkout_coupon_form() {
183 echo '<div class="rtsb-notice">';
184 woocommerce_checkout_coupon_form();
185 echo '</div>';
186 }
187
188 /**
189 * @return void
190 */
191 public static function woocommerce_checkout_login_form() {
192 echo '<div class="rtsb-notice">';
193 woocommerce_checkout_login_form();
194 echo '</div>';
195 }
196
197 /**
198 * @return void
199 */
200 public static function cart_is_empty() {
201 echo '<div class="rtsb-notice">';
202 wc_empty_cart_message();
203 echo '</div>';
204 }
205
206 /**
207 * @param int $post_id Post Ids.
208 * @param object $post Post Object.
209 *
210 * @return void
211 */
212 public static function deleted_post( $post_id, $post ) {
213 if ( BuilderFns::$post_type_tb !== $post->post_type ) {
214 return;
215 }
216
217 $options = BuilderFns::option_name_for_specific_product_set_default( $post_id );
218 TemplateSettings::instance()->delete_option( $options );
219
220 $template_options = BuilderFns::option_name_by_template_id( $post_id );
221 TemplateSettings::instance()->delete_option( $template_options );
222
223 $archive_options = BuilderFns::archive_option_name_by_template_id( $post_id );
224 TemplateSettings::instance()->delete_option( $archive_options );
225
226 $category_options = BuilderFns::option_name_for_specific_category_set_default( $post_id );
227 TemplateSettings::instance()->delete_option( $category_options );
228
229 $selected_category_options = BuilderFns::archive_option_name_by_template_id( $post_id );
230 TemplateSettings::instance()->delete_option( $selected_category_options );
231
232 // Delete Data From Options.
233 $options_product_selected_cat = BuilderFns::option_name_product_page_selected_cat( $post_id );
234 $cat_list = TemplateSettings::instance()->get_option( $options_product_selected_cat );
235 if ( ! empty( $cat_list ) ) {
236 foreach ( $cat_list as $old_slug ) {
237 $OldcatList = get_term_by( 'slug', $old_slug, 'product_cat' );
238 if ( ! empty( $OldcatList ) && ! is_wp_error( $OldcatList ) ) {
239 delete_term_meta( $OldcatList->term_id, BuilderFns::$categories_product_page_template, $post_id );
240 }
241 }
242 }
243 TemplateSettings::instance()->delete_option( $options_product_selected_cat );
244
245 $set_default_option = BuilderFns::option_name_product_page_specific_cat_set_default( $post_id );
246 TemplateSettings::instance()->delete_option( $set_default_option );
247
248 // Tags Remove.
249 $options_product_selected_tag = BuilderFns::option_name_product_page_selected_tag( $post_id );
250 $tag_list = TemplateSettings::instance()->get_option( $options_product_selected_tag );
251 if ( ! empty( $tag_list ) ) {
252 foreach ( $tag_list as $old_slug ) {
253 $OldTagList = get_term_by( 'slug', $old_slug, 'product_tag' );
254 if ( ! empty( $OldTagList ) && ! is_wp_error( $OldTagList ) ) {
255 delete_term_meta( $OldTagList->term_id, BuilderFns::$tags_product_page_template, $post_id );
256 }
257 }
258 }
259 TemplateSettings::instance()->delete_option( $options_product_selected_tag );
260
261 // Tag Set Default Option.
262 $tag_set_default_option = BuilderFns::option_name_product_page_specific_tag_set_default( $post_id );
263 TemplateSettings::instance()->delete_option( $tag_set_default_option );
264
265 global $wpdb;
266 // Prepare and execute the SQL query.
267 $sql = $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %d", BuilderFns::$view_template_for_products_meta, $post_id );
268 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
269
270 // Prepare and execute the SQL query.
271 $sql = $wpdb->prepare( "DELETE FROM $wpdb->termmeta WHERE meta_key = %s AND meta_value = %d", BuilderFns::$view_template_for_archive_meta, $post_id );
272 $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
273 }
274 /**
275 * Meta tags for social sharing.
276 *
277 * @return void
278 */
279 public static function shopbuilder_share() {
280 $generalList = GeneralList::instance()->get_data();
281
282 if (
283 empty( $generalList['social_share']['share_platforms_to_product_page'] ) ||
284 'on' !== $generalList['social_share']['share_platforms_to_product_page'] ||
285 empty( $generalList['social_share']['share_platforms'] )
286 ) {
287 return;
288 }
289
290 $share_platforms = [];
291
292 foreach ( $generalList['social_share']['share_platforms'] as $value ) {
293 $share_platforms[ $value ] = [
294 'share_items' => $value,
295 'share_text' => ucwords( $value ),
296 ];
297 }
298
299 $settings['share_platforms'] = $share_platforms;
300 $settings['layout'] = ! empty( $generalList['social_share']['share_icon_layout'] ) ? $generalList['social_share']['share_icon_layout'] : 1;
301 $settings['show_share_icon'] = 1;
302
303 /**
304 * Implement Later ! empty( $generalList['social_share']['share_icon_show_to_product_page'] ) && 'on' === $generalList['social_share']['share_icon_show_to_product_page'];
305 */
306 Fns::print_html( Render::instance()->social_share_view( 'elementor/general/social-share', $settings ), true );
307 }
308
309 /**
310 * Meta tags for social sharing.
311 *
312 * @return void
313 */
314 public static function og_metatags_for_sharing() {
315 global $post;
316
317 if ( ! isset( $post ) ) {
318 return;
319 }
320
321 if ( ! is_singular( 'product' ) ) {
322 return;
323 }
324
325 Fns::print_html( '<meta property="og:url" content="' . get_the_permalink() . '" />', true );
326 Fns::print_html( '<meta property="og:type" content="article" />', true );
327 Fns::print_html( '<meta property="og:title" content="' . $post->post_title . '" />', true );
328 Fns::print_html( '<meta property="og:description" content="' . wp_trim_words( $post->post_content, 150 ) . '" />' );
329
330 $attachment = get_the_post_thumbnail_url();
331
332 if ( ! empty( $attachment ) ) {
333 Fns::print_html( '<meta property="og:image" content="' . $attachment . '" />', true );
334 }
335
336 Fns::print_html( '<meta property="og:site_name" content="' . get_bloginfo( 'name' ) . '" />', true );
337 Fns::print_html( '<meta name="twitter:card" content="summary" />', true );
338 }
339
340 /**
341 * Render image.
342 *
343 * @param array $args Image args.
344 *
345 * @return void
346 */
347 public static function render_image( $args ) {
348 if ( $args['image_link'] ) {
349 $aria_label = esc_attr(
350 /* translators: Product Name */
351 sprintf( __( 'Image link for Product: %s', 'shopbuilder' ), $args['title'] )
352 );
353 ?>
354 <figure>
355 <a class="woocommerce-LoopProduct-link rtsb-img-link" href="<?php echo esc_url( $args['p_link'] ); ?>" aria-label="<?php echo esc_attr( $aria_label ); ?>">
356 <?php
357 Fns::get_product_image( $args['img_html'], $args['hover_img_html'] );
358 ?>
359 </a>
360 </figure>
361 <?php
362 } else {
363 echo '<figure class="rtsb-img-link">';
364 Fns::get_product_image( $args['img_html'], $args['hover_img_html'] );
365 echo '</figure>';
366 }
367 }
368
369 /**
370 * Modify WooCommerce query arguments for product retrieval.
371 *
372 * @param array $settings The settings array.
373 *
374 * @return void
375 */
376 public static function modify_wc_query_args( $settings ) {
377 if ( ( isset( $settings['tax_relation'] ) && 'OR' === $settings['tax_relation'] ) ||
378 ( isset( $settings['relation'] ) && 'OR' === $settings['relation'] ) ) {
379 add_filter( 'woocommerce_product_data_store_cpt_get_products_query', [ FilterHooks::class, 'extra_query_args_or' ], 10, 2 );
380 }
381 if ( ( isset( $settings['tax_relation'] ) && 'AND' === $settings['tax_relation'] ) ||
382 ( isset( $settings['relation'] ) && 'AND' === $settings['relation'] ) ) {
383 add_filter( 'woocommerce_product_data_store_cpt_get_products_query', [ FilterHooks::class, 'extra_query_args_and' ], 10, 2 );
384 }
385
386 if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
387 add_filter( 'woocommerce_product_data_store_cpt_get_products_query', [ FilterHooks::class, 'extra_query_args_outofstock' ] );
388 }
389 }
390
391 /**
392 * Reset WooCommerce query arguments for product retrieval.
393 *
394 * @param array $settings The settings array.
395 *
396 * @return void
397 */
398 public static function reset_wc_query_args( $settings ) {
399 if ( ( isset( $settings['tax_relation'] ) && 'OR' === $settings['tax_relation'] ) ||
400 ( isset( $settings['relation'] ) && 'OR' === $settings['relation'] ) ) {
401 remove_filter( 'woocommerce_product_data_store_cpt_get_products_query', [ FilterHooks::class, 'extra_query_args_or' ] );
402 }
403 if ( ( isset( $settings['tax_relation'] ) && 'AND' === $settings['tax_relation'] ) ||
404 ( isset( $settings['relation'] ) && 'AND' === $settings['relation'] ) ) {
405 remove_filter( 'woocommerce_product_data_store_cpt_get_products_query', [ FilterHooks::class, 'extra_query_args_and' ] );
406 }
407
408 if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
409 remove_filter( 'woocommerce_product_data_store_cpt_get_products_query', [ FilterHooks::class, 'extra_query_args_outofstock' ] );
410 }
411 }
412 /**
413 * Display a filter header.
414 *
415 * @param array $settings The settings.
416 *
417 * @return void
418 */
419 public static function default_filter_header( $settings ) {
420 if ( empty( $settings['show_filter_header'] ) && empty( $settings['filter_header_text'] ) ) {
421 return;
422 }
423
424 $wrapper_class = 'rtsb-default-filter-header ';
425
426 ?>
427
428 <div class="<?php echo esc_attr( $wrapper_class ); ?>">
429 <h3><?php echo esc_html( $settings['filter_header_text'] ); ?></h3>
430 </div>
431
432 <?php
433 }
434 /**
435 * Display a filter search form.
436 *
437 * @param array $settings The settings.
438 *
439 * @return void
440 */
441 public static function default_filter_search( $settings ) {
442 if ( empty( $settings['search_form'] ) ) {
443 return;
444 }
445
446 $title = [
447 'title' => ! empty( $settings['search_title'] ) ? $settings['search_title'] : '',
448 'show_icon' => ! empty( $settings['show_search_title_icon'] ),
449 'icon' => ! empty( $settings['filter_search_title_icon'] ) ? $settings['filter_search_title_icon'] : [],
450 ];
451 $placeholder = ! empty( $settings['search_placeholder'] ) ? $settings['search_placeholder'] : '';
452 $btn_icon = ! empty( $settings['search_title_icon'] ) ? $settings['search_title_icon'] : [];
453 $wrapper_class = 'rtsb-default-filter-search rtsb-default-product-search';
454 $unique_id = substr( uniqid(), -6 );
455 $search_term = isset( $_REQUEST['s'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
456 ?>
457
458 <div class="<?php echo esc_attr( $wrapper_class ); ?>">
459 <?php
460 Fns::print_html( RenderHelpers::get_default_filter_title( $title ) );
461 ?>
462 <div class="default-search-content">
463 <div class="woocommerce-product-search<?php echo ! empty( $search_term ) ? ' active' : ''; ?>">
464 <div class="search-input">
465 <label class="screen-reader-text" for="rtsb-product-default-search-form-<?php echo esc_attr( $unique_id ); ?>"><?php echo esc_html( $placeholder ); ?></label>
466 <input type="search" id="rtsb-product-default-search-form-<?php echo esc_attr( $unique_id ); ?>" class="rtsb-default-search-field" placeholder="<?php echo esc_html( $placeholder ); ?>" value="<?php echo esc_attr( $search_term ); ?>" name="s" autocomplete="off">
467 </div>
468 <button class="rtsb-search-submit">
469 <?php
470
471 Fns::print_html( Fns::icons_manager( $btn_icon, 'search-icon' ) );
472
473 ?>
474 <span></span>
475 </button>
476 </div>
477 </div>
478 </div>
479
480 <?php
481 }
482 /**
483 * Query modifier.
484 *
485 * @param object $query Query.
486 * @return object
487 */
488 public static function query_modifier( $query ) {
489 // phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
490
491 // Sale filter.
492 $onsale_filter = isset( $_GET['sale_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['sale_filter'] ) ) : '';
493 $on_sale_products = wc_get_product_ids_on_sale();
494
495 if ( 'onsale' === $onsale_filter ) {
496 $query->set( 'post__in', ! empty( $on_sale_products ) ? $on_sale_products : [ 0 ] );
497 } elseif ( 'regular' === $onsale_filter ) {
498 $query->set( 'post__not_in', $on_sale_products );
499 }
500
501 // Taxonomy filters (product_cat, product_tag, product_brand) from URL.
502 $tax_query = (array) $query->get( 'tax_query' );
503
504 $taxonomy_map = [
505 'product_cat' => 'product_cat',
506 'product_tag' => 'product_tag',
507 'product_brand' => 'product_brand',
508 ];
509
510 foreach ( $taxonomy_map as $param => $taxonomy ) {
511 if ( empty( $_GET[ $param ] ) || ! taxonomy_exists( $taxonomy ) ) {
512 continue;
513 }
514
515 $raw_values = wc_clean( wp_unslash( $_GET[ $param ] ) );
516 $slugs = array_filter( array_map( 'urldecode', explode( ',', $raw_values ) ) );
517
518 if ( empty( $slugs ) ) {
519 continue;
520 }
521
522 $tax_query[] = [
523 'taxonomy' => $taxonomy,
524 'field' => 'slug',
525 'terms' => $slugs,
526 'operator' => 'IN',
527 ];
528 }
529
530 // Rating filter (rating_filter=4,5).
531 if ( ! empty( $_GET['rating_filter'] ) ) {
532 $raw_ratings = wc_clean( wp_unslash( $_GET['rating_filter'] ) );
533 $ratings = array_filter( array_map( 'intval', explode( ',', $raw_ratings ) ) );
534
535 if ( ! empty( $ratings ) ) {
536 $rating_terms = [];
537 foreach ( $ratings as $rating ) {
538 $rating_terms[] = 'rated-' . $rating;
539 }
540
541 $tax_query[] = [
542 'taxonomy' => 'product_visibility',
543 'field' => 'name',
544 'terms' => $rating_terms,
545 'operator' => 'IN',
546 ];
547 }
548 }
549
550 if ( ! empty( $tax_query ) ) {
551 $query->set( 'tax_query', $tax_query );
552 }
553
554 // phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
555
556 return $query;
557 }
558
559 /**
560 * Delete cache when switching to another theme.
561 *
562 * @return void
563 */
564 public static function clear_cache() {
565 Cache::clear_all_cache();
566 }
567 }
568