0 ) { add_action( 'plugins_loaded', array( $this, 'after_plugin_activation' ), 30 ); } add_action( 'admin_menu', array( $this, 'add_plugin_menu' ) ); add_filter( 'plugin_action_links_' . plugin_basename( A_W_F_PLUGIN_FILE ), array( $this, 'plugin_settings_link' ) ); add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 ); add_filter( 'woocommerce_get_settings_pages', array( $this, 'set_plugin_settings_tab' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ), 20 ); add_action( 'wp_ajax_awf_admin', array( $this, 'ajax_controller' ) ); add_action( 'before_delete_post', array( $this, 'on_product_deletion') ); add_action( 'wp_trash_post', array( $this, 'on_product_trashing') ); add_filter( 'untrashed_post', array( $this, 'on_product_untrashing') ); add_action( 'woocommerce_update_product', array( $this, 'on_product_update' ) ); add_action( 'created_product_cat', array( $this, 'on_product_cat_created' ), 10, 2 ); add_action( 'delete_product_cat', array( $this, 'on_product_cat_deleted' ), 10, 4 ); $this->filter_types = array( 'single' => array( 'label' => __( 'Single item selection', 'annasta-filters' ), 'styles' => array( 'radios', 'icons', 'labels', 'colours' ) ), 'multi' => array( 'label' => __( 'Multiple items selection', 'annasta-filters' ), 'styles' => array( 'checkboxes', 'icons', 'colours', 'tags' ) ), 'range' => array( 'label' => __( 'Range selection', 'annasta-filters' ), 'styles' => array( 'range-slider', 'radios', 'icons', 'labels', 'range-stars' ) ), ); $this->filter_styles = array( 'checkboxes' => __( 'System checkboxes', 'annasta-filters' ), 'radios' => __( 'System radio buttons', 'annasta-filters' ), 'range-slider' => __( 'Range slider', 'annasta-filters' ), 'range-stars' => __( 'Stars', 'annasta-filters' ), 'labels' => __( 'Labels', 'annasta-filters' ), 'icons' => __( 'Custom icons', 'annasta-filters' ), 'images' => __( 'Images', 'annasta-filters' ), 'colours' => __( 'Color boxes', 'annasta-filters' ), 'custom-terms' => __( 'Custom term icons and labels', 'annasta-filters' ), 'tags' => __( 'Tags', 'annasta-filters' ), ); $this->filter_style_limitations = array( 'taxonomy' => array( 'single' => array( 'radios', 'labels', 'icons', 'images', 'colours', 'custom-terms' ), 'multi' => array( 'checkboxes', 'icons', 'images', 'colours', 'tags', 'custom-terms' ), ), 'price' => array( 'range' => array( 'range-slider', 'radios', 'icons', 'labels', 'images', 'custom-terms' ) ), 'stock' => array( 'single' => array( 'radios', 'icons', 'labels', 'images', 'custom-terms' ) ), 'featured' => array( 'multi' => array( 'checkboxes', 'icons', 'labels', 'images', 'custom-terms' ) ), 'rating' => array( 'range' => array( 'radios', 'icons', 'labels', 'images', 'custom-terms' ) ), 'onsale' => array( 'multi' => array( 'checkboxes', 'icons', 'labels', 'images', 'custom-terms' ) ), 'ppp' => array( 'single' => array( 'radios', 'icons', 'labels', 'images' ) ), ); } public function add_plugin_menu() { add_menu_page( __( 'annasta Filters Settings', 'annasta-filters' ), __( 'annasta Filters', 'annasta-filters' ), 'manage_woocommerce', 'annasta-filters', array( $this, 'safe_redirect_to_presets_tab'), 'dashicons-filter', 56 ); add_submenu_page( 'annasta-filters', __( 'Settings', 'annasta-filters' ), __( 'Settings', 'annasta-filters' ), 'manage_woocommerce', 'annasta-filters', array( $this, 'safe_redirect_to_presets_tab') ); } public function after_plugin_activation() { if ( version_compare( PHP_VERSION, '5.4' ) < 0 ) { add_action( 'admin_notices', array( $this, 'display_php_version_warning' ) ); } else { // Run updates $this->generate_styles_css(); update_option( 'awf_version', A_W_F_VERSION ); } } public function display_php_version_warning() { echo '

', sprintf( esc_html__( 'annasta Woocommerce Product Filters requires PHP Version 5.4 or later to function. Your server currently runs PHP version %1$s. Please, install the newer version of PHP on your server for the plugin to function properly.', 'annasta-filters' ), PHP_VERSION ), '

'; } public function set_plugin_settings_tab( $tabs ) { $tabs[] = new A_W_F_settings(); return $tabs; } public function plugin_settings_link( $links ) { $settings_link = '' . esc_html__( 'Settings', 'annasta-filters' ) . ''; array_unshift( $links, $settings_link ); return $links; } public function plugin_row_meta( $links, $file ) { if ( strpos( $file, 'annasta-woocommerce-product-filters.php' ) !== false ) { $new_links = array( 'documentation' => '' . esc_html__( 'Documentation', 'annasta-filters' ) . '' ); $links = array_merge( $links, $new_links ); } return $links; } public function redirect_to_presets_tab( $args = array() ) { $redirect_url = add_query_arg( $args, admin_url( 'admin.php?page=wc-settings&tab=annasta-filters' ) ); wp_redirect( $redirect_url ); exit(); } public function safe_redirect_to_presets_tab() { $redirect_url = admin_url( 'admin.php?page=wc-settings&tab=annasta-filters' ); wp_safe_redirect( $redirect_url ); exit(); } public function enqueue_admin_scripts( $hook ) { if( isset( $_GET['tab'] ) && 'annasta-filters' === $_GET['tab'] ) { if( isset( $_GET['awf-preset'] ) ) { wp_enqueue_style( 'wp-color-picker' ); wp_enqueue_style( 'awf-nouislider-styles', A_W_F_PLUGIN_URL . '/styles/nouislider.min.css', array() ); wp_enqueue_script( 'awf-nouislider', A_W_F_PLUGIN_URL . '/code/js/nouislider.min.js', array() ); } wp_enqueue_style( 'awf-styles', A_W_F_PLUGIN_URL . '/styles/awf-admin.css', false, A_W_F::$plugin_version ); wp_enqueue_style( 'awf-fontawesome', A_W_F_PLUGIN_URL . '/styles/fontawesome-all.min.css', array() ); wp_enqueue_script( 'awf-admin', A_W_F_PLUGIN_URL . '/code/js/awf-admin.js', array( 'jquery', 'wp-color-picker', 'jquery-ui-sortable' ), A_W_F::$plugin_version ); // @ToDo delete after WC v3.7 if( version_compare( WC_VERSION, '3.6', '>=' ) && version_compare( WC_VERSION, '3.6.3', '<' ) ) { wp_enqueue_style( 'awf-select2-fix', A_W_F_PLUGIN_URL . '/styles/awf-select2-fix.css', false, A_W_F::$plugin_version ); } wp_localize_script( 'awf-admin', 'awf_js_data', array( 'awf_ajax_referer' => wp_create_nonce( 'awf_ajax_nonce' ) ) ); } } public function ajax_controller() { check_ajax_referer( 'awf_ajax_nonce', 'awf_ajax_referer', true ); if ( ! current_user_can( 'manage_woocommerce' ) ) die( __( 'Error: permission denied.', 'annasta-filters' ) ); if( 'update_presets_positions' === $_POST['awf_action'] ) { $this->update_presets_positions(); } elseif( isset( $_POST['awf_preset'] ) ) { $preset_id = (int) $_POST['awf_preset']; if( ! isset( A_W_F::$presets[$preset_id] ) ) die( __( 'Error: preset doesn\'t exist', 'annasta-filters' ) ); if( 'add-preset-association' === $_POST['awf_action'] ) { $this->add_preset_association( $preset_id ); } else if( 'delete-preset-association' === $_POST['awf_action'] ) { $this->delete_preset_association( $preset_id ); } else { if( 'add-filter' === $_POST['awf_action'] ) { $this->add_filter( $preset_id, sanitize_text_field( $_POST['awf_filter'] ) ); } elseif( 'update_filters_positions' === $_POST['awf_action'] ) { $this->update_positions( $preset_id ); } if( isset( $_POST['awf_filter'] ) ) { $filter_id = (int) $_POST['awf_filter']; if( ! isset( A_W_F::$presets[$preset_id]['filters'][$filter_id] ) ) die( __( 'Error: filter doesn\'t exist', 'annasta-filters' ) ); $filter = new A_W_F_filter( $preset_id, $filter_id ); if( 'delete-filter' === $_POST['awf_action'] ) { echo $this->delete_filter( $filter ); } elseif( 'rebuild-styles' === $_POST['awf_action'] ) { echo $this->build_style_options( $filter, sanitize_key( $_POST['awf_filter_type'] ) ); } else if( 'rebuild-style-options' === $_POST['awf_action'] ) { echo $this->get_style_options_html( $filter, sanitize_key( $_POST['awf_filter_style'] ) ); } else if( 'rebuild-range-type-options' === $_POST['awf_action'] ) { $filter->settings['type'] = 'range'; if( 'taxonomy' === $filter->module ) { $filter->settings['type_options']['range_type'] = 'taxonomy_range'; } else { $filter->settings['type_options']['range_type'] = sanitize_key( $_POST['awf_filter_range_type'] ); } $this->display_range_type( $filter ); } else if( 'add-custom-range-value' === $_POST['awf_action'] ) { $this->add_custom_range_value( $filter, floatval( $_POST['awf_new_range_value'] ) ); } else if( 'delete-custom-range-value' === $_POST['awf_action'] ) { $this->delete_custom_range_value( $filter, floatval( $_POST['awf_delete_range_value'] ) ); } else if( 'exclude-filter-item' === $_POST['awf_action'] ) { $this->exclude_filter_term( $filter, intval( $_POST['awf_exclude_item'] ) ); echo $this->build_excluded_terms( $filter ); } else if( 'remove-from-excluded' === $_POST['awf_action'] ) { $this->remove_from_excluded( $filter, intval( $_POST['awf_remove_from_excluded'] ) ); echo $this->build_excluded_terms( $filter ); } else if( 'add-ppp-value' === $_POST['awf_action'] ) { $this->add_ppp_value( $filter ); } else if( 'remove-ppp-value' === $_POST['awf_action'] ) { $this->remove_ppp_value( $filter ); } else { if( method_exists( $this, 'premium_ajax_controller' ) ) { $this->premium_ajax_controller( $filter ); } } } } } wp_die(); } private function update_presets_positions() { $positions = ( isset( $_POST['awf_presets_positions'] ) && is_array( $_POST['awf_presets_positions'] ) ) ? array_map( 'intval', $_POST['awf_presets_positions'] ) : array(); $new_positions = array_flip( $positions ); $check_ids = array_diff_key( $new_positions, A_W_F::$presets ); if( count( $check_ids ) === 0 ) { foreach( $new_positions as $preset_id => $position ) { $position = absint( sanitize_key( $position ) ) + 1; A_W_F::$presets[intval( $preset_id )]['position'] = $position; } uasort( A_W_F::$presets, function( $a, $b ) { return $a['position'] - $b['position']; }); update_option( 'awf_presets', A_W_F::$presets ); } else { die( __( 'An error occured when updating presets positions.', 'annasta-filters' ) ); } } private function add_preset_association( $preset_id ) { $association_id = sanitize_text_field( $_POST['awf_association'] ); if( ! in_array( $association_id, A_W_F::$presets[$preset_id]['associations'] ) ) { $taxonomies = get_object_taxonomies( 'product', 'names' ); $taxonomies = array_diff( $taxonomies, A_W_F::$excluded_taxonomies ); if( ! in_array( $association_id, array( 'all', 'shop-pages', 'cat-pages' ) ) ) { $invalid_id = true; if ( 0 === strpos( $association_id, 'wp_page--' ) ) { $assoc_data = explode( '--', $association_id ); $wp_pages = get_all_page_ids(); $wp_pages = array_diff( $wp_pages, array( wc_get_page_id( 'shop' ) ) ); if( in_array( $assoc_data[1], $wp_pages ) ) { $invalid_id = false; } } else { foreach( $taxonomies as $t ) { if ( 0 === strpos( $association_id, $t . '--' ) ) { $assoc_data = explode( '--', $association_id ); $terms = get_terms( array( 'taxonomy' => $t->name, 'fields' => 'slugs', 'hide_empty' => false ) ); if( in_array( $assoc_data[1], $terms ) ) { $invalid_id = false; break; } } } } if( $invalid_id ) { die( 'ERROR: ' . esc_html__( 'Request couldn\'t be completed: invalid association id.', 'annasta-filters' ) ); } } if( 'all' === $association_id ) { A_W_F::$presets[$preset_id]['associations'] = array(); } elseif( 'shop-pages' === $association_id ) { if( false !== ( $key = array_search( 'cat-pages', A_W_F::$presets[$preset_id]['associations'] ) ) ) { unset( A_W_F::$presets[$preset_id]['associations'][$key] ); } foreach( A_W_F::$presets[$preset_id]['associations'] as $key => $aid ) { $tax_data = explode( '--', $aid ); if( count( $tax_data ) === 2 && 'wp_page--' !== $tax_data[0] ) { if( in_array( $tax_data[0], $taxonomies ) ) { unset( A_W_F::$presets[$preset_id]['associations'][$key] ); } } } } elseif( 'cat-pages' === $association_id ) { foreach( A_W_F::$presets[$preset_id]['associations'] as $key => $aid ) { if( 0 === strpos( $aid, 'product_cat--' ) ) { unset( A_W_F::$presets[$preset_id]['associations'][$key] ); } } } A_W_F::$presets[$preset_id]['associations'][] = $association_id; update_option( 'awf_presets', A_W_F::$presets ); $this->display_associations( $preset_id ); } else { die( __( 'Error completing request: wrong preset or association.', 'annasta-filters' ) ); } } private function delete_preset_association( $preset_id ) { $association_id = sanitize_text_field( $_POST['awf_association'] ); if ( ( $key = array_search( $association_id, A_W_F::$presets[$preset_id]['associations'] ) ) !== false ) { unset( A_W_F::$presets[$preset_id]['associations'][$key] ); update_option( 'awf_presets', A_W_F::$presets ); $this->display_associations( $preset_id ); } else { echo( 'ERROR: ' . esc_html__( 'Request couldn\'t be completed: wrong preset or association.', 'annasta-filters' ) ); } } private function add_filter( $preset_id, $filter_name ) { $filter_data = array(); $filter; $settings; if( 0 === strpos( $filter_name, 'taxonomy--' ) ) { $filter_name_data = explode( '--', $filter_name ); $taxonomy = array_pop( $filter_name_data ); $allowed_taxonomies = get_object_taxonomies( 'product', 'names' ); $allowed_taxonomies = array_diff( $allowed_taxonomies, A_W_F::$excluded_taxonomies ); if( in_array( $taxonomy, $allowed_taxonomies ) ) { $filter_data['module'] = 'taxonomy'; $filter_data['taxonomy'] = get_taxonomy( $taxonomy ); } } else { $filter_data['module'] = $filter_name; $filter_data['title'] = $this->get_filter_title( $filter_name ); } if( ! in_array( $filter_data['module'], A_W_F::$modules ) || ! isset( A_W_F::$presets[$preset_id] ) ) { die( 'ERROR: ' . esc_html__( 'Error creating filter: invalid preset, filter, or taxonomy.', 'annasta-filters' ) ); } A_W_F::$presets[$preset_id]['filters'][] = count( A_W_F::$presets[$preset_id]['filters'] ); end( A_W_F::$presets[$preset_id]['filters'] ); $new_filter_id = key( A_W_F::$presets[$preset_id]['filters'] ); update_option( 'awf_presets', A_W_F::$presets ); $prefix = A_W_F_filter::get_prefix( $preset_id, $new_filter_id ); $settings = $this->get_module_defaults( $filter_data ); update_option( $prefix . 'name', $filter_name ); update_option( $prefix . 'module', $filter_data['module'] ); update_option( $prefix . 'settings', $settings ); $filter = new A_W_F_filter( $preset_id, $new_filter_id ); include( A_W_F_PLUGIN_PATH . 'templates/admin/filter.php' ); } public function delete_filter( $filter ) { if( wp_doing_ajax() ) { if( isset( A_W_F::$presets[$filter->preset_id]['filters'][$filter->id] ) ) { $ajax_response['option_value'] = $filter->name; if( 'taxonomy' === $filter->module ) { if( $taxonomy = get_taxonomy( $filter->settings['taxonomy'] ) ) { $ajax_response['option_label'] = $taxonomy->label; } if( ! empty( $filter->settings['show_count'] ) || ( isset( $filter->settings['hide_empty'] ) && 'none' !== $filter->settings['hide_empty'] ) ) { $this->clear_product_counts_cache(); } } else { $ajax_response['option_label'] = $this->get_filter_title( $ajax_response['option_value'] ); } unset( A_W_F::$presets[$filter->preset_id]['filters'][$filter->id] ); if( ! empty( A_W_F::$presets[$filter->preset_id]['filters'] ) ) { asort( A_W_F::$presets[$filter->preset_id]['filters'], SORT_NUMERIC ); A_W_F::$presets[$filter->preset_id]['filters'] = array_flip( A_W_F::$presets[$filter->preset_id]['filters'] ); A_W_F::$presets[$filter->preset_id]['filters'] = array_values( A_W_F::$presets[$filter->preset_id]['filters'] ); A_W_F::$presets[$filter->preset_id]['filters'] = array_flip( A_W_F::$presets[$filter->preset_id]['filters'] ); } update_option( 'awf_presets', A_W_F::$presets ); } else { $ajax_response['error'] = sprintf( __( 'Error: a problem occured while deleting filter %1$s.', 'annasta-filters' ), $filter->preset_id . '-' . $filter->id ); return $ajax_response; } } delete_option( $filter->prefix . 'name' ); delete_option( $filter->prefix . 'module' ); delete_option( $filter->prefix . 'settings' ); return json_encode( $ajax_response ); } private function update_positions( $preset_id ) { $positions = isset( $_POST['awf_filters_positions'] ) && is_array( $_POST['awf_filters_positions'] ) ? array_map( 'intval', $_POST['awf_filters_positions'] ) : array(); $filters = array(); foreach( $positions as $position => $filter_id ) { $filters[$filter_id] = (int) $position; } $check_ids = array_diff( $filters, A_W_F::$presets[$preset_id]['filters'] ); if( count( $check_ids ) === 0 ) { A_W_F::$presets[$preset_id]['filters'] = $filters; update_option( 'awf_presets', A_W_F::$presets ); } else { die( __( 'An error occured when updating filters\' positions.', 'annasta-filters' ) ); } } public function update_filter( $filter ) { $old_settings = $filter->settings; $filter->settings['style_options'] = array(); $response = array(); foreach( $filter->settings as $setting => $value ) { if( is_null( $value ) ) { continue; } switch( $setting ) { case 'title': $filter->settings[$setting] = sanitize_text_field( $_POST[$filter->prefix . $setting] ); break; case 'type': case 'style': $filter->settings[$setting] = sanitize_key( $_POST[$filter->prefix . $setting] ); break; case 'show_title': case 'show_active': case 'reset_all': case 'is_dropdown': case 'children_collapsible': case 'children_collapsible_on': case 'show_search': $filter->settings[$setting] = $this->get_sanitized_checkbox_setting( $filter, $setting ); break; case 'show_in_row': $filter->settings[$setting] = $this->get_sanitized_checkbox_setting( $filter, $setting ); if( $old_settings[$setting] !== $filter->settings[$setting] ) { $response['generate_styles_css'] = true; } break; case 'show_count': $filter->settings[$setting] = $this->get_sanitized_checkbox_setting( $filter, $setting ); if( $filter->settings[$setting] !== $value ) { $response['clear_counts_cache'] = true; } break; case 'hide_empty': $filter->settings[$setting] = sanitize_key( $_POST[$filter->prefix . $setting] ); break; if( $filter->settings[$setting] !== $value ) { $response['clear_counts_cache'] = true; } case 'height_limit': $filter->settings[$setting] = (int) $_POST[$filter->prefix . $setting]; if( $old_settings[$setting] !== $filter->settings[$setting] ) { $response['generate_styles_css'] = true; } break; case 'sort_by': case 'sort_order': $filter->settings[$setting] = sanitize_key( $_POST[$filter->prefix . $setting] ); break; default: break; } } if( 'range' === $filter->settings['type'] ) { $filter->settings['type_options']['range_type'] = sanitize_key( $_POST[$filter->prefix . 'range_type'] ); if( 'auto_range' === $filter->settings['type_options']['range_type'] || 'custom_range' === $filter->settings['type_options']['range_type'] ) { $filter->settings['type_options']['precision'] = round( floatval( $_POST[$filter->prefix . 'precision'] ), 2, PHP_ROUND_HALF_UP ); $filter->settings['type_options']['decimals'] = absint( $_POST[$filter->prefix . 'decimals'] ); if( 2 < $filter->settings['type_options']['decimals'] ) { $filter->settings['type_options']['decimals'] = 2; } $filter->settings['style_options']['value_prefix'] = sanitize_text_field( $_POST[$filter->prefix . 'value_prefix'] ); $filter->settings['style_options']['value_postfix'] = sanitize_text_field( $_POST[$filter->prefix . 'value_postfix'] ); } if( 'auto_range' === $filter->settings['type_options']['range_type'] ) { $range_min = round( floatval( $_POST[$filter->prefix . 'range_min'] ), 2, PHP_ROUND_HALF_UP ); $range_max = round( floatval( $_POST[$filter->prefix . 'range_max'] ), 2, PHP_ROUND_HALF_UP ); if( $range_min === $range_max ) { $range_max += 1; } elseif( $range_min > $range_max ) { $temp = $range_max; $range_max = $range_min; $range_min = $temp; } $range_segments = (int) $_POST[$filter->prefix . 'range_segments']; if( $range_segments < 1 ) { $range_segments = 1; } $increment = ( $range_max - $range_min ) / $range_segments; $increment = round( $increment, 2, PHP_ROUND_HALF_UP ); $filter->settings['type_options']['range_values'] = array(); for( $v = $range_min; $v < $range_max; $v += $increment ) { $filter->settings['type_options']['range_values'][] = round( $v, 2, PHP_ROUND_HALF_UP ); } while( count( $filter->settings['type_options']['range_values'] ) > $range_segments ) { array_pop( $filter->settings['type_options']['range_values'] ); } $filter->settings['type_options']['range_values'][] = $range_max; } elseif( 'custom_range' === $filter->settings['type_options']['range_type'] ) { $filter->settings['type_options']['range_values'] = $old_settings['type_options']['range_values']; } } if( 'icons' === $filter->settings['style'] ) { $filter->settings['style_options']['icons'][] = sanitize_text_field( $_POST[$filter->prefix . 'unselected_icon'] ); $filter->settings['style_options']['solid'][] = isset( $_POST[$filter->prefix . 'unselected_icon_solid'] ) && 'yes' === sanitize_key( $_POST[$filter->prefix . 'unselected_icon_solid'] ) ? 'awf-solid' : ''; $filter->settings['style_options']['icons'][] = sanitize_text_field( $_POST[$filter->prefix . 'unselected_icon_hover'] ); $filter->settings['style_options']['solid'][] = isset( $_POST[$filter->prefix . 'unselected_icon_hover_solid'] ) && 'yes' === sanitize_key( $_POST[$filter->prefix . 'unselected_icon_hover_solid'] ) ? 'awf-solid' : ''; $filter->settings['style_options']['icons'][] = sanitize_text_field( $_POST[$filter->prefix . 'selected_icon'] ); $filter->settings['style_options']['solid'][] = isset( $_POST[$filter->prefix . 'selected_icon_solid'] ) && 'yes' === sanitize_key( $_POST[$filter->prefix . 'selected_icon_solid'] ) ? 'awf-solid' : ''; $filter->settings['style_options']['icons'][] = sanitize_text_field( $_POST[$filter->prefix . 'selected_icon_hover'] ); $filter->settings['style_options']['solid'][] = isset( $_POST[$filter->prefix . 'selected_icon_hover_solid'] ) && 'yes' === sanitize_key( $_POST[$filter->prefix . 'selected_icon_hover_solid'] ) ? 'awf-solid' : ''; if( $old_settings['style_options'] !== $filter->settings['style_options'] ) { $response['generate_styles_css'] = true; } } elseif( 'range-slider' === $filter->settings['style'] ) { if( isset( $old_settings->settings['children_collapsible'] ) ) { $filter->settings['children_collapsible'] = $filter->settings['children_collapsible_on'] = false; } if( isset( $old_settings->settings['show_in_row'] ) ) { $filter->settings['show_in_row'] = false; } if( isset( $old_settings->settings['show_search'] ) ) { $filter->settings['show_search'] = false; } $filter->settings['height_limit'] = (int) 0; $response['generate_styles_css'] = true; if( 'auto_range' === $filter->settings['type_options']['range_type'] || 'custom_range' === $filter->settings['type_options']['range_type'] ) { $filter->settings['style_options']['step'] = empty( $_POST[$filter->prefix . 'step'] ) ? floatval( 1 ) : (float) $_POST[$filter->prefix . 'step']; } $filter->settings['style_options']['show_range_btn'] = $this->get_sanitized_checkbox_setting( $filter, 'show_range_btn' ); $filter->settings['style_options']['badge_label'] = isset( $_POST[$filter->prefix . 'badge_label'] ) ? sanitize_text_field( $_POST[$filter->prefix . 'badge_label'] ) : ''; } elseif( 'colours' === $filter->settings['style'] ) { if( ! isset( $_POST[$filter->prefix . 'show_label'] ) ) { $filter->settings['style_options']['hide_label'] = true; } $filter_terms = $filter->get_filter_terms( false ); $filter->settings['style_options']['colours'] = array(); foreach( $filter_terms as $mt ) { if( in_array( $mt->term_id, $filter->settings['excluded_items'] ) ) continue; if( isset( $_POST[$filter->prefix . 'term_' . $mt->term_id . '_colour'] ) ) { $filter->settings['style_options']['colours'][$mt->term_id] = sanitize_text_field( $_POST[$filter->prefix . 'term_' . $mt->term_id . '_colour'] ); } } if( $old_settings['style_options'] !== $filter->settings['style_options'] ) { $response['generate_styles_css'] = true; } } if( method_exists( $this, 'update_premium_filter' ) ) { $this->update_premium_filter( $filter, $old_settings, $response ); } update_option( $filter->prefix. 'settings', $filter->settings ); return( $response ); } protected function add_custom_range_value( $filter, $new_value ) { if( 'custom_range' !== $filter->settings['type_options']['range_type'] ) { die( 'WARNING: ' . esc_html__( 'Please save preset before adding or deleting values of the range.', 'annasta-filters' ) ); } if( isset( $filter->settings['type_options']['range_values'] ) && ! in_array( $new_value, $filter->settings['type_options']['range_values'] ) ) { $filter->settings['type_options']['range_values'][] = $new_value; asort( $filter->settings['type_options']['range_values'], SORT_NUMERIC ); $filter->settings['type_options']['range_values'] = array_values( $filter->settings['type_options']['range_values'] ); update_option( $filter->prefix. 'settings', $filter->settings ); } $this->display_range_type( $filter ); } protected function delete_custom_range_value( $filter, $value ) { if( ! isset( $filter->settings['type_options']['range_values'] ) || count( $filter->settings['type_options']['range_values'] ) < 3 ) { die( esc_html__( 'This range value can not be deleted, because a range needs at least 2 values to work. If you want to change this value, first add the new value, and then delete the unneeded one.', 'annasta-filters' ) ); } if( 'custom_range' !== $filter->settings['type_options']['range_type'] ) { die( esc_html__( 'Please save preset before adding or deleting values of the range.', 'annasta-filters' ) ); } if( false !== ( $key = array_search( $value, $filter->settings['type_options']['range_values'] ) ) ) { unset( $filter->settings['type_options']['range_values'][$key] ); $filter->settings['type_options']['range_values'] = array_values( $filter->settings['type_options']['range_values'] ); update_option( $filter->prefix. 'settings', $filter->settings ); } } public function exclude_filter_term( $filter, $term_id ) { $all_items = $filter->get_filter_terms( false ); $all_items_ids = wp_list_pluck( $all_items, 'term_id' ); if( in_array( $term_id, $all_items_ids ) && ! in_array( $term_id, $filter->settings['excluded_items'] ) ) { $filter->settings['excluded_items'][] = $term_id; update_option( $filter->prefix. 'settings', $filter->settings ); } } public function remove_from_excluded( $filter, $term_id ) { if( in_array( $term_id, $filter->settings['excluded_items'] ) ) { $filter->settings['excluded_items'] = array_diff( $filter->settings['excluded_items'], array( $term_id ) ); $filter->settings['excluded_items'] = array_values( $filter->settings['excluded_items'] ); update_option( $filter->prefix. 'settings', $filter->settings ); } } public function add_ppp_value( $filter ) { $value = (int) $_POST['awf_add_ppp_value']; $filter->settings['ppp_values'][$value] = mb_strimwidth( sanitize_text_field( $_POST['awf_add_ppp_label'] ), 0, 100, '...' ); ksort( $filter->settings['ppp_values'] ); update_option( $filter->prefix. 'settings', $filter->settings ); echo $this->build_ppp_values_list( $filter, intval( get_option( 'awf_ppp_default', 0 ) ) ); } public function remove_ppp_value( $filter ) { $value = (int) $_POST['awf_remove_ppp_value']; unset( $filter->settings['ppp_values'][$value] ); update_option( $filter->prefix. 'settings', $filter->settings ); } public function build_associations_lists() { $associations_by_preset = array(); foreach( A_W_F::$presets as $preset_id => $preset ) { $preset_associations = array(); foreach( $preset['associations'] as $association_id ) { if( $association_id === 'all' ) { $preset_associations[] = __( 'All pages', 'annasta-filters' ); } else if( $association_id === 'shop-pages' ) { $preset_associations[] = __( 'Shop pages', 'annasta-filters' ); } else if( $association_id === 'cat-pages' ) { $preset_associations[] = __( 'Product categories pages', 'annasta-filters' ); } else if( 0 === strpos( $association_id, 'wp_page--' ) ) { $page_id = (int) substr( $association_id, strlen( 'wp_page--' ) ); $preset_associations[] = get_the_title( $page_id ); } else if( false !== strpos( $association_id, '--' ) ) { $association_data = explode( '--', $association_id ); $association_term = get_term_by( 'slug', $association_data[1], $association_data[0] ); $association_taxonomy = get_taxonomy( $association_data[0] ); if( is_object( $association_term ) && is_object( $association_taxonomy ) ) { $preset_associations['taxonomies'][$association_taxonomy->label][] = $association_term->name; } } } if( isset( $preset_associations['taxonomies'] ) ) { foreach( $preset_associations['taxonomies'] as $tax => $terms ) { $preset_associations[] = $tax . ' > ' . implode( ', ', $terms ); } unset( $preset_associations['taxonomies'] ); } $associations_by_preset[$preset_id] = implode( ', ', $preset_associations ); } return $associations_by_preset; } public function display_associations( $preset_id ) { $preset_associations = array(); $associations_select = array(); if( in_array( 'all', A_W_F::$presets[$preset_id]['associations'] ) ) { $preset_associations['all'] = __( 'All pages', 'annasta-filters' ); } else { $associations_select['all'] = __( 'All pages', 'annasta-filters' ); if( in_array( 'shop-pages', A_W_F::$presets[$preset_id]['associations'] ) ) { $preset_associations['shop-pages'] = __( 'Shop pages', 'annasta-filters' ); } else { $associations_select['shop-pages'] = __( 'Shop pages', 'annasta-filters' ); if( in_array( 'cat-pages', A_W_F::$presets[$preset_id]['associations'] ) ) { $preset_associations['cat-pages'] = __( 'Product categories pages', 'annasta-filters' ); } else { $associations_select['cat-pages'] = __( 'Product categories pages', 'annasta-filters' ); } $taxonomies = get_object_taxonomies( 'product', 'objects' ); foreach( $taxonomies as $t ) { if( in_array( $t->name, A_W_F::$excluded_taxonomies ) ) continue; $terms = get_terms( array( 'taxonomy' => $t->name, 'parent' => 0, 'hide_empty' => false, 'orderby' => 'name' ) ); if( ! ( 'product_cat' === $t->name && in_array( 'cat-pages', A_W_F::$presets[$preset_id]['associations'] ) ) ) { $associations_select += $this->build_associations_taxonomy_terms( $preset_id, $terms, $t->label, $preset_associations ); } } } $wp_pages = get_all_page_ids(); $wp_pages = array_diff( $wp_pages, array( wc_get_page_id( 'shop' ) ) ); foreach( $wp_pages as $page_id ) { $association_id = 'wp_page--' . $page_id; if( in_array( $association_id, A_W_F::$presets[$preset_id]['associations'] ) ) { $preset_associations[$association_id] = __( 'WP page: ', 'annasta-filters' ) . get_the_title( $page_id ); } else { $associations_select[$association_id] = __( 'WP page: ', 'annasta-filters' ) . get_the_title( $page_id ); } } } include( A_W_F_PLUGIN_PATH . 'templates/admin/preset-associations.php' ); } private function build_associations_taxonomy_terms( $preset_id, $terms, $label = '', &$preset_associations, $indentation = 0 ) { $options = array(); foreach( $terms as $term ) { $association_id = $term->taxonomy . '--' . $term->slug; if( in_array( $association_id, A_W_F::$presets[$preset_id]['associations'] ) ) { $preset_associations[$association_id] = $label . ' > ' . $term->name; } else { $options[$association_id] = str_repeat( ' ', $indentation ) . $label . ' > ' . $term->name; } if( is_taxonomy_hierarchical( $term->taxonomy ) ) { $child_terms = get_terms( array( 'taxonomy' => $term->taxonomy, 'parent' => $term->term_id, 'hide_empty' => false, 'orderby' => 'name' ) ); if(! empty( $child_terms ) ) { $children = $this->build_associations_taxonomy_terms( $preset_id, $child_terms, $label . ' > ' . $term->name, $preset_associations, $indentation + 2 ); $options += $children; } } } return $options; } public function display_overrides( $preset_id ) {} public function build_type_select( $filter ) { $html = ''; return $html; } public function display_range_type( $filter ) { ob_start(); require( A_W_F_PLUGIN_PATH . 'templates/admin/filter-options/type_options.php' ); $html = ob_get_clean(); echo $html; } public function build_range_type_options( $filter ) { $html = ''; if( 'auto_range' === $filter->settings['type_options']['range_type'] ) { if( ! empty( $_POST['awf_filter_range_type'] ) ) { $defaults = $this->get_module_defaults( array( 'module' => $filter->module, 'taxonomy' => (object) array( 'name' => '', 'label' => '' ), 'title' => '' ) ); $filter->settings['type_options']['range_values'] = isset( $defaults['type_options']['range_values'] ) ? $defaults['type_options']['range_values'] : array( floatval( 0 ), floatval( 100 ) ); update_option( $filter->prefix. 'settings', $filter->settings ); } $html .= $this->build_auto_range( $filter ); } elseif( 'custom_range' === $filter->settings['type_options']['range_type'] ) { $html .= $this->build_custom_range( $filter ); } else { $html .= $this->build_taxonomy_range( $filter ); return $html; } $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; return $html; } protected function build_auto_range( $filter ) { $esc_html_fn = 'esc_html__'; $esc_attr_fn = 'esc_attr__'; $segments_count = count( $filter->settings['type_options']['range_values'] ) - 1; $range_min = $filter->settings['type_options']['range_values'][0]; $range_max = $filter->settings['type_options']['range_values'][$segments_count]; $html = <<
HTML; return $html; } protected function build_custom_range( $filter ) { $html = '
'; foreach( $filter->settings['type_options']['range_values'] as $i => $value ) { $html .= '
'; $html .= '
'; } $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; return $html; } private function build_show_range_btn( $filter ) { $html = '
'; $html .= 'settings['style_options']['show_range_btn'] ) ) { $html .= ' checked="checked"'; } $html .= '>'; $html .= ''; $html .= ''; $html .= '
'; return $html; } public function build_style_options( $filter, $type = null ) { if( is_null( $type ) ) { $type = $filter->settings['type']; } else { if( ! in_array( $filter->settings['style'], $this->filter_types[$type]['styles'] ) ) { $filter->settings['style'] = null; } } if( empty( $type ) || ! isset( $this->filter_types[$type] ) ) { return; } if( isset( $this->filter_style_limitations[$filter->module] ) ) { $styles = array_intersect( $this->filter_types[$type]['styles'], $this->filter_style_limitations[$filter->module][$type] ) ; } else { $styles = $this->filter_types[$type]['styles']; } if( is_null( $filter->settings['style'] ) ) { $filter->settings['style'] = reset( $styles ); } $select_html = ''; $select_html .= ''; $options_html .= ''; return '
' . $select_html . '
' . $options_html; } private function get_style_options_html( $filter, $style ) { $html = ''; $method = 'build_' . str_replace( '-', '_', $style ) . '_options_html'; if( method_exists( $this, $method ) ) { $html .= $this->{$method}( $filter ); } return $html; } public function build_icons_options_html( $filter ) { if( isset( $filter->settings['style_options']['icons'] ) ) { $icons = $filter->settings['style_options']['icons']; $solid_icons_class = $filter->settings['style_options']['solid']; $solid_icons = array_map( function( $is_solid ) { if( ! empty( $is_solid ) ) { return ' checked="checked"'; } return ''; }, $solid_icons_class ); } else { $icons = array( '', '', '', '' ); $solid_icons = $solid_icons_class = array( '', '', '', ''); } $html = '
'; $html .= '

' . esc_html__( 'Set icons', 'annasta-filters' ) . '

'; $html .= ''; $unselected_id = $filter->prefix . 'unselected_icon'; $html .= ''; $unselected_hover_id = $filter->prefix . 'unselected_icon_hover'; $html .= ''; $selected_id = $filter->prefix . 'selected_icon'; $html .= ''; $selected_hover_id = $filter->prefix . 'selected_icon_hover'; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= '
'; $html .= '
'; $html .= '

' . esc_html__( 'Preview', 'annasta-filters' ) . '

'; $preview_terms = $filter->get_unexcluded_filter_terms(); foreach( $preview_terms as $i => $term ) { if( $i === 6 ) { break; } $html .= ''; } $html .= '
'; $html .= '
'; $html .= '

' . esc_html__( 'Click an icon to copy to clipboard, then paste to the chosen box', 'annasta-filters' ); $html .= '' . '

'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; return $html; } public function build_colours_options_html( $filter ) { $terms_by_parent = $filter->build_terms_by_parent( $filter->get_filter_terms() ); $first_parent = 0; $html = ''; $html .= ''; $html .= $this->build_terms_colours_list( $filter, $first_parent, $terms_by_parent ); $html .= '
'; return $html; } protected function build_terms_colours_list( $filter, $parent_id = 0, $terms_by_parent ) { $terms_html = ''; foreach ( $terms_by_parent[$parent_id] as $term ) { if( in_array( $term->term_id, $filter->settings['excluded_items'] ) ) continue; $terms_html .= ''; $terms_html .= '' . $term->name . ''; $terms_html .= ''; $terms_html .= ''; $terms_html .= ''; $terms_html .= ''; if( isset( $terms_by_parent[$term->term_id] ) ) { $terms_html .= $this->build_terms_colours_list( $filter, $term->term_id, $terms_by_parent ); } } return $terms_html; } public function build_range_slider_options_html( $filter ) { $html = '
'; if( in_array( $filter->settings['type_options']['range_type'], array( 'auto_range', 'custom_range' ) ) ) { $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; } $html .= $this->build_show_range_btn( $filter ); $html .= '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; if( in_array( $filter->settings['type_options']['range_type'], array( 'auto_range', 'taxonomy_range' ) ) ) { $html .= ''; } if( ! empty( $filter->settings['type_options']['range_values'] ) && count( $filter->settings['type_options']['range_values'] ) > 1 ) { $html .= '
settings['style_options']['step'] ) ? '1' : esc_attr( $filter->settings['style_options']['step'] ) ) . '"'; if( 'taxonomy_range' === $filter->settings['type_options']['range_type'] ) { $html .= ' data-taxonomy-range="1"'; $html .= ' data-labels="' . esc_attr( implode( '_+_', $filter->settings['type_options']['range_labels'] ) ) . '"'; if( ! empty( $filter->settings['type_options']['range_labels'] ) ) { $html .= esc_attr( implode( '_+_', $filter->settings['type_options']['range_labels'] ) ); } $html .= '"'; $html .= ' data-values="' . implode( '_+_', $filter->settings['type_options']['range_values'] ) . '"'; } else { $formatted_values = array(); $labels = array(); $prefix = empty( $filter->settings['style_options']['value_prefix'] ) ? '' : $filter->settings['style_options']['value_prefix']; $postfix = empty( $filter->settings['style_options']['value_postfix'] ) ? '' : $filter->settings['style_options']['value_postfix']; $decimals = empty( $filter->settings['type_options']['decimals'] ) ? 0 : $filter->settings['type_options']['decimals']; $decimal_separator = wc_get_price_decimal_separator(); $thousand_separator = wc_get_price_thousand_separator(); foreach( $filter->settings['type_options']['range_values'] as $value ) { $formatted_value = number_format( $value, $decimals, $decimal_separator, $thousand_separator ); $formatted_values[] = $formatted_value; $labels[] = $prefix . $formatted_value . $postfix; } $html .= ' data-labels="' . esc_attr( implode( '_+_', $labels ) ) . '"'; $html .= ' data-values="' . implode( '_+_', $formatted_values ) . '"'; } $html .= '>'; $html .= '
'; } return $html; } public function build_excluded_terms( $filter ) { $terms = $filter->get_filter_terms(); $terms_by_parent = $filter->build_terms_by_parent( $terms ); $terms_by_id = array(); foreach( $terms as $term ) { $terms_by_id[$term->term_id] = $term; } /* Cleanup excluded terms array */ $deleted_terms = array_diff( $filter->settings['excluded_items'], array_keys( $terms_by_id ) ); if( ! empty( $deleted_terms ) ) { $filter->settings['excluded_items'] = array_diff( $filter->settings['excluded_items'], $deleted_terms ); update_option( $filter->prefix. 'settings', $filter->settings ); } /* endof Cleanup excluded terms array */ if( empty( $terms ) ) return __( 'This filter has no terms', 'annasta-filters' ); $first_parent = 0; $html = ''; foreach( $filter->settings['excluded_items'] as $ei ) { if( isset( $terms_by_id[$ei] ) ) { $html .= ''; $html .= ''; $html .= ''; } } $html .= ''; $html .= ''; $html .= '
' . $terms_by_id[$ei]->name . '
'; return $html; } protected function build_excluded_terms_select( $filter, $parent_id = 0, $terms_by_parent, $indentation = '' ) { $options_html = ''; foreach ( $terms_by_parent[$parent_id] as $term ) { if( in_array( $term->term_id, $filter->settings['excluded_items'] ) ) continue; $options_html .= ''; if( isset( $terms_by_parent[$term->term_id] ) ) { $options_html .= $this->build_excluded_terms_select( $filter, $term->term_id, $terms_by_parent, $indentation . '  ' ); } } return $options_html; } public function build_ppp_values_list( $filter, $ppp_default ) { $html = ''; foreach( $filter->settings['ppp_values'] as $value => $label ) { $html .= ''; $html .= ''; if( -1 !== $value ) { $html .= $value; } $html .= ' ' . esc_html( $label ); $html .= ''; $html .= ''; if( $value === $ppp_default ) { $html .= ''; } $html .= ''; $html .= ''; $html .= ''; } return $html; } public function awf_display_preset_btns( $preset_id, $admin_url ) {} public function awf_display_presets_list_footer( $admin_url = '' ) { echo sprintf( wp_kses( __( 'Upgrade to annasta Woocommerce Product Filters Premium to manage multiple presets!', 'annasta-filters' ), array( 'a' => array( 'href' => array() ), 'strong' => array() ) ), esc_url( a_w_f_fs()->get_upgrade_url() ) ); } protected function get_module_defaults( $filter_data ) { $method = 'get_' . $filter_data['module'] . '_defaults'; if( method_exists( $this, $method ) ) { return $this->$method( $filter_data ); } return array(); } protected function get_taxonomy_defaults( $filter_data ) { $settings = array( 'taxonomy' => $filter_data['taxonomy']->name, 'title' => $filter_data['taxonomy']->label, 'show_title' => true, 'show_active' => false, 'type' => 'multi', 'style' => 'icons', 'style_options' => array(), 'show_in_row' => false, 'show_search' => false, 'excluded_items' => array(), 'sort_by' => 'admin', 'sort_order' => 'none', 'height_limit' => '0', 'show_count' => false, ); if( $filter_data['taxonomy']->hierarchical ) { $settings = array_merge( array_slice( $settings, 0, 8, true), array( 'children_collapsible' => false, 'children_collapsible_on' => false ), array_slice( $settings, 8, count( $settings ) - 1, true) ); } return $settings; } protected function get_search_defaults( $filter_data ) { return( array( 'title' => $filter_data['title'], 'show_title' => true, 'show_active' => false, 'type' => null, 'style' => null, 'style_options' => array(), 'height_limit' => '0', ) ); } protected function get_price_defaults( $filter_data ) { return( array( 'title' => $filter_data['title'], 'show_title' => true, 'show_active' => false, 'type' => 'range', 'type_options' => array( 'range_type' => 'auto_range', 'range_values' => array( floatval( 0 ), floatval( 100 ) ) ), 'style' => 'range-slider', 'style_options' => array(), 'show_in_row' => false, 'height_limit' => '0', ) ); } protected function get_stock_defaults( $filter_data ) { return( array( 'title' => $filter_data['title'], 'show_title' => true, 'show_active' => false, 'type' => 'single', 'style' => 'radios', 'style_options' => array(), 'show_in_row' => false, 'show_search' => false, 'excluded_items' => array(), 'height_limit' => '0', ) ); } protected function get_featured_defaults( $filter_data ) { return( array( 'title' => $filter_data['title'], 'show_title' => true, 'type' => 'multi', 'style' => 'checkboxes', 'style_options' => array(), 'height_limit' => '0', ) ); } protected function get_onsale_defaults( $filter_data ) { return( array( 'title' => $filter_data['title'], 'show_title' => true, 'type' => 'multi', 'style' => 'checkboxes', 'style_options' => array(), 'height_limit' => '0', ) ); } protected function get_rating_defaults( $filter_data ) { return( array( 'title' => $filter_data['title'], 'show_title' => true, 'show_active' => false, 'type' => 'range', 'type_options' => array( 'range_type' => 'custom_range', 'range_values' => array( round( floatval( 1 ), 2, PHP_ROUND_HALF_UP ), round( floatval( 2 ), 2, PHP_ROUND_HALF_UP ), round( floatval( 3 ), 2, PHP_ROUND_HALF_UP ), round( floatval( 4 ), 2, PHP_ROUND_HALF_UP ), round( floatval( 5 ), 2, PHP_ROUND_HALF_UP ), round( floatval( 5.01 ), 2, PHP_ROUND_HALF_UP ) ), 'precision' => round( floatval( 0.01 ), 2, PHP_ROUND_HALF_UP ), 'decimals' => intval( 0 ), ), 'style' => 'radios', 'style_options' => array( 'step' => intval( 1 ) ), 'show_in_row' => false, 'show_search' => false, 'height_limit' => '0', ) ); } protected function get_ppp_defaults( $filter_data ) { return( array( 'title' => $filter_data['title'], 'show_title' => true, 'show_active' => false, 'reset_all' => false, 'type' => 'single', 'style' => 'radios', 'style_options' => array(), 'ppp_values' => array( 12 => __( 'products per page', 'annasta-filters' ) ), 'show_in_row' => false, 'show_search' => false, 'height_limit' => '0', ) ); } public function get_filter_title( $filter_name ) { switch( $filter_name ) { case 'search': return esc_html__( 'Products Search', 'annasta-filters' ); break; case 'ppp': return esc_html__( 'Products Per Page', 'annasta-filters' ); break; case 'stock': return esc_html__( 'Products Stock Status Filter', 'annasta-filters' ); break; case 'price': return esc_html__( 'Products Price Filter', 'annasta-filters' ); break; case 'featured': return esc_html__( 'Featured Products Filter', 'annasta-filters' ); break; case 'onsale': return esc_html__( 'Products on Sale Filter', 'annasta-filters' ); break; case 'rating': return esc_html__( 'Products Rating Filter', 'annasta-filters' ); break; case 'orderby': return esc_html__( 'Products Sort (Orderby) Control', 'annasta-filters' ); break; case 'meta': return esc_html__( 'Custom Meta Filter', 'annasta-filters' ); break; default: return ''; break; } } public function get_preset_settings( $preset ) { return array( array( 'id' => 'awf_preset_settings_section_1', 'type' => 'title', 'name' => 0 === $preset->id ? '' : sprintf( esc_html__( 'Preset id: %1$s', 'annasta-filters' ), $preset->id ), ), array( 'id' => 'awf_preset_' . $preset->id . '_name', 'type' => 'text', 'name' => __( 'Preset name', 'annasta-filters' ), 'default' => $preset->name, ), array( 'id' => 'awf_preset_' . $preset->id . '_title', 'type' => 'text', 'name' => __( 'Preset title', 'annasta-filters' ), 'default' => $preset->title, 'desc_tip' => __( 'This will show as your filters\' header. Leave blank if not needed.', 'annasta-filters' ) ), array( 'id' => 'awf_preset_' . $preset->id . '_show_title_badges', 'type' => 'checkbox', 'name' => __( 'Show active filters', 'annasta-filters' ), 'default' => $preset->show_title_badges, 'desc_tip' => __( 'This will display active filter badges under the preset title, or on top of the preset if the title is omitted.', 'annasta-filters' ) ), array( 'id' => 'awf_preset_' . $preset->id . '_reset_btn', 'type' => 'select', 'name' => __( 'Reset all button', 'woocommerce' ), 'default' => $preset->reset_btn, 'options' => array( 'none' => __( 'None', 'annasta-filters' ), 'top' => __( 'At the top of the preset', 'annasta-filters' ), 'bottom' => __( 'At the bottom of the preset', 'annasta-filters' ), 'both' => __( 'Both at the top and at the bottom', 'annasta-filters' ) ), 'desc' => __( 'This controls the display of \'Clear all\' buttons that will reset all the existing active filters.', 'annasta-filters' ), 'desc_tip' => true, ), array( 'id' => 'awf_preset_' . $preset->id . '_button_on', 'type' => 'radio', 'name' => __( 'Filtering Style', 'annasta-filters' ), 'default' => $preset->button_on, 'options' => array( 'no' => __( 'Ιnstant filtering', 'annasta-filters' ), 'yes' => __( 'Filter button', 'annasta-filters' ) ), 'desc' => __( 'Choose between instant filtering (when filter is applied straight upon clicking the filtering option), or filters being applied after submitting the Filter button.', 'annasta-filters' ), 'desc_tip' => true ), array( 'id' => 'awf_preset_' . $preset->id . '_ajax_on', 'type' => 'checkbox', 'name' => __( 'Enable Ajax', 'annasta-filters' ), 'default' => $preset->ajax_on, 'desc' => __( 'With this option enabled only the products list part of the page will be reloading when appying filters.', 'annasta-filters' ), 'desc_tip' => true ), array( 'type' => 'sectionend', 'id' => 'awf_preset_settings_section_1' ), ); } public function get_styles_settings() { $custom_styles_select = array( 'none' => __( 'Default', 'annasta-filters' ), ); return array( array( 'id' => 'awf_styles_settings_tab', 'type' => 'title', 'name' => __( 'Style Settings', 'annasta-filters' ), ), array( 'id' => 'awf_pretty_scrollbars', 'type' => 'checkbox', 'name' => __( 'Enable pretty scrollbars', 'annasta-filters' ), 'default' => get_option( 'awf_pretty_scrollbars', 'no' ), 'desc_tip' => __( 'This will replace standard browser scrollbars in filters lists with limited height.', 'annasta-filters' ), ), array( 'id' => 'awf_custom_style', 'type' => 'select', 'options' => $custom_styles_select, 'name' => __( 'Filters Style', 'annasta-filters' ), 'default' => get_option( 'awf_custom_style', 'none' ), ), array( 'type' => 'sectionend', 'id' => 'awf_styles_settings_tab' ), ); } public function get_plugin_settings() { $wp_pages_options = array(); $wp_pages = get_all_page_ids(); $wc_shop_page = wc_get_page_id( 'shop' ); foreach( $wp_pages as $page_id ) { if( intval( $page_id ) === intval( $wc_shop_page ) ) { continue; } $wp_pages_options[$page_id] = get_the_title( $page_id ); } return array( array( 'id' => 'awf_plugin_settings_tab', 'type' => 'title', 'name' => __( 'Plugin Settings', 'annasta-filters' ), ), array( 'id' => 'awf_include_children_on', 'type' => 'checkbox', 'name' => __( 'Include subterms\' products', 'annasta-filters' ), 'default' => get_option( 'awf_include_children_on', 'yes' ), 'desc_tip' => __( 'When a parent term of a hierarchical taxonomy is selected, include products belonging to its children terms (for example, subcategories) in the filtered results.', 'annasta-filters' ) ), array( 'id' => 'awf_shortcode_pages', 'type' => 'multiselect', 'options' => $wp_pages_options, 'name' => __( 'Shortcodes pages', 'annasta-filters' ), 'default' => get_option( 'awf_shortcode_pages', array() ), 'desc_tip' => __( 'Declare the pages at which you wish your filters to work with shortcodes. By default clicking a filter at pages other than shop or category page will redirect the user to the main shop page. Use this in conjunction with registering presets for display on the same pages.', 'annasta-filters' ), 'class' => 'chosen_select' ), array( 'id' => 'awf_force_products_display_on', 'type' => 'checkbox', 'name' => __( 'Force products display', 'annasta-filters' ), 'default' => get_option( 'awf_force_products_display_on', 'yes' ), 'desc_tip' => __( 'This option disables categories display on shop pages and subcategories display on product category pages to ensure the accuracy of the filtered results. You can disable it if you are using filters exclusively on shortcode-created pages.', 'annasta-filters' ) ), array( 'id' => 'awf_products_html_wrapper', 'type' => 'text', 'name' => __( 'Products list html container', 'annasta-filters' ), 'default' => get_option( 'awf_products_html_wrapper', '#main' ), 'desc_tip' => __( 'If your template uses non-standard html structure, enter your template-specific products list html container here. #main is the WooCommerce default.', 'annasta-filters' ), ), array( 'type' => 'sectionend', 'id' => 'awf_plugin_settings_tab' ), ); } public function generate_styles_css() { $css = '/* annasta Woocommerce Product Filters autogenerated style options css */'; foreach( A_W_F::$presets as $preset_id => $preset ) { foreach( $preset['filters'] as $filter_id => $position ) { $filter = new A_W_F_filter( $preset_id, $filter_id ); if( ! empty( $filter->settings['height_limit'] ) ) { $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container {position:relative;'; $css .= 'height:' . $filter->settings['height_limit'] . 'px;overflow:hidden;'; if ( 'yes' !== get_option( 'awf_pretty_scrollbars' ) ) { $css .= 'padding-right:0.5em;overflow-y:auto;'; } $css .= '}'; } if( ! empty( $filter->settings['show_in_row'] ) ) { $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container ul {display:flex;flex-flow:row wrap;margin:0;align-items:stretch;justify-content:space-between;}'; $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container > ul > ul > * {margin-bottom: 0;}'; $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container ul > * {margin: 0 0 0.5em 0;flex-grow:1;}'; if( isset( $filter->settings['style_options']['hide_label'] ) ) { $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container li {flex: 1.2 0.8 25%;text-align:center;}'; $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container label::before {margin:0;}'; } } if( 'icons' === $filter->settings['style'] && isset( $filter->settings['style_options']['icons'] ) ) { $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container.awf-style-icons label::before {'; $css .= 'content:"' . $filter->settings['style_options']['icons'][0] . '";'; if( ! empty( $filter->settings['style_options']['solid'][0] ) ) { $css .= 'font-weight:900;'; } $css .= '}'; $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container.awf-style-icons .awf-filter-container:not(.awf-empty-disabled):not(.awf-hover-off) label:hover::before {'; $css .= 'content:"' . $filter->settings['style_options']['icons'][1] . '";'; if( ! empty( $filter->settings['style_options']['solid'][1] ) ) { $css .= 'font-weight:900;'; } $css .= '}'; $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container.awf-style-icons .awf-active label::before {'; $css .= 'content:"' . $filter->settings['style_options']['icons'][2] . '";'; if( ! empty( $filter->settings['style_options']['solid'][2] ) ) { $css .= 'font-weight:900;'; } $css .= '}'; $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container.awf-style-icons .awf-active:not(.awf-empty-disabled):not(.awf-hover-off) label:hover::before {'; $css .= 'content:"' . $filter->settings['style_options']['icons'][3] . '";'; if( ! empty( $filter->settings['style_options']['solid'][3] ) ) { $css .= 'font-weight:900;'; } $css .= '}'; } else if( 'colours' === $filter->settings['style'] ) { if( isset( $filter->settings['style_options']['colours'] ) ) { foreach( $filter->settings['style_options']['colours'] as $term_id => $colour ) { $css .= '.awf-filters-' . $preset_id . '-' . $filter_id . '-container label.awf-term-' . $term_id . '::after {'; $css .= 'background-color:' . $colour . ';}'; } } } if( method_exists( $this, 'generate_premium_css' ) ) { $css .= $this->generate_premium_css( $filter ); } } } $awf_uploads_folder = trailingslashit( wp_upload_dir()['basedir'] ) . 'annasta-filters'; if( wp_mkdir_p( $awf_uploads_folder ) ) { file_put_contents( $awf_uploads_folder . '/style-options.css', $css ); } } /* Clear product counts cache on product updates and/or deletes */ public function on_product_update( $product_id ) { $this->clear_product_counts_cache(); } public function on_product_deletion( $product_id ) { if( 'product' === get_post_type( $product_id ) && 'trash' !== get_post_status( $product_id ) ) { $this->clear_product_counts_cache(); } } public function on_product_trashing( $product_id ) { if( 'product' === get_post_type( $product_id ) ) { $this->clear_product_counts_cache(); } } public function on_product_untrashing() { if( 'product' === $GLOBALS['post_type'] ) { $this->clear_product_counts_cache(); } } public function on_product_cat_created( $term_id, $taxonomy_id ) { $this->clear_product_counts_cache(); } public function on_product_cat_deleted( $term_id, $taxonomy_id, $deleted_term, $object_ids ) { $this->clear_product_counts_cache(); } public function clear_product_counts_cache() { global $wpdb; $transient_name = '_transient_awf_counts_%'; $results = array(); $sql = "SELECT `option_name` FROM $wpdb->options WHERE `option_name` LIKE '%s'"; $transients = $wpdb->get_results( $wpdb->prepare( $sql, $transient_name ), ARRAY_A ); if ( $transients && ! is_wp_error( $transients ) && is_array( $transients ) ) { foreach ( $transients as $transient ) { if ( is_array( $transient ) ) { $transient = current( $transient ); } $results[$transient] = delete_transient( str_replace( '_transient_', '', $transient ) ); } } //error_log('awf counts cache cleared: ' . count( $results ) . ' transients removed.' ); } /* endof Clear product counts cache on product updates and/or deletes */ private final function __clone() {} // prevent cloning private final function __wakeup() {} // prevent serialization public static function get_instance() { if( is_null( self::$instance ) ) { $called_class = get_called_class(); self::$instance = new $called_class; } return self::$instance; } /** Helper Functions */ protected function get_sanitized_checkbox_setting( $filter, $setting, $no = false ) { $setting_name = $filter->prefix . $setting; if( isset( $_POST[$setting_name] ) ) { return ( 'yes' === $_POST[$setting_name] ); } else { return $no; } } public function display_admin_notice( $msg, $type = 'error', $dismissable = ' is-dismissible' ) { /* $type can take the following values: error, warning, info, success */ echo ('

' . esc_html( $msg ) . '

'); } public function build_select_html( $options ) { $html = ' $label ) { $html .= '