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
← All changes | app/Controllers/Hooks/ActionHooks.php +438 -4 2.0.2 → 3.4.0 View file →
@@ -6,12 +6,16 @@
6 6 */
7 7
8 8 namespace RadiusTheme\SB\Controllers\Hooks;
9 9
10 -use RadiusTheme\SB\Elementor\Render\Render;
11 10 use RadiusTheme\SB\Helpers\Fns;
11 +use RadiusTheme\SB\Helpers\Cache;
12 12 use RadiusTheme\SB\Models\GeneralList;
13 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;
14 18
15 19 defined( 'ABSPATH' ) || exit();
16 20
17 21 /**
@@ -23,8 +27,13 @@
23 27 *
24 28 * @return void
25 29 */
26 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
27 36 add_action( 'wp_head', [ __CLASS__, 'og_metatags_for_sharing' ], 1 );
28 37 add_action( 'woocommerce_share', [ __CLASS__, 'shopbuilder_share' ], 20 );
29 38 add_action( 'rtsb/wcqv/product/summary', [ __CLASS__, 'shopbuilder_share' ], 40 );
30 39 add_action( 'rtsb/shop/product/image', [ __CLASS__, 'render_image' ], 10, 2 );
@@ -34,11 +43,236 @@
34 43 function () {
35 44 remove_post_type_support( BuilderFns::$post_type_tb, 'revisions' );
36 45 }
37 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' ] );
38 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 + }
39 142
40 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 + /**
41 275 * Meta tags for social sharing.
42 276 *
43 277 * @return void
44 278 */
@@ -65,9 +299,11 @@
65 299 $settings['share_platforms'] = $share_platforms;
66 300 $settings['layout'] = ! empty( $generalList['social_share']['share_icon_layout'] ) ? $generalList['social_share']['share_icon_layout'] : 1;
67 301 $settings['show_share_icon'] = 1;
68 302
69 - // TODO:: Implement Later ! empty( $generalList['social_share']['share_icon_show_to_product_page'] ) && 'on' === $generalList['social_share']['share_icon_show_to_product_page'];
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 + */
70 306 Fns::print_html( Render::instance()->social_share_view( 'elementor/general/social-share', $settings ), true );
71 307 }
72 308
73 309 /**
@@ -104,13 +340,12 @@
104 340 /**
105 341 * Render image.
106 342 *
107 343 * @param array $args Image args.
108 - * @param array $settings Settings array.
109 344 *
110 345 * @return void
111 346 */
112 - public static function render_image( $args, $settings ) {
347 + public static function render_image( $args ) {
113 348 if ( $args['image_link'] ) {
114 349 $aria_label = esc_attr(
115 350 /* translators: Product Name */
116 351 sprintf( __( 'Image link for Product: %s', 'shopbuilder' ), $args['title'] )
@@ -128,6 +363,205 @@
128 363 echo '<figure class="rtsb-img-link">';
129 364 Fns::get_product_image( $args['img_html'], $args['hover_img_html'] );
130 365 echo '</figure>';
131 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();
132 566 }
133 567 }