| @@ -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 | } |